16 Commits

Author SHA1 Message Date
Alex Shevchuk
62ce86f1c4 updated stg pots
Some checks failed
Go Linter / Build golang services (api_gateway) (push) Has been cancelled
Go Linter / Tag Commit (push) Has been cancelled
Go Linter / Push Docker Images (api_gateway) (push) Has been cancelled
Go Linter / Run golangci-lint (api_gateway) (push) Has been cancelled
2025-09-22 13:01:59 +03:00
Alex Shevchuk
ce7aecf8be updated stg deploy
Some checks failed
Go Linter / Build golang services (api_gateway) (push) Has been cancelled
Go Linter / Tag Commit (push) Has been cancelled
Go Linter / Push Docker Images (api_gateway) (push) Has been cancelled
Go Linter / Run golangci-lint (api_gateway) (push) Has been cancelled
2025-09-22 12:58:13 +03:00
Alex Shevchuk
f64936e0f3 77 СЕМЬ
All checks were successful
Go Linter / Run golangci-lint (api_gateway) (push) Successful in 3m56s
Go Linter / Tag Commit (push) Successful in 15s
Go Linter / Build golang services (api_gateway) (push) Successful in 4m15s
Go Linter / Push Docker Images (api_gateway) (push) Successful in 5m0s
2025-09-17 16:28:57 +03:00
Alex Shevchuk
a11e3b3a82 77 СЕМЬ
All checks were successful
Go Linter / Run golangci-lint (api_gateway) (push) Successful in 3m51s
Go Linter / Tag Commit (push) Successful in 12s
Go Linter / Build golang services (api_gateway) (push) Successful in 4m15s
Go Linter / Push Docker Images (api_gateway) (push) Successful in 8m11s
2025-09-17 16:13:32 +03:00
Alex Shevchuk
9fb046223c 76 ШЕСТЬ
All checks were successful
Go Linter / Run golangci-lint (api_gateway) (push) Successful in 3m57s
Go Linter / Push Docker Images (api_gateway) (push) Successful in 29s
Go Linter / Build golang services (api_gateway) (push) Successful in 2m21s
Deploy Production / Deploy to Staging (push) Has been skipped
Go Linter / Tag Commit (push) Successful in 9s
2025-09-17 15:45:45 +03:00
Alex Shevchuk
0d9dc14131 75
All checks were successful
Go Linter / Run golangci-lint (api_gateway) (push) Has been skipped
Deploy Production / Deploy to Staging (push) Has been skipped
Go Linter / Push Docker Images (api_gateway) (push) Successful in 32s
Go Linter / Build golang services (api_gateway) (push) Has been skipped
Go Linter / Tag Commit (push) Has been skipped
2025-09-17 15:43:30 +03:00
Alex Shevchuk
cf4a0ac7b7 74
All checks were successful
Go Linter / Run golangci-lint (api_gateway) (push) Has been skipped
Deploy Production / Deploy to Staging (push) Has been skipped
Go Linter / Build golang services (api_gateway) (push) Has been skipped
Go Linter / Tag Commit (push) Has been skipped
Go Linter / Push Docker Images (api_gateway) (push) Successful in 21s
2025-09-17 15:41:18 +03:00
Alex Shevchuk
cb4dd943bc 74
All checks were successful
Go Linter / Run golangci-lint (api_gateway) (push) Has been skipped
Deploy Production / Deploy to Staging (push) Has been skipped
Go Linter / Build golang services (api_gateway) (push) Has been skipped
Go Linter / Tag Commit (push) Has been skipped
Go Linter / Push Docker Images (api_gateway) (push) Successful in 29s
2025-09-17 15:39:48 +03:00
Alex Shevchuk
9d4b138190 73
All checks were successful
Go Linter / Run golangci-lint (api_gateway) (push) Has been skipped
Deploy Production / Deploy to Staging (push) Has been skipped
Go Linter / Build golang services (api_gateway) (push) Has been skipped
Go Linter / Tag Commit (push) Has been skipped
Go Linter / Push Docker Images (api_gateway) (push) Successful in 23s
2025-09-17 15:35:57 +03:00
Alex Shevchuk
e3262d588c 72
All checks were successful
Go Linter / Tag Commit (push) Successful in 14s
Deploy Production / Deploy to Staging (push) Has been skipped
Go Linter / Run golangci-lint (api_gateway) (push) Successful in 3m47s
Go Linter / Build golang services (api_gateway) (push) Successful in 4m15s
Go Linter / Push Docker Images (api_gateway) (push) Successful in 5m4s
2025-09-17 15:24:08 +03:00
Alex Shevchuk
33229f1eb7 71
Some checks failed
Go Linter / Tag Commit (push) Successful in 13s
Go Linter / Build golang services (api_gateway) (push) Successful in 3m2s
Deploy Production / Deploy to Staging (push) Has been skipped
Go Linter / Run golangci-lint (api_gateway) (push) Successful in 3m52s
Go Linter / Push Docker Images (api_gateway) (push) Failing after 1m45s
2025-09-17 15:11:39 +03:00
Alex Shevchuk
5d10849397 71
Some checks failed
Go Linter / Tag Commit (push) Successful in 28s
Deploy Production / Deploy to Staging (push) Has been skipped
Go Linter / Run golangci-lint (api_gateway) (push) Successful in 4m13s
Go Linter / Push Docker Images (api_gateway) (push) Failing after 1m57s
Go Linter / Build golang services (api_gateway) (push) Failing after 2m5s
2025-09-17 14:59:21 +03:00
Alex Shevchuk
f46b07c210 71
Some checks failed
Deploy Production / Deploy to Staging (push) Has been skipped
Go Linter / Run golangci-lint (api_gateway) (push) Failing after 42s
Go Linter / Build golang services (api_gateway) (push) Has been skipped
Go Linter / Tag Commit (push) Has been skipped
Go Linter / Push Docker Images (api_gateway) (push) Has been skipped
2025-09-17 14:56:52 +03:00
Alex Shevchuk
f5310dd516 71
Some checks failed
Go Linter / Tag Commit (push) Has been skipped
Deploy Production / Deploy to Staging (push) Has been skipped
Go Linter / Run golangci-lint (api_gateway) (push) Failing after 2m39s
Go Linter / Build golang services (api_gateway) (push) Has been skipped
Go Linter / Push Docker Images (api_gateway) (push) Has been skipped
2025-09-17 14:37:10 +03:00
Alex Shevchuk
61fc0d2747 71
Some checks failed
Deploy Production / Deploy to Staging (push) Has been skipped
Go Linter / Run golangci-lint (api_gateway) (push) Failing after 2m31s
Go Linter / Build golang services (api_gateway) (push) Has been skipped
Go Linter / Tag Commit (push) Has been skipped
Go Linter / Push Docker Images (api_gateway) (push) Has been skipped
2025-09-17 14:32:06 +03:00
Alex Shevchuk
03372d7f9b 70
Some checks failed
Go Linter / Tag Commit (push) Successful in 13s
Deploy Production / Deploy to Staging (push) Has been skipped
Go Linter / Run golangci-lint (api_gateway) (push) Successful in 2m43s
Go Linter / Push Docker Images (api_gateway) (push) Failing after 28s
Go Linter / Build golang services (api_gateway) (push) Successful in 1m46s
2025-09-14 23:01:46 +03:00
27 changed files with 15607 additions and 113 deletions

View File

@@ -0,0 +1,22 @@
env: "local"
host: "0.0.0.0"
port: 8000
broker:
notificationsQueueName: "molva-notification"
cache:
readOnly: false
dialTimeout: 1h
poolSize: 10
defaultTtl: 1h
rootCaFilePath: "/etc/.redis/YandexInternalRootCA.crt"
s3Storage:
bucket: "molva-staging" # TODO: change to prod bucket
defaultLinkTtl: 1h
database:
schema: test_schema # TODO: change to prod schema
sslmode: require
rootCaFilePath: "/etc/.postgres/YandexInternalRootCA.crt"

View File

@@ -19,4 +19,4 @@ s3Storage:
database: database:
schema: test_schema schema: test_schema
sslmode: require sslmode: require
rootCaFilePath: "/etc/.redis/YandexInternalRootCA.crt" rootCaFilePath: "/etc/.postgres/YandexInternalRootCA.crt"

View File

@@ -25,17 +25,21 @@ jobs:
uses: actions/checkout@v3 uses: actions/checkout@v3
- name: Set up Go - name: Set up Go
uses: actions/setup-go@v4 uses: actions/setup-go@v6
with: with:
go-version: 1.23 go-version: '1.24.x'
check-latest: true
- name: Enable Go toolchain auto
run: echo "GOTOOLCHAIN=auto" >> $GITHUB_ENV
- name: Install golangci-lint - name: Install golangci-lint
run: | run: |
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.62.2 echo "Installing golangci-lint v1.62.2 with $(go version)"
GOBIN=$(go env GOPATH)/bin go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.62.2
- name: Run golangci-lint - name: Run golangci-lint
run: | run: |
go clean -modcache
go mod tidy go mod tidy
golangci-lint run -c ./.golangci-lint.yaml --fix=false --color=always golangci-lint run -c ./.golangci-lint.yaml --fix=false --color=always
@@ -59,81 +63,13 @@ jobs:
go-version: 1.24 go-version: 1.24
- name: Build golang services - name: Build golang services
env:
HOST: ${{ github.event.base_ref == 'refs/heads/release' && secrets.HOST_STG || secrets.HOST_PROD }}
run: | run: |
go mod tidy go mod tidy
SWAGGER_HOST=${HOST} make docs
CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o main cmd/main.go CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o main cmd/main.go
push:
name: Push Docker Images
runs-on: ubuntu-22.04
needs: lint
if: ${{ gitea.ref == 'refs/heads/master' || gitea.ref == 'refs/heads/release' }}
strategy:
matrix:
project:
- api_gateway
steps:
- name: Checkout репозитория
uses: actions/checkout@v4
- name: Extract Git metadata
id: git-metadata
env:
REPO: ${{ github.repository }}
run: |
GIT_SHA=$(git rev-parse --short HEAD)
GIT_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo 'none')
TARGET_ENV=${{ github.ref == 'refs/heads/release' && 'staging' || 'production' }}
echo "GIT_SHA=${GIT_SHA}" >> $GITHUB_OUTPUT
echo "GIT_TAG=${GIT_TAG}" >> $GITHUB_OUTPUT
echo "TARGET_ENV=${TARGET_ENV}" >> $GITHUB_OUTPUT
echo "REPO_NAME=$(echo $REPO | cut -d'/' -f2)" >> $GITHUB_OUTPUT
- name: Login to Docker Registry
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Extract image metadata
id: docker-metadata
needs: git-metadata
env:
REGISTRY: hub.docker.com
REPO_NAME: ${{ steps.git-metadata.outputs.REPO_NAME }}
TARGET_ENV: ${{ steps.git-metadata.outputs.TARGET_ENV }}
GIT_TAG: ${{ steps.git-metadata.outputs.GIT_TAG }}
GIT_SHA: ${{ steps.git-metadata.outputs.GIT_SHA }}
run: |
IMAGE_TAG=$TARGET_ENV-$($GIT_TAG != 'none' && echo $GIT_TAG || echo $GIT_SHA)
echo "IMAGE_NAME=molvaapp/${{ steps.git-metadata.outputs.REPO_NAME }}" >> $GITHUB_OUTPUT
echo "IMAGE_TAG=${IMAGE_TAG}" >> $GITHUB_OUTPUT
- name: Build and Push Docker Image
needs: docker-metadata
env:
IMAGE_NAME: ${{ steps.docker-metadata.outputs.IMAGE_NAME }}
IMAGE_TAG: ${{ steps.docker-metadata.outputs.IMAGE_TAG }}
CONFIG_FILE: .build/config/${{ steps.git-metadata.outputs.TARGET_ENV }}.yaml
run: |
docker build \
--build-arg BUILD_LDFLAGS="-w -s" \
--build-arg CONFIG_FILE_PATH=$CONFIG_FILE \
-t $IMAGE_NAME:$IMAGE_TAG \
-t $IMAGE_NAME:latest \
.
docker tag $IMAGE_NAME:$IMAGE_TAG $IMAGE_NAME:latest
docker push $IMAGE_NAME:$IMAGE_TAG
docker push $IMAGE_NAME:latest
echo "Pushed image $IMAGE_NAME:$IMAGE_TAG and :latest"
tag: tag:
name: Tag Commit name: Tag Commit
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
@@ -186,3 +122,87 @@ jobs:
git tag ${{ steps.get-latest-tag.outputs.NEW_TAG }} git tag ${{ steps.get-latest-tag.outputs.NEW_TAG }}
git push origin ${{ steps.get-latest-tag.outputs.NEW_TAG }} git push origin ${{ steps.get-latest-tag.outputs.NEW_TAG }}
echo "Successfully pushed tag: ${{ steps.get-latest-tag.outputs.NEW_TAG }}" echo "Successfully pushed tag: ${{ steps.get-latest-tag.outputs.NEW_TAG }}"
push:
name: Push Docker Images
runs-on: ubuntu-22.04
needs:
lint
tag
if: ${{ gitea.ref == 'refs/heads/master' || gitea.ref == 'refs/heads/release' }}
strategy:
matrix:
project:
- api_gateway
steps:
- name: Checkout репозитория
uses: actions/checkout@v4
with:
fetch-depth: 0
fetch-tags: true
- name: Extract Git metadata
id: git-metadata
env:
REPO: ${{ github.repository }}
run: |
git fetch --tags --force
GIT_SHA=$(git rev-parse --short HEAD)
GIT_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "none")
TARGET_ENV=${{ github.ref == 'refs/heads/release' && 'staging' || 'production' }}
echo "GIT_SHA=${GIT_SHA}" >> $GITHUB_OUTPUT
echo "GIT_TAG=${GIT_TAG}" >> $GITHUB_OUTPUT
echo "TARGET_ENV=${TARGET_ENV}" >> $GITHUB_OUTPUT
echo "REPO_NAME=$(echo $REPO | cut -d'/' -f2)" >> $GITHUB_OUTPUT
- name: Login to Docker Registry
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Extract image metadata
id: docker-metadata
needs: git-metadata
env:
REGISTRY: hub.docker.com
REPO_NAME: ${{ steps.git-metadata.outputs.REPO_NAME }}
TARGET_ENV: ${{ steps.git-metadata.outputs.TARGET_ENV }}
GIT_TAG: ${{ steps.git-metadata.outputs.GIT_TAG }}
GIT_SHA: ${{ steps.git-metadata.outputs.GIT_SHA }}
run: |
if [ "$GIT_TAG" != "none" ]; then
IMAGE_TAG="${TARGET_ENV}-${GIT_TAG}"
else
IMAGE_TAG="${TARGET_ENV}-${GIT_SHA}"
fi
echo "IMAGE_NAME=molvaapp/${{ steps.git-metadata.outputs.REPO_NAME }}" >> $GITHUB_OUTPUT
echo "IMAGE_TAG=${IMAGE_TAG}" >> $GITHUB_OUTPUT
- name: Build and Push Docker Image
needs: docker-metadata
env:
IMAGE_NAME: ${{ steps.docker-metadata.outputs.IMAGE_NAME }}
IMAGE_TAG: ${{ steps.docker-metadata.outputs.IMAGE_TAG }}
CONFIG_FILE: .build/config/${{ steps.git-metadata.outputs.TARGET_ENV }}.yaml
HOST: ${{ github.event.base_ref == 'refs/heads/release' && secrets.HOST_STG || secrets.HOST_PROD }}
run: |
docker build \
--build-arg BUILD_LDFLAGS="-w -s" \
--build-arg CONFIG_FILE_PATH=$CONFIG_FILE \
--build-arg SWAGGER_HOST=$HOST \
-t $IMAGE_NAME:$IMAGE_TAG \
-t $IMAGE_NAME:latest \
.
docker tag $IMAGE_NAME:$IMAGE_TAG $IMAGE_NAME:latest
docker push $IMAGE_NAME:$IMAGE_TAG
docker push $IMAGE_NAME:latest
echo "Pushed image $IMAGE_NAME:$IMAGE_TAG and :latest"

View File

@@ -18,7 +18,7 @@ on:
jobs: jobs:
deploy: deploy:
name: Deploy to ${{ inputs.environment }} name: Deploy
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
env: env:

View File

@@ -1,25 +0,0 @@
name: Deploy Production
on:
push:
branches: [master, release]
pull_request:
branches: [master, release]
jobs:
deploy_to_staging:
name: Deploy to Staging
runs-on: ubuntu-22.04
if: ${{ gitea.ref == 'refs/heads/release' }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Manual Approval Step
run: echo "Ручное подтверждение получено. Запуск деплоя..."
- name: Deployment Script (Заглушка)
run: |
echo "Здесь будет скрипт деплоя на staging"
# TODO: Реальный скрипт деплоя
echo "Симуляция деплоя..."

View File

@@ -40,7 +40,7 @@ run:
# Минимально поддерживаемая версия go. # Минимально поддерживаемая версия go.
# Mainly related to generics support in go1.18. # Mainly related to generics support in go1.18.
# Default: use Go version from the go.mod file, fallback on the env var `GOVERSION`, fallback on 1.17 # Default: use Go version from the go.mod file, fallback on the env var `GOVERSION`, fallback on 1.17
go: '1.22' go: '1.24'
# output configuration options # output configuration options
output: output:

View File

@@ -1,13 +1,20 @@
FROM golang:1.24-alpine AS builder FROM golang:1.24-alpine AS builder
ARG BUILD_LDFLAGS ARG BUILD_LDFLAGS
ARG SWAGGER_HOST=localhost:8000
WORKDIR /app WORKDIR /app
COPY go.mod go.sum ./ RUN apk add --no-cache make
COPY go.mod ./
RUN go mod download -x RUN go mod download -x
COPY . . COPY . .
RUN go mod tidy && go mod download -x
RUN SWAGGER_HOST=${SWAGGER_HOST} make docs
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="${BUILD_LDFLAGS}" -trimpath -o main ./cmd/main.go RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="${BUILD_LDFLAGS}" -trimpath -o main ./cmd/main.go
FROM alpine:3.18 AS certs FROM alpine:3.18 AS certs

View File

@@ -5,9 +5,16 @@ BUILD_DATE := $(shell date -u +'%Y-%m-%dT%H:%M:%SZ')
GIT_COMMIT := $(shell git rev-parse HEAD 2>/dev/null) GIT_COMMIT := $(shell git rev-parse HEAD 2>/dev/null)
LDFLAGS := "-s -w -X main.version=$(VERSION) -X main.commit=$(GIT_COMMIT) -X main.date=$(BUILD_DATE)" LDFLAGS := "-s -w -X main.version=$(VERSION) -X main.commit=$(GIT_COMMIT) -X main.date=$(BUILD_DATE)"
GOLANGCI_LINT_VERSION := v1.62.2 GOLANGCI_LINT_VERSION := v1.62.2
SWAG_VERSION := v1.16.2
ENV := "local" ENV := "local"
UNAME_S := $(shell uname -s) UNAME_S := $(shell uname -s)
CONFIG_PATH := .build/config/ CONFIG_PATH := .build/config/
SWAGGER_DOCS_PATH := internal/http/swagger/docs
ifeq ($(UNAME_S),Darwin)
SED_INPLACE := -i ''
else
SED_INPLACE := -i
endif
ifeq ($(OS),Windows_NT) ifeq ($(OS),Windows_NT)
CONFIG_PATH := $(subst /,\,$(CONFIG_PATH)) CONFIG_PATH := $(subst /,\,$(CONFIG_PATH))
@@ -18,7 +25,7 @@ all: lint build
## -- Dependency Management -- ## -- Dependency Management --
.PHONY: install-tools .PHONY: install-tools
install-tools: $(BIN_DIR)/golangci-lint install-tools: $(BIN_DIR)/golangci-lint $(BIN_DIR)/swag
.PHONY: $(BIN_DIR)/golangci-lint .PHONY: $(BIN_DIR)/golangci-lint
$(BIN_DIR)/golangci-lint: $(BIN_DIR)/golangci-lint:
@@ -26,12 +33,45 @@ $(BIN_DIR)/golangci-lint:
@echo "Installing golangci-lint $(GOLANGCI_LINT_VERSION)..." @echo "Installing golangci-lint $(GOLANGCI_LINT_VERSION)..."
@GOBIN=$(BIN_DIR) go install github.com/golangci/golangci-lint/cmd/golangci-lint@$(GOLANGCI_LINT_VERSION) @GOBIN=$(BIN_DIR) go install github.com/golangci/golangci-lint/cmd/golangci-lint@$(GOLANGCI_LINT_VERSION)
.PHONY: $(BIN_DIR)/swag
$(BIN_DIR)/swag:
@mkdir -p $(@D)
@echo "Installing swag $(SWAG_VERSION)..."
@GOBIN=$(BIN_DIR) go install github.com/swaggo/swag/cmd/swag@$(SWAG_VERSION)
## -- Linting -- ## -- Linting --
.PHONY: lint .PHONY: lint
lint: $(BIN_DIR)/golangci-lint lint: $(BIN_DIR)/golangci-lint
@echo "Running linter..." @echo "Running linter..."
@$(BIN_DIR)/golangci-lint run --config .golangci-lint.yaml --fix=false --color=always @$(BIN_DIR)/golangci-lint run --config .golangci-lint.yaml --fix=false --color=always
## -- Documentation --
.PHONY: docs
docs: $(BIN_DIR)/swag
@echo "Generating Swagger documentation..."
@if [ -n "$(SWAGGER_HOST)" ]; then \
echo "Using SWAGGER_HOST: $(SWAGGER_HOST)"; \
$(MAKE) .generate-swagger-with-host HOST=$(SWAGGER_HOST); \
else \
echo "Using default host: localhost:8000"; \
mkdir -p $(SWAGGER_DOCS_PATH); \
$(BIN_DIR)/swag init -g cmd/main.go -o $(SWAGGER_DOCS_PATH) --parseDependency --parseInternal; \
echo "Swagger documentation generated in $(SWAGGER_DOCS_PATH)"; \
fi
.PHONY: .generate-swagger-with-host
.generate-swagger-with-host: $(BIN_DIR)/swag
@echo "Генерация Swagger документации с host: $(HOST)"
@mkdir -p $(SWAGGER_DOCS_PATH)
@TEMP_MAIN="cmd/main_temp.go" && \
cp cmd/main.go $$TEMP_MAIN && \
ESC_HOST=$$(printf '%s\n' "$(HOST)" | sed -e 's/[\\\/&]/\\\\&/g') && \
sed $(SED_INPLACE) "s|localhost:8000|$${ESC_HOST}|g" $$TEMP_MAIN && \
$(BIN_DIR)/swag init -g $$TEMP_MAIN -o $(SWAGGER_DOCS_PATH) --parseDependency --parseInternal && \
rm -f $$TEMP_MAIN && \
echo "Swagger документация успешно сгенерирована с host: $(HOST)" && \
echo "Документация доступна по адресу: $(HOST)/swagger/index.html"
## -- Run -- ## -- Run --
## To change env use: make run CONFIG_PATH={config file dir path} ENV={env} ## To change env use: make run CONFIG_PATH={config file dir path} ENV={env}
.PHONY: run .PHONY: run
@@ -71,12 +111,33 @@ docker-build:
@echo "Building Docker image..." @echo "Building Docker image..."
@docker build \ @docker build \
--build-arg BUILD_LDFLAGS=$(LDFLAGS) \ --build-arg BUILD_LDFLAGS=$(LDFLAGS) \
--build-arg SWAGGER_HOST=$(SWAGGER_HOST) \
--build-arg CONFIG_FILE_PATH="$(CONFIG_PATH)$(ENV).yaml" \ --build-arg CONFIG_FILE_PATH="$(CONFIG_PATH)$(ENV).yaml" \
-t $(APP_NAME):$(VERSION) \ -t $(APP_NAME):$(VERSION) \
. .
.PHONY: docker-build-staging
docker-build-staging:
@echo "Building Docker image for staging..."
@docker build \
--build-arg BUILD_LDFLAGS=$(LDFLAGS) \
--build-arg SWAGGER_HOST=api-staging.example.com \
--build-arg CONFIG_FILE_PATH="$(CONFIG_PATH)$(ENV).yaml" \
-t $(APP_NAME):staging \
.
.PHONY: docker-build-production
docker-build-production:
@echo "Building Docker image for production..."
@docker build \
--build-arg BUILD_LDFLAGS=$(LDFLAGS) \
--build-arg SWAGGER_HOST=api.example.com \
--build-arg CONFIG_FILE_PATH="$(CONFIG_PATH)$(ENV).yaml" \
-t $(APP_NAME):production \
.
## -- Cleanup -- ## -- Cleanup --
.PHONY: clean .PHONY: clean
clean: clean:
@echo "Cleaning..." @echo "Cleaning..."
@rm -rf $(BIN_DIR) @rm -rf $(BIN_DIR)

View File

@@ -4,9 +4,8 @@ services:
molva-api-gateway: molva-api-gateway:
image: molvaapp/test_deploy:${VERSION} image: molvaapp/test_deploy:${VERSION}
ports: ports:
- target: 8000 - "8001:8000"
published: 8001 - "[::]:8001:8000"
protocol: tcp
environment: environment:
APP_VERSION: ${APP_VERSION} APP_VERSION: ${APP_VERSION}
APP_COMMIT: ${APP_COMMIT} APP_COMMIT: ${APP_COMMIT}

19
go.mod
View File

@@ -1,6 +1,8 @@
module git-molva.ru/Molva/molva-backend/services/api_gateway module git-molva.ru/Molva/molva-backend/services/api_gateway
go 1.23.3 go 1.24
toolchain go1.24.0
require ( require (
github.com/AlexOreL-272/ProtoMolva v1.32.5 github.com/AlexOreL-272/ProtoMolva v1.32.5
@@ -10,7 +12,6 @@ require (
github.com/aws/aws-sdk-go-v2/config v1.29.14 github.com/aws/aws-sdk-go-v2/config v1.29.14
github.com/aws/aws-sdk-go-v2/service/s3 v1.79.4 github.com/aws/aws-sdk-go-v2/service/s3 v1.79.4
github.com/aws/smithy-go v1.22.3 github.com/aws/smithy-go v1.22.3
github.com/ekomobile/dadata/v2 v2.17.0
github.com/go-redis/redis/v7 v7.4.1 github.com/go-redis/redis/v7 v7.4.1
github.com/golang-jwt/jwt/v5 v5.2.3 github.com/golang-jwt/jwt/v5 v5.2.3
github.com/google/uuid v1.6.0 github.com/google/uuid v1.6.0
@@ -20,12 +21,14 @@ require (
github.com/jmoiron/sqlx v1.4.0 github.com/jmoiron/sqlx v1.4.0
github.com/lib/pq v1.10.9 github.com/lib/pq v1.10.9
github.com/rabbitmq/amqp091-go v1.10.0 github.com/rabbitmq/amqp091-go v1.10.0
github.com/swaggo/http-swagger v1.3.4
github.com/swaggo/swag v1.16.2
google.golang.org/protobuf v1.36.6 google.golang.org/protobuf v1.36.6
gopkg.in/yaml.v3 v3.0.1
) )
require ( require (
github.com/BurntSushi/toml v1.4.0 // indirect github.com/BurntSushi/toml v1.4.0 // indirect
github.com/KyleBanks/depth v1.2.1 // indirect
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.10 // indirect github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.10 // indirect
github.com/aws/aws-sdk-go-v2/credentials v1.17.67 // indirect github.com/aws/aws-sdk-go-v2/credentials v1.17.67 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30 // indirect github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30 // indirect
@@ -40,24 +43,34 @@ require (
github.com/aws/aws-sdk-go-v2/service/sso v1.25.3 // indirect github.com/aws/aws-sdk-go-v2/service/sso v1.25.3 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.1 // indirect github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.1 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.33.19 // indirect github.com/aws/aws-sdk-go-v2/service/sts v1.33.19 // indirect
github.com/go-openapi/jsonpointer v0.19.5 // indirect
github.com/go-openapi/jsonreference v0.20.0 // indirect
github.com/go-openapi/spec v0.20.6 // indirect
github.com/go-openapi/swag v0.19.15 // indirect
github.com/go-resty/resty/v2 v2.16.5 // indirect github.com/go-resty/resty/v2 v2.16.5 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
github.com/jackc/puddle/v2 v2.2.2 // indirect github.com/jackc/puddle/v2 v2.2.2 // indirect
github.com/joho/godotenv v1.5.1 // indirect github.com/joho/godotenv v1.5.1 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect
github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect
github.com/mailru/easyjson v0.7.6 // indirect
github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/opentracing/opentracing-go v1.2.0 // indirect
github.com/pkg/errors v0.9.1 // indirect github.com/pkg/errors v0.9.1 // indirect
github.com/rogpeppe/go-internal v1.14.1 // indirect github.com/rogpeppe/go-internal v1.14.1 // indirect
github.com/segmentio/ksuid v1.0.4 // indirect github.com/segmentio/ksuid v1.0.4 // indirect
github.com/swaggo/files v1.0.1 // indirect
golang.org/x/crypto v0.37.0 // indirect golang.org/x/crypto v0.37.0 // indirect
golang.org/x/net v0.37.0 // indirect golang.org/x/net v0.37.0 // indirect
golang.org/x/sync v0.13.0 // indirect golang.org/x/sync v0.13.0 // indirect
golang.org/x/sys v0.32.0 // indirect golang.org/x/sys v0.32.0 // indirect
golang.org/x/text v0.24.0 // indirect golang.org/x/text v0.24.0 // indirect
golang.org/x/tools v0.26.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb // indirect
google.golang.org/grpc v1.71.0 // indirect google.golang.org/grpc v1.71.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
olympos.io/encoding/edn v0.0.0-20201019073823-d3554ca0b0a3 // indirect olympos.io/encoding/edn v0.0.0-20201019073823-d3554ca0b0a3 // indirect
) )

View File

@@ -1,5 +1,5 @@
package config package config
const ( const (
ConfigBasePath = "/config.yaml" ConfigBasePath = ".build/config/local.yaml"
) )

View File

@@ -26,6 +26,17 @@ import (
// LOGIN USER // LOGIN USER
// ------------------------------ // ------------------------------
// @Summary Вход пользователя
// @Description Аутентификация пользователя по email и паролю
// @Tags auth
// @Accept json
// @Produce json
// @Param request body rmodel.LoginUserRequest true "Данные для входа"
// @Success 200 {object} rmodel.LoginUserResponse "Успешная аутентификация"
// @Failure 400 {object} map[string]string "Неверные данные запроса"
// @Failure 401 {object} map[string]string "Неверные учетные данные"
// @Failure 500 {object} map[string]string "Внутренняя ошибка сервера"
// @Router /api/v1/login [post]
func (h *handler) loginHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) loginHandler(w http.ResponseWriter, r *http.Request) {
const handlerName = "loginHandler" const handlerName = "loginHandler"
@@ -110,6 +121,17 @@ func (h *handler) loginHandler(w http.ResponseWriter, r *http.Request) {
// REGISTER USER // REGISTER USER
// ------------------------------ // ------------------------------
// @Summary Регистрация пользователя
// @Description Создание нового пользователя в системе
// @Tags auth
// @Accept json
// @Produce json
// @Param request body rmodel.UserCredentials true "Данные для регистрации"
// @Success 201 {object} rmodel.RegisterResponse "Пользователь успешно создан"
// @Failure 400 {object} map[string]string "Неверные данные запроса"
// @Failure 409 {object} map[string]string "Пользователь уже существует"
// @Failure 500 {object} map[string]string "Внутренняя ошибка сервера"
// @Router /api/v1/register [post]
func (h *handler) registerHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) registerHandler(w http.ResponseWriter, r *http.Request) {
const handlerName = "registerHandler" const handlerName = "registerHandler"
@@ -301,6 +323,17 @@ func (h *handler) saveUser(ctx context.Context, uid string, creds rmodel.UserCre
// LOGOUT USER // LOGOUT USER
// ------------------------------ // ------------------------------
// @Summary Выход пользователя
// @Description Завершение сессии пользователя
// @Tags auth
// @Accept json
// @Produce json
// @Param request body rmodel.LogoutUserRequest true "Токен для выхода"
// @Success 200 "Успешный выход"
// @Failure 400 {object} map[string]string "Неверные данные запроса"
// @Failure 401 {object} map[string]string "Неверный токен"
// @Failure 500 {object} map[string]string "Внутренняя ошибка сервера"
// @Router /api/v1/logout [post]
func (h *handler) logoutHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) logoutHandler(w http.ResponseWriter, r *http.Request) {
const handlerName = "logoutHandler" const handlerName = "logoutHandler"
@@ -327,6 +360,17 @@ func (h *handler) logoutHandler(w http.ResponseWriter, r *http.Request) {
// REFRESH USER TOKEN // REFRESH USER TOKEN
// ------------------------------ // ------------------------------
// @Summary Обновление токена доступа
// @Description Получение нового access token по refresh token
// @Tags auth
// @Accept json
// @Produce json
// @Param request body rmodel.RefreshTokenRequest true "Refresh token"
// @Success 200 {object} rmodel.RefreshTokenResponse "Новые токены"
// @Failure 400 {object} map[string]string "Неверные данные запроса"
// @Failure 401 {object} map[string]string "Неверный refresh token"
// @Failure 500 {object} map[string]string "Внутренняя ошибка сервера"
// @Router /api/v1/refresh-token [post]
func (h *handler) refreshTokenHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) refreshTokenHandler(w http.ResponseWriter, r *http.Request) {
const handlerName = "refreshTokenHandler" const handlerName = "refreshTokenHandler"
@@ -362,6 +406,17 @@ func (h *handler) refreshTokenHandler(w http.ResponseWriter, r *http.Request) {
} }
} }
// @Summary Страница подтверждения email
// @Description HTML страница для подтверждения email адреса пользователя
// @Tags auth
// @Accept html
// @Produce html
// @Param uid query string true "ID пользователя"
// @Param token query string true "Токен подтверждения"
// @Success 200 {string} string "HTML страница подтверждения"
// @Failure 400 {object} map[string]string "Неверные параметры запроса"
// @Failure 500 {object} map[string]string "Внутренняя ошибка сервера"
// @Router /api/v1/confirm_email [get]
func (h *handler) confirmEmailPageHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) confirmEmailPageHandler(w http.ResponseWriter, r *http.Request) {
const handlerName = "confirmEmailPageHandler" const handlerName = "confirmEmailPageHandler"
@@ -418,6 +473,16 @@ func (h *handler) confirmEmailPageHandler(w http.ResponseWriter, r *http.Request
// RESET PASSWORD // RESET PASSWORD
// ------------------------------ // ------------------------------
// @Summary Запрос восстановления пароля
// @Description Отправка OTP кода на email для восстановления пароля
// @Tags auth
// @Accept json
// @Produce json
// @Param request body rmodel.ForgotPasswordRequest true "Данные для восстановления пароля"
// @Success 200 {object} map[string]string "OTP код отправлен"
// @Failure 400 {object} map[string]string "Неверные данные запроса"
// @Failure 500 {object} map[string]string "Внутренняя ошибка сервера"
// @Router /api/v1/forgot_password [post]
func (h *handler) forgotPasswordHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) forgotPasswordHandler(w http.ResponseWriter, r *http.Request) {
const handlerName = "forgotPasswordHandler" const handlerName = "forgotPasswordHandler"
@@ -475,6 +540,17 @@ func (h *handler) forgotPasswordHandler(w http.ResponseWriter, r *http.Request)
w.WriteHeader(http.StatusCreated) w.WriteHeader(http.StatusCreated)
} }
// @Summary Валидация OTP кода
// @Description Проверка OTP кода для восстановления пароля
// @Tags auth
// @Accept json
// @Produce json
// @Param otp query string true "OTP код"
// @Param email query string true "Email пользователя"
// @Success 200 {object} map[string]string "OTP код валиден"
// @Failure 400 {object} map[string]string "Неверные параметры запроса"
// @Failure 500 {object} map[string]string "Внутренняя ошибка сервера"
// @Router /api/v1/validate_otp [get]
func (h *handler) validateOTPHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) validateOTPHandler(w http.ResponseWriter, r *http.Request) {
const handlerName = "validateOTPHandler" const handlerName = "validateOTPHandler"
@@ -519,6 +595,16 @@ func (h *handler) validateOTPHandler(w http.ResponseWriter, r *http.Request) {
} }
} }
// @Summary Сброс пароля
// @Description Установка нового пароля после валидации OTP кода
// @Tags auth
// @Accept json
// @Produce json
// @Param request body rmodel.ResetPasswordRequest true "Данные для сброса пароля"
// @Success 200 {object} map[string]string "Пароль успешно изменен"
// @Failure 400 {object} map[string]string "Неверные данные запроса"
// @Failure 500 {object} map[string]string "Внутренняя ошибка сервера"
// @Router /api/v1/reset_password [put]
func (h *handler) resetPasswordHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) resetPasswordHandler(w http.ResponseWriter, r *http.Request) {
const handlerName = "resetPasswordHandler" const handlerName = "resetPasswordHandler"

View File

@@ -12,6 +12,17 @@ import (
"github.com/gorilla/mux" "github.com/gorilla/mux"
) )
// @Summary Получить баланс агента
// @Description Получение текущего баланса агента
// @Tags agents
// @Accept json
// @Produce json
// @Param agent_id path string true "ID агента"
// @Success 200 {object} rmodel.BalanceGetResponse "Баланс агента"
// @Failure 400 {object} map[string]string "Неверные параметры запроса"
// @Failure 500 {object} map[string]string "Внутренняя ошибка сервера"
// @Security BearerAuth
// @Router /api/v1/agents/{agent_id}/balance [get]
func (h *handler) getBalanceAgentHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) getBalanceAgentHandler(w http.ResponseWriter, r *http.Request) {
const handlerName = "getBalanceAgentHandler" const handlerName = "getBalanceAgentHandler"
@@ -42,6 +53,17 @@ func (h *handler) getBalanceAgentHandler(w http.ResponseWriter, r *http.Request)
} }
} }
// @Summary Получить список транзакций агента
// @Description Получение списка транзакций агента с возможностью фильтрации
// @Tags agents
// @Accept json
// @Produce json
// @Param agent_id path string true "ID агента"
// @Success 200 {object} rmodel.TransactionListGetResponse "Список транзакций"
// @Failure 400 {object} map[string]string "Неверные параметры запроса"
// @Failure 500 {object} map[string]string "Внутренняя ошибка сервера"
// @Security BearerAuth
// @Router /api/v1/agents/{agent_id}/transactions [get]
func (h *handler) getTransactionListAgentHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) getTransactionListAgentHandler(w http.ResponseWriter, r *http.Request) {
const handlerName = "getTransactionListAgentHandler" const handlerName = "getTransactionListAgentHandler"
@@ -84,6 +106,18 @@ func (h *handler) getTransactionListAgentHandler(w http.ResponseWriter, r *http.
} }
} }
// @Summary Создать транзакцию агента
// @Description Создание новой транзакции для агента
// @Tags agents
// @Accept json
// @Produce json
// @Param agent_id path string true "ID агента"
// @Param request body rmodel.TransactionCreateRequest true "Данные транзакции"
// @Success 201 {object} rmodel.TransactionCreateResponse "Транзакция создана"
// @Failure 400 {object} map[string]string "Неверные данные запроса"
// @Failure 500 {object} map[string]string "Внутренняя ошибка сервера"
// @Security BearerAuth
// @Router /api/v1/agents/{agent_id}/transactions [post]
func (h *handler) createTransactionAgentHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) createTransactionAgentHandler(w http.ResponseWriter, r *http.Request) {
const handlerName = "createTransactionAgentHandler" const handlerName = "createTransactionAgentHandler"
@@ -146,6 +180,17 @@ func (h *handler) createTransactionAgentHandler(w http.ResponseWriter, r *http.R
} }
} }
// @Summary Получить список банковских счетов агента
// @Description Получение списка банковских счетов агента
// @Tags agents
// @Accept json
// @Produce json
// @Param agent_id path string true "ID агента"
// @Success 200 {object} rmodel.BankAccountListGetResponse "Список банковских счетов"
// @Failure 400 {object} map[string]string "Неверные параметры запроса"
// @Failure 500 {object} map[string]string "Внутренняя ошибка сервера"
// @Security BearerAuth
// @Router /api/v1/agents/{agent_id}/bank_accounts [get]
func (h *handler) getBankAccountListAgentHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) getBankAccountListAgentHandler(w http.ResponseWriter, r *http.Request) {
const handlerName = "getBankAccountListAgentHandler" const handlerName = "getBankAccountListAgentHandler"
@@ -178,6 +223,18 @@ func (h *handler) getBankAccountListAgentHandler(w http.ResponseWriter, r *http.
} }
} }
// @Summary Создать банковский счет агента
// @Description Создание нового банковского счета для агента
// @Tags agents
// @Accept json
// @Produce json
// @Param agent_id path string true "ID агента"
// @Param request body rmodel.BankAccountCreateRequest true "Данные банковского счета"
// @Success 201 {object} rmodel.BankAccountCreateResponse "Банковский счет создан"
// @Failure 400 {object} map[string]string "Неверные данные запроса"
// @Failure 500 {object} map[string]string "Внутренняя ошибка сервера"
// @Security BearerAuth
// @Router /api/v1/agents/{agent_id}/bank_accounts [post]
func (h *handler) createBankAccountAgentHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) createBankAccountAgentHandler(w http.ResponseWriter, r *http.Request) {
const handlerName = "createBankAccountAgentHandler" const handlerName = "createBankAccountAgentHandler"
@@ -232,6 +289,19 @@ func (h *handler) createBankAccountAgentHandler(w http.ResponseWriter, r *http.R
} }
} }
// @Summary Обновить банковский счет агента
// @Description Обновление информации о банковском счете агента
// @Tags agents
// @Accept json
// @Produce json
// @Param agent_id path string true "ID агента"
// @Param bank_account_id path string true "ID банковского счета"
// @Param request body rmodel.BankAccountUpdateRequest true "Данные для обновления"
// @Success 200 {object} map[string]string "Банковский счет обновлен"
// @Failure 400 {object} map[string]string "Неверные данные запроса"
// @Failure 500 {object} map[string]string "Внутренняя ошибка сервера"
// @Security BearerAuth
// @Router /api/v1/agents/{agent_id}/bank_accounts/{bank_account_id} [put]
func (h *handler) updateBankAccountAgentHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) updateBankAccountAgentHandler(w http.ResponseWriter, r *http.Request) {
const handlerName = "updateBankAccountAgentHandler" const handlerName = "updateBankAccountAgentHandler"
@@ -285,6 +355,18 @@ func (h *handler) updateBankAccountAgentHandler(w http.ResponseWriter, r *http.R
} }
// TODO: test when implemented // TODO: test when implemented
// @Summary Удалить банковский счет агента
// @Description Удаление банковского счета агента
// @Tags agents
// @Accept json
// @Produce json
// @Param agent_id path string true "ID агента"
// @Param bank_account_id path string true "ID банковского счета"
// @Success 200 {object} map[string]string "Банковский счет удален"
// @Failure 400 {object} map[string]string "Неверные параметры запроса"
// @Failure 500 {object} map[string]string "Внутренняя ошибка сервера"
// @Security BearerAuth
// @Router /api/v1/agents/{agent_id}/bank_accounts/{bank_account_id} [delete]
func (h *handler) deleteBankAccountAgentHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) deleteBankAccountAgentHandler(w http.ResponseWriter, r *http.Request) {
const handlerName = "deleteBankAccountAgentHandler" const handlerName = "deleteBankAccountAgentHandler"
@@ -327,6 +409,17 @@ func (h *handler) deleteBankAccountAgentHandler(w http.ResponseWriter, r *http.R
} }
} }
// @Summary Получить баланс дистрибьютора
// @Description Получение текущего баланса дистрибьютора
// @Tags distributors
// @Accept json
// @Produce json
// @Param distributor_id path string true "ID дистрибьютора"
// @Success 200 {object} rmodel.BalanceGetResponse "Баланс дистрибьютора"
// @Failure 400 {object} map[string]string "Неверные параметры запроса"
// @Failure 500 {object} map[string]string "Внутренняя ошибка сервера"
// @Security BearerAuth
// @Router /api/v1/distributor/{distributor_id}/balance [get]
func (h *handler) getBalanceDistributorHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) getBalanceDistributorHandler(w http.ResponseWriter, r *http.Request) {
const handlerName = "getBalanceDistributorHandler" const handlerName = "getBalanceDistributorHandler"
@@ -359,6 +452,18 @@ func (h *handler) getBalanceDistributorHandler(w http.ResponseWriter, r *http.Re
} }
} }
// @Summary Получить баланс компании дистрибьютора
// @Description Получение баланса конкретной компании дистрибьютора
// @Tags distributors
// @Accept json
// @Produce json
// @Param distributor_id path string true "ID дистрибьютора"
// @Param company_id path string true "ID компании"
// @Success 200 {object} rmodel.BalanceGetResponse "Баланс компании"
// @Failure 400 {object} map[string]string "Неверные параметры запроса"
// @Failure 500 {object} map[string]string "Внутренняя ошибка сервера"
// @Security BearerAuth
// @Router /api/v1/distributor/{distributor_id}/company/{company_id}/balance [get]
func (h *handler) getCompanyBalanceDistributorHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) getCompanyBalanceDistributorHandler(w http.ResponseWriter, r *http.Request) {
const handlerName = "getCompanyBalanceDistributorHandler" const handlerName = "getCompanyBalanceDistributorHandler"
@@ -391,6 +496,17 @@ func (h *handler) getCompanyBalanceDistributorHandler(w http.ResponseWriter, r *
} }
} }
// @Summary Получить список транзакций дистрибьютора
// @Description Получение списка транзакций дистрибьютора с возможностью фильтрации
// @Tags distributors
// @Accept json
// @Produce json
// @Param distributor_id path string true "ID дистрибьютора"
// @Success 200 {object} rmodel.TransactionListGetResponse "Список транзакций"
// @Failure 400 {object} map[string]string "Неверные параметры запроса"
// @Failure 500 {object} map[string]string "Внутренняя ошибка сервера"
// @Security BearerAuth
// @Router /api/v1/distributor/{distributor_id}/transactions [get]
func (h *handler) getTransactionListDistributorHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) getTransactionListDistributorHandler(w http.ResponseWriter, r *http.Request) {
const handlerName = "getTransactionListDistributorHandler" const handlerName = "getTransactionListDistributorHandler"
@@ -434,6 +550,18 @@ func (h *handler) getTransactionListDistributorHandler(w http.ResponseWriter, r
} }
} }
// @Summary Получить список транзакций компании дистрибьютора
// @Description Получение списка транзакций конкретной компании дистрибьютора
// @Tags distributors
// @Accept json
// @Produce json
// @Param distributor_id path string true "ID дистрибьютора"
// @Param company_id path string true "ID компании"
// @Success 200 {object} rmodel.TransactionListGetResponse "Список транзакций компании"
// @Failure 400 {object} map[string]string "Неверные параметры запроса"
// @Failure 500 {object} map[string]string "Внутренняя ошибка сервера"
// @Security BearerAuth
// @Router /api/v1/distributor/{distributor_id}/company/{company_id}/transactions [get]
func (h *handler) getCompanyTransactionListDistributorHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) getCompanyTransactionListDistributorHandler(w http.ResponseWriter, r *http.Request) {
const handlerName = "getCompanyTransactionListDistributorHandler" const handlerName = "getCompanyTransactionListDistributorHandler"
@@ -477,6 +605,18 @@ func (h *handler) getCompanyTransactionListDistributorHandler(w http.ResponseWri
} }
} }
// @Summary Создать транзакцию дистрибьютора
// @Description Создание новой транзакции для дистрибьютора
// @Tags distributors
// @Accept json
// @Produce json
// @Param distributor_id path string true "ID дистрибьютора"
// @Param request body rmodel.TransactionCreateRequest true "Данные транзакции"
// @Success 201 {object} rmodel.TransactionCreateResponse "Транзакция создана"
// @Failure 400 {object} map[string]string "Неверные данные запроса"
// @Failure 500 {object} map[string]string "Внутренняя ошибка сервера"
// @Security BearerAuth
// @Router /api/v1/distributor/{distributor_id}/transactions [post]
func (h *handler) createTransactionDistributorHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) createTransactionDistributorHandler(w http.ResponseWriter, r *http.Request) {
const handlerName = "createTransactionDistributorHandler" const handlerName = "createTransactionDistributorHandler"
@@ -539,6 +679,17 @@ func (h *handler) createTransactionDistributorHandler(w http.ResponseWriter, r *
} }
} }
// @Summary Получить список банковских счетов дистрибьютора
// @Description Получение списка банковских счетов дистрибьютора
// @Tags distributors
// @Accept json
// @Produce json
// @Param distributor_id path string true "ID дистрибьютора"
// @Success 200 {object} rmodel.BankAccountListGetResponse "Список банковских счетов"
// @Failure 400 {object} map[string]string "Неверные параметры запроса"
// @Failure 500 {object} map[string]string "Внутренняя ошибка сервера"
// @Security BearerAuth
// @Router /api/v1/distributor/{distributor_id}/bank_accounts [get]
func (h *handler) getBankAccountListDistributorHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) getBankAccountListDistributorHandler(w http.ResponseWriter, r *http.Request) {
const handlerName = "getBankAccountListDistributorHandler" const handlerName = "getBankAccountListDistributorHandler"
@@ -571,6 +722,18 @@ func (h *handler) getBankAccountListDistributorHandler(w http.ResponseWriter, r
} }
} }
// @Summary Получить список банковских счетов компании дистрибьютора
// @Description Получение списка банковских счетов конкретной компании дистрибьютора
// @Tags distributors
// @Accept json
// @Produce json
// @Param distributor_id path string true "ID дистрибьютора"
// @Param company_id path string true "ID компании"
// @Success 200 {object} rmodel.BankAccountListGetResponse "Список банковских счетов компании"
// @Failure 400 {object} map[string]string "Неверные параметры запроса"
// @Failure 500 {object} map[string]string "Внутренняя ошибка сервера"
// @Security BearerAuth
// @Router /api/v1/distributor/{distributor_id}/company/{company_id}/bank_accounts [get]
func (h *handler) getCompanyBankAccountListDistributorHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) getCompanyBankAccountListDistributorHandler(w http.ResponseWriter, r *http.Request) {
const handlerName = "getCompanyBankAccountListDistributorHandler" const handlerName = "getCompanyBankAccountListDistributorHandler"
@@ -603,6 +766,19 @@ func (h *handler) getCompanyBankAccountListDistributorHandler(w http.ResponseWri
} }
} }
// @Summary Создать банковский счет компании дистрибьютора
// @Description Создание нового банковского счета для компании дистрибьютора
// @Tags distributors
// @Accept json
// @Produce json
// @Param distributor_id path string true "ID дистрибьютора"
// @Param company_id path string true "ID компании"
// @Param request body rmodel.BankAccountCreateRequest true "Данные банковского счета"
// @Success 201 {object} rmodel.BankAccountCreateResponse "Банковский счет создан"
// @Failure 400 {object} map[string]string "Неверные данные запроса"
// @Failure 500 {object} map[string]string "Внутренняя ошибка сервера"
// @Security BearerAuth
// @Router /api/v1/distributor/{distributor_id}/company/{company_id}/bank_accounts [post]
func (h *handler) createBankAccountDistributorHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) createBankAccountDistributorHandler(w http.ResponseWriter, r *http.Request) {
const handlerName = "createBankAccountDistributorHandler" const handlerName = "createBankAccountDistributorHandler"
@@ -664,6 +840,19 @@ func (h *handler) createBankAccountDistributorHandler(w http.ResponseWriter, r *
} }
} }
// @Summary Обновить банковский счет дистрибьютора
// @Description Обновление информации о банковском счете дистрибьютора
// @Tags distributors
// @Accept json
// @Produce json
// @Param distributor_id path string true "ID дистрибьютора"
// @Param bank_account_id path string true "ID банковского счета"
// @Param request body rmodel.BankAccountUpdateRequest true "Данные для обновления"
// @Success 200 {object} map[string]string "Банковский счет обновлен"
// @Failure 400 {object} map[string]string "Неверные данные запроса"
// @Failure 500 {object} map[string]string "Внутренняя ошибка сервера"
// @Security BearerAuth
// @Router /api/v1/distributor/{distributor_id}/bank_accounts/{bank_account_id} [put]
func (h *handler) updateBankAccountDistributorHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) updateBankAccountDistributorHandler(w http.ResponseWriter, r *http.Request) {
const handlerName = "updateBankAccountDistributorHandler" const handlerName = "updateBankAccountDistributorHandler"
@@ -725,6 +914,18 @@ func (h *handler) updateBankAccountDistributorHandler(w http.ResponseWriter, r *
} }
} }
// @Summary Удалить банковский счет дистрибьютора
// @Description Удаление банковского счета дистрибьютора
// @Tags distributors
// @Accept json
// @Produce json
// @Param distributor_id path string true "ID дистрибьютора"
// @Param bank_account_id path string true "ID банковского счета"
// @Success 200 {object} map[string]string "Банковский счет удален"
// @Failure 400 {object} map[string]string "Неверные параметры запроса"
// @Failure 500 {object} map[string]string "Внутренняя ошибка сервера"
// @Security BearerAuth
// @Router /api/v1/distributor/{distributor_id}/bank_accounts/{bank_account_id} [delete]
func (h *handler) deleteBankAccountDistributorHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) deleteBankAccountDistributorHandler(w http.ResponseWriter, r *http.Request) {
const handlerName = "deleteBankAccountDistributorHandler" const handlerName = "deleteBankAccountDistributorHandler"

View File

@@ -5,6 +5,13 @@ import (
"net/http" "net/http"
) )
// @Summary Получить информацию о сборке
// @Description Получение информации о версии, коммите и дате сборки приложения
// @Tags system
// @Accept json
// @Produce json
// @Success 200 {object} map[string]string "Информация о сборке"
// @Router /api/v1/healthcheck [get]
func (h *handler) getBuildInfoHandler(w http.ResponseWriter, _ *http.Request) { func (h *handler) getBuildInfoHandler(w http.ResponseWriter, _ *http.Request) {
response := struct { response := struct {
Version string `json:"version"` Version string `json:"version"`

View File

@@ -12,6 +12,18 @@ import (
rmodel "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/request_model" rmodel "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/request_model"
) )
// @Summary Получить список компаний агента
// @Description Получение списка всех компаний, принадлежащих агенту
// @Tags agents
// @Accept json
// @Produce json
// @Param agent_id path string true "ID агента"
// @Success 200 {object} rmodel.CompanyListGetResponse "Список компаний"
// @Failure 400 {object} map[string]string "Неверные данные запроса"
// @Failure 401 {object} map[string]string "Неавторизованный доступ"
// @Failure 500 {object} map[string]string "Внутренняя ошибка сервера"
// @Security BearerAuth
// @Router /api/v1/agents/{agent_id}/companies [get]
func (h *handler) getCompanyListAgentHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) getCompanyListAgentHandler(w http.ResponseWriter, r *http.Request) {
const handlerName = "getCompanyListAgentHandler" const handlerName = "getCompanyListAgentHandler"
@@ -44,6 +56,20 @@ func (h *handler) getCompanyListAgentHandler(w http.ResponseWriter, r *http.Requ
} }
} }
// @Summary Получить компанию по ID
// @Description Получение детальной информации о компании агента
// @Tags agents
// @Accept json
// @Produce json
// @Param agent_id path string true "ID агента"
// @Param company_id path string true "ID компании"
// @Success 200 {object} rmodel.CompanyByIdGetResponse "Информация о компании"
// @Failure 400 {object} map[string]string "Неверные данные запроса"
// @Failure 401 {object} map[string]string "Неавторизованный доступ"
// @Failure 404 {object} map[string]string "Компания не найдена"
// @Failure 500 {object} map[string]string "Внутренняя ошибка сервера"
// @Security BearerAuth
// @Router /api/v1/agents/{agent_id}/company/{company_id} [get]
func (h *handler) getCompanyByIdAgentHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) getCompanyByIdAgentHandler(w http.ResponseWriter, r *http.Request) {
const handlerName = "getCompanyByIdAgentHandler" const handlerName = "getCompanyByIdAgentHandler"
@@ -78,6 +104,19 @@ func (h *handler) getCompanyByIdAgentHandler(w http.ResponseWriter, r *http.Requ
} }
} }
// @Summary Создать компанию
// @Description Создание новой компании для агента
// @Tags agents
// @Accept json
// @Produce json
// @Param agent_id path string true "ID агента"
// @Param request body rmodel.CompanyCreateRequest true "Данные для создания компании"
// @Success 201 {object} rmodel.CompanyCreateResponse "Компания создана"
// @Failure 400 {object} map[string]string "Неверные данные запроса"
// @Failure 401 {object} map[string]string "Неавторизованный доступ"
// @Failure 500 {object} map[string]string "Внутренняя ошибка сервера"
// @Security BearerAuth
// @Router /api/v1/agents/{agent_id}/company [post]
// FIXME: foreign key violation review // FIXME: foreign key violation review
func (h *handler) createCompanyAgentHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) createCompanyAgentHandler(w http.ResponseWriter, r *http.Request) {
const handlerName = "createAgentCompanyHandler" const handlerName = "createAgentCompanyHandler"

View File

@@ -10,6 +10,18 @@ import (
"github.com/gorilla/mux" "github.com/gorilla/mux"
) )
// @Summary Получить список компаний дистрибьютора
// @Description Получение списка всех компаний, принадлежащих дистрибьютору
// @Tags distributors
// @Accept json
// @Produce json
// @Param distributor_id path string true "ID дистрибьютора"
// @Success 200 {object} rmodel.CompanyListGetResponse "Список компаний"
// @Failure 400 {object} map[string]string "Неверные данные запроса"
// @Failure 401 {object} map[string]string "Неавторизованный доступ"
// @Failure 500 {object} map[string]string "Внутренняя ошибка сервера"
// @Security BearerAuth
// @Router /api/v1/distributor/{distributor_id}/companies [get]
func (h *handler) getCompanyListDistributorHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) getCompanyListDistributorHandler(w http.ResponseWriter, r *http.Request) {
const handlerName = "getCompanyListDistributorHandler" const handlerName = "getCompanyListDistributorHandler"
@@ -42,6 +54,20 @@ func (h *handler) getCompanyListDistributorHandler(w http.ResponseWriter, r *htt
} }
} }
// @Summary Получить компанию дистрибьютора по ID
// @Description Получение детальной информации о компании дистрибьютора
// @Tags distributors
// @Accept json
// @Produce json
// @Param distributor_id path string true "ID дистрибьютора"
// @Param company_id path string true "ID компании"
// @Success 200 {object} rmodel.CompanyByIdGetResponse "Информация о компании"
// @Failure 400 {object} map[string]string "Неверные данные запроса"
// @Failure 401 {object} map[string]string "Неавторизованный доступ"
// @Failure 404 {object} map[string]string "Компания не найдена"
// @Failure 500 {object} map[string]string "Внутренняя ошибка сервера"
// @Security BearerAuth
// @Router /api/v1/distributor/{distributor_id}/company/{company_id} [get]
func (h *handler) getCompanyByIdDistributorHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) getCompanyByIdDistributorHandler(w http.ResponseWriter, r *http.Request) {
const handlerName = "getCompanyByIdDistributorHandler" const handlerName = "getCompanyByIdDistributorHandler"
@@ -76,6 +102,19 @@ func (h *handler) getCompanyByIdDistributorHandler(w http.ResponseWriter, r *htt
} }
} }
// @Summary Создать компанию дистрибьютора
// @Description Создание новой компании для дистрибьютора
// @Tags distributors
// @Accept json
// @Produce json
// @Param distributor_id path string true "ID дистрибьютора"
// @Param request body rmodel.CompanyCreateRequest true "Данные для создания компании"
// @Success 201 {object} rmodel.CompanyCreateResponse "Компания создана"
// @Failure 400 {object} map[string]string "Неверные данные запроса"
// @Failure 401 {object} map[string]string "Неавторизованный доступ"
// @Failure 500 {object} map[string]string "Внутренняя ошибка сервера"
// @Security BearerAuth
// @Router /api/v1/distributor/{distributor_id}/company [post]
func (h *handler) createCompanyDistributorHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) createCompanyDistributorHandler(w http.ResponseWriter, r *http.Request) {
const handlerName = "createCompanyDistributorHandler" const handlerName = "createCompanyDistributorHandler"
@@ -124,6 +163,21 @@ func (h *handler) createCompanyDistributorHandler(w http.ResponseWriter, r *http
} }
} }
// @Summary Обновить компанию дистрибьютора
// @Description Обновление информации о компании дистрибьютора
// @Tags distributors
// @Accept json
// @Produce json
// @Param distributor_id path string true "ID дистрибьютора"
// @Param company_id path string true "ID компании"
// @Param request body rmodel.CompanyUpdateRequest true "Данные для обновления"
// @Success 204 "Компания обновлена"
// @Failure 400 {object} map[string]string "Неверные данные запроса"
// @Failure 401 {object} map[string]string "Неавторизованный доступ"
// @Failure 404 {object} map[string]string "Компания не найдена"
// @Failure 500 {object} map[string]string "Внутренняя ошибка сервера"
// @Security BearerAuth
// @Router /api/v1/distributor/{distributor_id}/company/{company_id} [patch]
func (h *handler) updateCompanyDistributorHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) updateCompanyDistributorHandler(w http.ResponseWriter, r *http.Request) {
const handlerName = "updateCompanyDistributorHandler" const handlerName = "updateCompanyDistributorHandler"
@@ -161,6 +215,21 @@ func (h *handler) updateCompanyDistributorHandler(w http.ResponseWriter, r *http
w.WriteHeader(http.StatusNoContent) w.WriteHeader(http.StatusNoContent)
} }
// @Summary Добавить участника в компанию
// @Description Добавление нового участника в компанию дистрибьютора
// @Tags distributors
// @Accept json
// @Produce json
// @Param distributor_id path string true "ID дистрибьютора"
// @Param company_id path string true "ID компании"
// @Param request body rmodel.AddDistributorCompanyMemberRequest true "Данные участника"
// @Success 201 "Участник добавлен"
// @Failure 400 {object} map[string]string "Неверные данные запроса"
// @Failure 401 {object} map[string]string "Неавторизованный доступ"
// @Failure 404 {object} map[string]string "Компания не найдена"
// @Failure 500 {object} map[string]string "Внутренняя ошибка сервера"
// @Security BearerAuth
// @Router /api/v1/distributor/{distributor_id}/company/{company_id} [post]
func (h *handler) addCompanyMemberDistributorHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) addCompanyMemberDistributorHandler(w http.ResponseWriter, r *http.Request) {
const handlerName = "addCompanyMemberDistributorHandler" const handlerName = "addCompanyMemberDistributorHandler"

View File

@@ -32,6 +32,19 @@ import (
"github.com/gorilla/mux" "github.com/gorilla/mux"
) )
// @Summary Получить персональную ссылку
// @Description Получение персональной ссылки агента для вакансии
// @Tags agents
// @Accept json
// @Produce json
// @Param agent_id path string true "ID агента"
// @Param vacancy_id path string true "ID вакансии"
// @Success 200 {object} types.PersonalLinkResponse "Персональная ссылка"
// @Failure 400 {object} map[string]string "Неверные данные запроса"
// @Failure 401 {object} map[string]string "Неавторизованный доступ"
// @Failure 500 {object} map[string]string "Внутренняя ошибка сервера"
// @Security BearerAuth
// @Router /api/v1/agents/{agent_id}/vacancies/{vacancy_id} [get]
func (h *handler) getPersonalLinkHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) getPersonalLinkHandler(w http.ResponseWriter, r *http.Request) {
handlerName := "getPersonalLinkHandler" handlerName := "getPersonalLinkHandler"
vars := mux.Vars(r) vars := mux.Vars(r)
@@ -70,6 +83,18 @@ func (h *handler) getPersonalLinkHandler(w http.ResponseWriter, r *http.Request)
} }
} }
// @Summary Получить анкету
// @Description Получение HTML формы анкеты для клиента
// @Tags clients
// @Accept json
// @Produce text/html
// @Param link query string true "Зашифрованная ссылка с параметрами"
// @Success 200 {string} string "HTML форма анкеты"
// @Failure 400 {object} map[string]string "Неверные данные запроса"
// @Failure 404 {object} map[string]string "Вакансия не найдена"
// @Failure 500 {object} map[string]string "Внутренняя ошибка сервера"
// @Router /api/v1/anketa [get]
//
//nolint:funlen // TODO: make it sudo super clean //nolint:funlen // TODO: make it sudo super clean
func (h *handler) getAnketaHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) getAnketaHandler(w http.ResponseWriter, r *http.Request) {
handlerName := "getAnketaHandler" handlerName := "getAnketaHandler"
@@ -235,6 +260,19 @@ func (h *handler) extractPermissions(permMap *auth.GetPermissionsByUsersIdRespon
return perm return perm
} }
// @Summary Получить список сотрудников компании
// @Description Получение списка сотрудников компании
// @Tags employees
// @Accept json
// @Produce json
// @Param company_id path string true "ID компании"
// @Param uid query string true "ID пользователя"
// @Success 200 {object} rmodel.EmployeeResponse "Список сотрудников"
// @Failure 400 {object} map[string]string "Неверные данные запроса"
// @Failure 401 {object} map[string]string "Неавторизованный доступ"
// @Failure 500 {object} map[string]string "Внутренняя ошибка сервера"
// @Security BearerAuth
// @Router /api/v1/companies/{company_id}/employees [get]
func (h *handler) getEmployeesHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) getEmployeesHandler(w http.ResponseWriter, r *http.Request) {
const handlerName = "getEmployeesHandler" const handlerName = "getEmployeesHandler"
@@ -292,6 +330,16 @@ func (h *handler) getEmployeesHandler(w http.ResponseWriter, r *http.Request) {
} }
} }
// @Summary Получить статус валидации пользователя
// @Description Получение статуса валидации пользователя по UID
// @Tags system
// @Accept json
// @Produce json
// @Param uid path string true "UID пользователя"
// @Success 200 {object} map[string]string "Статус валидации"
// @Failure 400 {object} map[string]string "Неверные параметры запроса"
// @Failure 500 {object} map[string]string "Внутренняя ошибка сервера"
// @Router /api/v1/{uid}/validation [get]
func (h *handler) getUserValidationStatusHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) getUserValidationStatusHandler(w http.ResponseWriter, r *http.Request) {
const handlerName = "getValidationStatusHandler" const handlerName = "getValidationStatusHandler"
@@ -331,6 +379,16 @@ func (h *handler) getUserValidationStatusHandler(w http.ResponseWriter, r *http.
} }
} }
// @Summary Получить файл документа
// @Description Получение файла документа по имени
// @Tags system
// @Accept json
// @Produce application/octet-stream
// @Param file path string true "Имя файла"
// @Success 200 {file} file "Файл документа"
// @Failure 404 {object} map[string]string "Файл не найден"
// @Failure 500 {object} map[string]string "Внутренняя ошибка сервера"
// @Router /api/v1/docs/{file} [get]
func (h *handler) getFileHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) getFileHandler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r) vars := mux.Vars(r)
fileName := vars["file"] fileName := vars["file"]
@@ -389,6 +447,17 @@ func (h *handler) getFileHandler(w http.ResponseWriter, r *http.Request) {
_, _ = w.Write([]byte(link)) _, _ = w.Write([]byte(link))
} }
// @Summary Подтверждение email
// @Description Подтверждение email адреса пользователя по токену
// @Tags auth
// @Accept json
// @Produce json
// @Param uid query string true "ID пользователя"
// @Param token query string true "Токен подтверждения"
// @Success 200 {object} map[string]string "Email успешно подтвержден"
// @Failure 400 {object} map[string]string "Неверные параметры запроса"
// @Failure 500 {object} map[string]string "Внутренняя ошибка сервера"
// @Router /api/v1/verify_email [patch]
func (h *handler) verifyEmailHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) verifyEmailHandler(w http.ResponseWriter, r *http.Request) {
const handlerName = "verifyEmailHandler" const handlerName = "verifyEmailHandler"
@@ -528,6 +597,16 @@ func (h *handler) sendNewUserNotificationToAdmin(userInfo *auth.UserInfo, userNa
return nil return nil
} }
// @Summary Статус подтверждения email
// @Description Получение статуса подтверждения email адреса пользователя
// @Tags auth
// @Accept json
// @Produce json
// @Param uid query string true "ID пользователя"
// @Success 200 {object} map[string]string "Статус подтверждения email"
// @Failure 400 {object} map[string]string "Неверные параметры запроса"
// @Failure 500 {object} map[string]string "Внутренняя ошибка сервера"
// @Router /api/v1/verify_email [get]
func (h *handler) getEmailVerificationStatusHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) getEmailVerificationStatusHandler(w http.ResponseWriter, r *http.Request) {
const handlerName = "getEmailVerificationStatusHandler" const handlerName = "getEmailVerificationStatusHandler"
@@ -638,6 +717,23 @@ func (h *handler) validateEmail(email string) (bool, error) {
return isValidEmail, nil return isValidEmail, nil
} }
// @Summary Получить события пользователя
// @Description Получение ленты событий пользователя с возможностью фильтрации
// @Tags feed
// @Accept json
// @Produce json
// @Param uid path string true "ID пользователя"
// @Param user_type query string true "Тип пользователя (agent/distributor)"
// @Param event_type query string false "Тип события (через запятую)"
// @Param show_cancelled query bool false "Показывать отмененные события"
// @Param limit query int false "Лимит событий"
// @Param offset query int false "Смещение"
// @Success 200 {object} []feed.Event "Список событий"
// @Failure 400 {object} map[string]string "Неверные данные запроса"
// @Failure 401 {object} map[string]string "Неавторизованный доступ"
// @Failure 500 {object} map[string]string "Внутренняя ошибка сервера"
// @Security BearerAuth
// @Router /api/v1/feed/{uid}/events [get]
func (h *handler) GetUserEventsHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) GetUserEventsHandler(w http.ResponseWriter, r *http.Request) {
handlerName := "GetUserEventsHandler" handlerName := "GetUserEventsHandler"
query := r.URL.Query() query := r.URL.Query()

View File

@@ -11,6 +11,16 @@ import (
intrmodel "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/request_model/integration" intrmodel "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/request_model/integration"
) )
// @Summary Callback интеграции с ВкусВилл
// @Description Обработка callback запросов от интеграции с ВкусВилл
// @Tags integration
// @Accept json
// @Produce json
// @Param request body map[string]interface{} true "Данные callback от ВкусВилл"
// @Success 200 {object} map[string]string "Callback обработан"
// @Failure 400 {object} map[string]string "Неверные данные запроса"
// @Failure 500 {object} map[string]string "Внутренняя ошибка сервера"
// @Router /api/v1/integration/vkusvill/callback [post]
func (h *handler) vkusvillIntegrationCallbackHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) vkusvillIntegrationCallbackHandler(w http.ResponseWriter, r *http.Request) {
const handlerName = "vkusvillIntegrationCallbackHandler" const handlerName = "vkusvillIntegrationCallbackHandler"

View File

@@ -130,6 +130,19 @@ func (lf *LogoFile) Reset() error {
// =============== LOGO HANDLERS =============== // =============== LOGO HANDLERS ===============
// @Summary Получить логотип компании
// @Description Получение логотипа компании дистрибьютора
// @Tags distributors
// @Accept json
// @Produce json
// @Param distributor_id path string true "ID дистрибьютора"
// @Param company_id path string true "ID компании"
// @Success 200 {file} file "Логотип компании"
// @Failure 400 {object} map[string]string "Неверные параметры запроса"
// @Failure 404 {object} map[string]string "Логотип не найден"
// @Failure 500 {object} map[string]string "Внутренняя ошибка сервера"
// @Security BearerAuth
// @Router /api/v1/distributor/{distributor_id}/company/{company_id}/logo [get]
func (h *handler) getCompanyLogoHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) getCompanyLogoHandler(w http.ResponseWriter, r *http.Request) {
const handlerName = "getCompanyLogoHandler" const handlerName = "getCompanyLogoHandler"
@@ -180,6 +193,19 @@ func (h *handler) getCompanyLogoHandler(w http.ResponseWriter, r *http.Request)
} }
} }
// @Summary Создать логотип компании
// @Description Загрузка нового логотипа для компании дистрибьютора
// @Tags distributors
// @Accept multipart/form-data
// @Produce json
// @Param distributor_id path string true "ID дистрибьютора"
// @Param company_id path string true "ID компании"
// @Param logo formData file true "Файл логотипа"
// @Success 201 {object} map[string]string "Логотип загружен"
// @Failure 400 {object} map[string]string "Неверные данные запроса"
// @Failure 500 {object} map[string]string "Внутренняя ошибка сервера"
// @Security BearerAuth
// @Router /api/v1/distributor/{distributor_id}/company/{company_id}/logo [post]
func (h *handler) createCompanyLogoHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) createCompanyLogoHandler(w http.ResponseWriter, r *http.Request) {
const handlerName = "createCompanyLogoHandler" const handlerName = "createCompanyLogoHandler"
@@ -240,6 +266,19 @@ func (h *handler) createCompanyLogoHandler(w http.ResponseWriter, r *http.Reques
w.WriteHeader(http.StatusCreated) w.WriteHeader(http.StatusCreated)
} }
// @Summary Обновить логотип компании
// @Description Обновление логотипа компании дистрибьютора
// @Tags distributors
// @Accept multipart/form-data
// @Produce json
// @Param distributor_id path string true "ID дистрибьютора"
// @Param company_id path string true "ID компании"
// @Param logo formData file true "Новый файл логотипа"
// @Success 200 {object} map[string]string "Логотип обновлен"
// @Failure 400 {object} map[string]string "Неверные данные запроса"
// @Failure 500 {object} map[string]string "Внутренняя ошибка сервера"
// @Security BearerAuth
// @Router /api/v1/distributor/{distributor_id}/company/{company_id}/logo [put]
func (h *handler) updateCompanyLogoHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) updateCompanyLogoHandler(w http.ResponseWriter, r *http.Request) {
const handlerName = "updateCompanyLogoHandler" const handlerName = "updateCompanyLogoHandler"
@@ -300,6 +339,18 @@ func (h *handler) updateCompanyLogoHandler(w http.ResponseWriter, r *http.Reques
w.WriteHeader(http.StatusNoContent) w.WriteHeader(http.StatusNoContent)
} }
// @Summary Удалить логотип компании
// @Description Удаление логотипа компании дистрибьютора
// @Tags distributors
// @Accept json
// @Produce json
// @Param distributor_id path string true "ID дистрибьютора"
// @Param company_id path string true "ID компании"
// @Success 200 {object} map[string]string "Логотип удален"
// @Failure 400 {object} map[string]string "Неверные параметры запроса"
// @Failure 500 {object} map[string]string "Внутренняя ошибка сервера"
// @Security BearerAuth
// @Router /api/v1/distributor/{distributor_id}/company/{company_id}/logo [delete]
func (h *handler) deleteCompanyLogoHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) deleteCompanyLogoHandler(w http.ResponseWriter, r *http.Request) {
const handlerName = "deleteCompanyLogoHandler" const handlerName = "deleteCompanyLogoHandler"

View File

@@ -12,6 +12,17 @@ import (
rmodel "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/request_model" rmodel "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/request_model"
) )
// @Summary Получить профиль агента
// @Description Получение профиля агента по ID
// @Tags agents
// @Accept json
// @Produce json
// @Param agent_id path string true "ID агента"
// @Success 200 {object} rmodel.ProfileGetResponse "Профиль агента"
// @Failure 400 {object} map[string]string "Неверные параметры запроса"
// @Failure 500 {object} map[string]string "Внутренняя ошибка сервера"
// @Security BearerAuth
// @Router /api/v1/agents/{agent_id}/profile [get]
func (h *handler) getProfileAgentHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) getProfileAgentHandler(w http.ResponseWriter, r *http.Request) {
const handlerName = "getAgentProfileHandler" const handlerName = "getAgentProfileHandler"
@@ -44,6 +55,18 @@ func (h *handler) getProfileAgentHandler(w http.ResponseWriter, r *http.Request)
} }
} }
// @Summary Обновить профиль агента
// @Description Обновление профиля агента
// @Tags agents
// @Accept json
// @Produce json
// @Param agent_id path string true "ID агента"
// @Param request body rmodel.ProfileUpdateRequest true "Данные для обновления профиля"
// @Success 200 {object} map[string]string "Профиль обновлен"
// @Failure 400 {object} map[string]string "Неверные данные запроса"
// @Failure 500 {object} map[string]string "Внутренняя ошибка сервера"
// @Security BearerAuth
// @Router /api/v1/agents/{agent_id}/profile [put]
func (h *handler) updateProfileAgentHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) updateProfileAgentHandler(w http.ResponseWriter, r *http.Request) {
const handlerName = "setAgentProfileHandler" const handlerName = "setAgentProfileHandler"
@@ -86,6 +109,17 @@ func (h *handler) updateProfileAgentHandler(w http.ResponseWriter, r *http.Reque
w.WriteHeader(http.StatusNoContent) w.WriteHeader(http.StatusNoContent)
} }
// @Summary Получить профиль дистрибьютора
// @Description Получение профиля дистрибьютора по ID
// @Tags distributors
// @Accept json
// @Produce json
// @Param distributor_id path string true "ID дистрибьютора"
// @Success 200 {object} rmodel.ProfileGetResponse "Профиль дистрибьютора"
// @Failure 400 {object} map[string]string "Неверные параметры запроса"
// @Failure 500 {object} map[string]string "Внутренняя ошибка сервера"
// @Security BearerAuth
// @Router /api/v1/distributor/{distributor_id}/profile [get]
func (h *handler) getProfileDisributorHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) getProfileDisributorHandler(w http.ResponseWriter, r *http.Request) {
const handlerName = "getProfileDisributorHandler" const handlerName = "getProfileDisributorHandler"
@@ -118,6 +152,18 @@ func (h *handler) getProfileDisributorHandler(w http.ResponseWriter, r *http.Req
} }
} }
// @Summary Обновить профиль дистрибьютора
// @Description Обновление профиля дистрибьютора
// @Tags distributors
// @Accept json
// @Produce json
// @Param distributor_id path string true "ID дистрибьютора"
// @Param request body rmodel.ProfileUpdateRequest true "Данные для обновления профиля"
// @Success 200 {object} map[string]string "Профиль обновлен"
// @Failure 400 {object} map[string]string "Неверные данные запроса"
// @Failure 500 {object} map[string]string "Внутренняя ошибка сервера"
// @Security BearerAuth
// @Router /api/v1/distributor/{distributor_id}/profile [put]
func (h *handler) updateProfileDistributorHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) updateProfileDistributorHandler(w http.ResponseWriter, r *http.Request) {
const handlerName = "updateProfileDistributorHandler" const handlerName = "updateProfileDistributorHandler"

View File

@@ -23,7 +23,9 @@ import (
formgenerator "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/form_generator" formgenerator "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/form_generator"
"git-molva.ru/Molva/molva-backend/services/api_gateway/internal/config" "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/config"
_ "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/http/swagger/docs"
"github.com/gorilla/mux" "github.com/gorilla/mux"
httpSwagger "github.com/swaggo/http-swagger"
) )
type Router struct { type Router struct {
@@ -200,6 +202,9 @@ func SetupRouter(r *Router, buildCfg config.BuildInfo) {
// --------------- FEED ------------ // --------------- FEED ------------
subRouter.HandleFunc("/feed/{uid}/events", h.GetUserEventsHandler).Methods(http.MethodGet) subRouter.HandleFunc("/feed/{uid}/events", h.GetUserEventsHandler).Methods(http.MethodGet)
// --------------- SWAGGER UI ------------
r.Mux.PathPrefix("/swagger/").Handler(httpSwagger.WrapHandler)
} }
func setupAuthHandlers(r *Router, h *handler) { func setupAuthHandlers(r *Router, h *handler) {

View File

@@ -18,6 +18,22 @@ import (
rmodel "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/request_model" rmodel "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/request_model"
) )
// @Summary Получить список заявок агента
// @Description Получение списка заявок агента с возможностью фильтрации
// @Tags agents
// @Accept json
// @Produce json
// @Param agent_id path string true "ID агента"
// @Param vacancy_id query string false "ID вакансии"
// @Param status query string false "Статус заявки"
// @Param page query int false "Номер страницы"
// @Param page_size query int false "Размер страницы"
// @Success 200 {object} rmodel.SubmissionListGetResponse "Список заявок"
// @Failure 400 {object} map[string]string "Неверные данные запроса"
// @Failure 401 {object} map[string]string "Неавторизованный доступ"
// @Failure 500 {object} map[string]string "Внутренняя ошибка сервера"
// @Security BearerAuth
// @Router /api/v1/agents/{agent_id}/submissions [get]
func (h *handler) getSubmissionListAgentHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) getSubmissionListAgentHandler(w http.ResponseWriter, r *http.Request) {
const handlerName = "getSubmissionListAgentHandler" const handlerName = "getSubmissionListAgentHandler"
@@ -58,6 +74,20 @@ func (h *handler) getSubmissionListAgentHandler(w http.ResponseWriter, r *http.R
} }
} }
// @Summary Получить CV заявки
// @Description Получение CV файла заявки
// @Tags agents
// @Accept json
// @Produce application/octet-stream
// @Param agent_id path string true "ID агента"
// @Param submission_id path string true "ID заявки"
// @Success 200 {file} file "CV файл"
// @Failure 400 {object} map[string]string "Неверные данные запроса"
// @Failure 401 {object} map[string]string "Неавторизованный доступ"
// @Failure 404 {object} map[string]string "CV не найден"
// @Failure 500 {object} map[string]string "Внутренняя ошибка сервера"
// @Security BearerAuth
// @Router /api/v1/agents/{agent_id}/submissions/{submission_id}/cv [get]
func (h *handler) getSubmissionCVHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) getSubmissionCVHandler(w http.ResponseWriter, r *http.Request) {
const handlerName = "getSubmissionCVHandler" const handlerName = "getSubmissionCVHandler"
@@ -121,6 +151,20 @@ func (h *handler) getSubmissionCVHandler(w http.ResponseWriter, r *http.Request)
} }
} }
// @Summary Удалить заявку агента
// @Description Удаление заявки агента
// @Tags agents
// @Accept json
// @Produce json
// @Param agent_id path string true "ID агента"
// @Param submission_id path string true "ID заявки"
// @Success 204 "Заявка удалена"
// @Failure 400 {object} map[string]string "Неверные данные запроса"
// @Failure 401 {object} map[string]string "Неавторизованный доступ"
// @Failure 404 {object} map[string]string "Заявка не найдена"
// @Failure 500 {object} map[string]string "Внутренняя ошибка сервера"
// @Security BearerAuth
// @Router /api/v1/agents/{agent_id}/submissions/{submission_id} [delete]
func (h *handler) deleteSubmissionAgentHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) deleteSubmissionAgentHandler(w http.ResponseWriter, r *http.Request) {
const handlerName = "deleteSubmissionHandler" const handlerName = "deleteSubmissionHandler"
@@ -162,6 +206,22 @@ func (h *handler) deleteSubmissionAgentHandler(w http.ResponseWriter, r *http.Re
} }
} }
// @Summary Получить список заявок дистрибьютора
// @Description Получение списка заявок дистрибьютора с возможностью фильтрации
// @Tags distributors
// @Accept json
// @Produce json
// @Param distributor_id path string true "ID дистрибьютора"
// @Param vacancy_id path string true "ID вакансии"
// @Param status query string false "Статус заявки"
// @Param page query int false "Номер страницы"
// @Param page_size query int false "Размер страницы"
// @Success 200 {object} rmodel.SubmissionListGetResponse "Список заявок"
// @Failure 400 {object} map[string]string "Неверные данные запроса"
// @Failure 401 {object} map[string]string "Неавторизованный доступ"
// @Failure 500 {object} map[string]string "Внутренняя ошибка сервера"
// @Security BearerAuth
// @Router /api/v1/distributor/{distributor_id}/vacancies/{vacancy_id}/submissions [get]
func (h *handler) getSubmissionListDistributorHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) getSubmissionListDistributorHandler(w http.ResponseWriter, r *http.Request) {
const handlerName = "getSubmissionsDistributorHandler" const handlerName = "getSubmissionsDistributorHandler"
@@ -205,6 +265,22 @@ func (h *handler) getSubmissionListDistributorHandler(w http.ResponseWriter, r *
} }
} }
// @Summary Обновить статус заявки
// @Description Обновление статуса заявки дистрибьютором
// @Tags distributors
// @Accept json
// @Produce json
// @Param distributor_id path string true "ID дистрибьютора"
// @Param vacancy_id path string true "ID вакансии"
// @Param submission_id path string true "ID заявки"
// @Param request body rmodel.SubmissionStatusUpdateRequest true "Новый статус заявки"
// @Success 200 "Статус обновлен"
// @Failure 400 {object} map[string]string "Неверные данные запроса"
// @Failure 401 {object} map[string]string "Неавторизованный доступ"
// @Failure 404 {object} map[string]string "Заявка не найдена"
// @Failure 500 {object} map[string]string "Внутренняя ошибка сервера"
// @Security BearerAuth
// @Router /api/v1/distributor/{distributor_id}/vacancies/{vacancy_id}/submissions/{submission_id}/status [post]
func (h *handler) updateSubmissionStatusDistributorHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) updateSubmissionStatusDistributorHandler(w http.ResponseWriter, r *http.Request) {
const handlerName = "updateSubmissionStatusDistributorHandler" const handlerName = "updateSubmissionStatusDistributorHandler"
@@ -243,6 +319,17 @@ func (h *handler) updateSubmissionStatusDistributorHandler(w http.ResponseWriter
w.WriteHeader(http.StatusNoContent) w.WriteHeader(http.StatusNoContent)
} }
// @Summary Отправить анкету
// @Description Отправка заполненной анкеты клиента
// @Tags clients
// @Accept json
// @Produce json
// @Param request body map[string]interface{} true "Данные анкеты"
// @Success 201 {object} map[string]string "Анкета отправлена"
// @Failure 400 {object} map[string]string "Неверные данные запроса"
// @Failure 500 {object} map[string]string "Внутренняя ошибка сервера"
// @Router /api/v1/anketa [post]
//
//nolint:funlen // TODO: refactor //nolint:funlen // TODO: refactor
func (h *handler) postAnketaHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) postAnketaHandler(w http.ResponseWriter, r *http.Request) {
handlerName := "postAnketaHandler" handlerName := "postAnketaHandler"

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,14 @@
package swagger
// ErrorResponse представляет стандартный ответ об ошибке
type ErrorResponse struct {
Error string `json:"error" example:"Bad Request"`
Message string `json:"message" example:"Invalid request parameters"`
Code int `json:"code" example:"400"`
}
// SuccessResponse представляет стандартный ответ об успехе
type SuccessResponse struct {
Message string `json:"message" example:"Operation completed successfully"`
Code int `json:"code" example:"200"`
}

View File

@@ -34,6 +34,27 @@ func (h *handler) setVacancyLogoLinks(
} }
} }
// @Summary Получить список вакансий для агента
// @Description Получение списка вакансий с возможностью фильтрации
// @Tags agents
// @Accept json
// @Produce json
// @Param agent_id path string true "ID агента"
// @Param distributor_id query string false "ID дистрибьютора"
// @Param company_id query string false "ID компании"
// @Param region query string false "Регион"
// @Param salary_bottom query int false "Минимальная зарплата"
// @Param salary_top query int false "Максимальная зарплата"
// @Param is_archived query bool false "Архивные вакансии"
// @Param status query string false "Статус вакансии"
// @Param page query int false "Номер страницы"
// @Param page_size query int false "Размер страницы"
// @Success 200 {object} rmodel.VacancyListGetResponse "Список вакансий"
// @Failure 400 {object} map[string]string "Неверные данные запроса"
// @Failure 401 {object} map[string]string "Неавторизованный доступ"
// @Failure 500 {object} map[string]string "Внутренняя ошибка сервера"
// @Security BearerAuth
// @Router /api/v1/agents/{agent_id}/vacancies [get]
func (h *handler) getVacancyListAgentHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) getVacancyListAgentHandler(w http.ResponseWriter, r *http.Request) {
const handlerName = "getVacancyListAgentHandler" const handlerName = "getVacancyListAgentHandler"
@@ -71,6 +92,26 @@ func (h *handler) getVacancyListAgentHandler(w http.ResponseWriter, r *http.Requ
} }
} }
// @Summary Получить список вакансий дистрибьютора
// @Description Получение списка вакансий дистрибьютора с возможностью фильтрации
// @Tags distributors
// @Accept json
// @Produce json
// @Param distributor_id path string true "ID дистрибьютора"
// @Param company_id query string false "ID компании"
// @Param region query string false "Регион"
// @Param salary_bottom query int false "Минимальная зарплата"
// @Param salary_top query int false "Максимальная зарплата"
// @Param is_archived query bool false "Архивные вакансии"
// @Param status query string false "Статус вакансии"
// @Param page query int false "Номер страницы"
// @Param page_size query int false "Размер страницы"
// @Success 200 {object} rmodel.VacancyListGetResponse "Список вакансий"
// @Failure 400 {object} map[string]string "Неверные данные запроса"
// @Failure 401 {object} map[string]string "Неавторизованный доступ"
// @Failure 500 {object} map[string]string "Внутренняя ошибка сервера"
// @Security BearerAuth
// @Router /api/v1/distributor/{distributor_id}/vacancies [get]
func (h *handler) getVacancyListDistributorHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) getVacancyListDistributorHandler(w http.ResponseWriter, r *http.Request) {
const handlerName = "getVacancyListDistributorHandler" const handlerName = "getVacancyListDistributorHandler"
@@ -106,6 +147,19 @@ func (h *handler) getVacancyListDistributorHandler(w http.ResponseWriter, r *htt
} }
} }
// @Summary Создать вакансию
// @Description Создание новой вакансии дистрибьютором
// @Tags distributors
// @Accept json
// @Produce json
// @Param distributor_id path string true "ID дистрибьютора"
// @Param request body rmodel.VacancyCreateRequest true "Данные для создания вакансии"
// @Success 201 {object} rmodel.VacancyCreateResponse "Вакансия создана"
// @Failure 400 {object} map[string]string "Неверные данные запроса"
// @Failure 401 {object} map[string]string "Неавторизованный доступ"
// @Failure 500 {object} map[string]string "Внутренняя ошибка сервера"
// @Security BearerAuth
// @Router /api/v1/distributor/{distributor_id}/vacancies [post]
func (h *handler) createVacancyDistributorHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) createVacancyDistributorHandler(w http.ResponseWriter, r *http.Request) {
const handlerName = "createVacancyDistributorHandler" const handlerName = "createVacancyDistributorHandler"
@@ -158,6 +212,21 @@ func (h *handler) createVacancyDistributorHandler(w http.ResponseWriter, r *http
} }
} }
// @Summary Обновить вакансию
// @Description Обновление информации о вакансии дистрибьютора
// @Tags distributors
// @Accept json
// @Produce json
// @Param distributor_id path string true "ID дистрибьютора"
// @Param vacancy_id path string true "ID вакансии"
// @Param request body rmodel.VacancyUpdateRequest true "Данные для обновления"
// @Success 204 "Вакансия обновлена"
// @Failure 400 {object} map[string]string "Неверные данные запроса"
// @Failure 401 {object} map[string]string "Неавторизованный доступ"
// @Failure 404 {object} map[string]string "Вакансия не найдена"
// @Failure 500 {object} map[string]string "Внутренняя ошибка сервера"
// @Security BearerAuth
// @Router /api/v1/distributor/{distributor_id}/vacancies/{vacancy_id} [patch]
func (h *handler) updateVacancyDistributorHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) updateVacancyDistributorHandler(w http.ResponseWriter, r *http.Request) {
const handlerName = "updateVacancyDistributorHandler" const handlerName = "updateVacancyDistributorHandler"
@@ -201,6 +270,20 @@ func (h *handler) updateVacancyDistributorHandler(w http.ResponseWriter, r *http
w.WriteHeader(http.StatusNoContent) w.WriteHeader(http.StatusNoContent)
} }
// @Summary Удалить вакансию
// @Description Удаление вакансии дистрибьютора
// @Tags distributors
// @Accept json
// @Produce json
// @Param distributor_id path string true "ID дистрибьютора"
// @Param vacancy_id path string true "ID вакансии"
// @Success 204 "Вакансия удалена"
// @Failure 400 {object} map[string]string "Неверные данные запроса"
// @Failure 401 {object} map[string]string "Неавторизованный доступ"
// @Failure 404 {object} map[string]string "Вакансия не найдена"
// @Failure 500 {object} map[string]string "Внутренняя ошибка сервера"
// @Security BearerAuth
// @Router /api/v1/distributor/{distributor_id}/vacancies/{vacancy_id} [delete]
func (h *handler) deleteVacancyDistributorHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) deleteVacancyDistributorHandler(w http.ResponseWriter, r *http.Request) {
const handlerName = "deleteDistributorVacancyHandler" const handlerName = "deleteDistributorVacancyHandler"
@@ -235,6 +318,18 @@ func (h *handler) deleteVacancyDistributorHandler(w http.ResponseWriter, r *http
w.WriteHeader(http.StatusNoContent) w.WriteHeader(http.StatusNoContent)
} }
// @Summary Отправить вакансию на модерацию
// @Description Отправка вакансии дистрибьютора на модерацию
// @Tags distributors
// @Accept json
// @Produce json
// @Param distributor_id path string true "ID дистрибьютора"
// @Param vacancy_id path string true "ID вакансии"
// @Success 200 {object} map[string]string "Вакансия отправлена на модерацию"
// @Failure 400 {object} map[string]string "Неверные параметры запроса"
// @Failure 500 {object} map[string]string "Внутренняя ошибка сервера"
// @Security BearerAuth
// @Router /api/v1/distributor/{distributor_id}/vacancies/{vacancy_id}/moderation [post]
func (h *handler) sendVacancyToModerationHandler(w http.ResponseWriter, r *http.Request) { func (h *handler) sendVacancyToModerationHandler(w http.ResponseWriter, r *http.Request) {
const handlerName = "sendVacancyToModerationHandler" const handlerName = "sendVacancyToModerationHandler"