Files
test_deploy/internal/http/vacancy.go
Alex Shevchuk 61fc0d2747
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
71
2025-09-17 14:32:06 +03:00

363 lines
13 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package http_router
import (
"context"
"encoding/json"
"log/slog"
"net/http"
"git-molva.ru/Molva/molva-backend/services/api_gateway/internal/constants"
rmodel "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/request_model"
"github.com/gorilla/mux"
)
// TODO: review
func (h *handler) setVacancyLogoLinks(
ctx context.Context,
vacancyList *rmodel.VacancyListGetResponse,
) {
const handlerName = "setVacancyLogoLinks"
for _, vacancy := range vacancyList.Vacancies {
logoLink, err := h.getLogoLinkWithCache(ctx, vacancy.Company.Id)
if err != nil {
h.logger.Warn("error getting logo link",
slog.String("error", err.Error()),
slog.String("vacancy_id", vacancy.Id),
slog.String("handler", handlerName),
)
continue
}
vacancy.Company.LogoLink = &logoLink
}
}
// @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) {
const handlerName = "getVacancyListAgentHandler"
request, err := new(rmodel.VacancyListGetRequest).FromQuery(r.URL.Query())
if err != nil {
http.Error(w, constants.ErrBadRequest.Error(), http.StatusBadRequest)
h.logger.Error("error parsing request: ",
slog.String("error", err.Error()),
slog.String("handler", handlerName))
return
}
result, err := h.agentService.GetVacancyList(r.Context(), request)
if err != nil {
h.handleAgentError(w, err)
h.logger.Error("error getting vacancy list",
slog.String("error", err.Error()),
slog.String("handler", handlerName),
)
return
}
h.setVacancyLogoLinks(r.Context(), result)
w.Header().Set("Content-Type", "application/json")
if err := json.NewEncoder(w).Encode(result); err != nil {
http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError)
h.logger.Error("error encoding response",
slog.String("error", err.Error()),
slog.String("handler", handlerName),
)
}
}
// @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) {
const handlerName = "getVacancyListDistributorHandler"
request, err := new(rmodel.VacancyListGetRequest).FromQuery(r.URL.Query())
if err != nil {
http.Error(w, constants.ErrBadRequest.Error(), http.StatusBadRequest)
h.logger.Error("error parsing request: ",
slog.String("error", err.Error()),
slog.String("handler", handlerName))
return
}
result, err := h.distributorService.GetVacancyList(r.Context(), request)
if err != nil {
h.handleDistributorError(w, err)
h.logger.Error("error getting vacancy list",
slog.String("error", err.Error()),
slog.String("handler", handlerName),
)
return
}
w.Header().Set("Content-Type", "application/json")
if err := json.NewEncoder(w).Encode(result); err != nil {
http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError)
h.logger.Error("error encoding response",
slog.String("error", err.Error()),
slog.String("handler", handlerName),
)
}
}
// @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) {
const handlerName = "createVacancyDistributorHandler"
var (
vars = mux.Vars(r)
distId = vars["distributor_id"]
)
var request rmodel.VacancyCreateRequest
if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
http.Error(w, constants.ErrBadRequest.Error(), http.StatusBadRequest)
h.logger.Error("error unmarshalling request: ",
slog.String("error", err.Error()),
slog.String("handler", handlerName))
return
}
defer r.Body.Close()
result, err := h.distributorService.CreateVacancy(r.Context(), &request)
if err != nil {
h.handleDistributorError(w, err)
h.logger.Error("error creating vacancy",
slog.String("error", err.Error()),
slog.String("handler", handlerName),
)
return
}
go h.createSetDistributorVacancyEvent(
context.Background(),
distId,
result.Id,
request.Name,
handlerName,
)
w.WriteHeader(http.StatusCreated)
w.Header().Set("Content-Type", "application/json")
if err := json.NewEncoder(w).Encode(result); err != nil {
http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError)
h.logger.Error("error encoding response",
slog.String("error", err.Error()),
slog.String("handler", handlerName),
)
}
}
// @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) {
const handlerName = "updateVacancyDistributorHandler"
var (
vars = mux.Vars(r)
distId = vars["distributor_id"]
vacancyId = vars["vacancy_id"]
)
var request rmodel.VacancyUpdateRequest
if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
http.Error(w, constants.ErrBadRequest.Error(), http.StatusBadRequest)
h.logger.Error("error unmarshalling request: ",
slog.String("error", err.Error()),
slog.String("handler", handlerName),
)
return
}
request.Id = vacancyId
if _, err := h.distributorService.UpdateVacancy(r.Context(), &request); err != nil {
h.handleDistributorError(w, err)
h.logger.Error("error updating vacancy",
slog.String("error", err.Error()),
slog.String("handler", handlerName),
)
return
}
go h.createEditDistributorVacancyEvent(
context.Background(),
distId,
vacancyId,
handlerName,
)
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) {
const handlerName = "deleteDistributorVacancyHandler"
var (
vars = mux.Vars(r)
distId = vars["distributor_id"]
vacancyId = vars["vacancy_id"]
)
if _, err := h.distributorService.DeleteVacancy(r.Context(), &rmodel.VacancyDeleteRequest{
Id: vacancyId,
}); err != nil {
h.handleDistributorError(w, err)
h.logger.Error("error deleting vacancy",
slog.String("error", err.Error()),
slog.String("handler", handlerName),
)
return
}
go func(hdn *handler) {
if err := h.feed.CancelEvent(r.Context(), vacancyId, "Вакансия была удалена"); err != nil {
h.logger.Error("failed to cancel feed event",
slog.String("error", err.Error()),
slog.String("handler", handlerName),
slog.String("vacancy_id", vacancyId),
slog.String("distributor_id", distId))
}
}(h)
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) {
const handlerName = "sendVacancyToModerationHandler"
var (
vars = mux.Vars(r)
distId = vars["distributor_id"]
vacancyId = vars["vacancy_id"]
)
if _, err := h.distributorService.SendVacancyToModeration(r.Context(), &rmodel.SendVacancyToModerationRequest{
Id: vacancyId,
}); err != nil {
h.handleDistributorError(w, err)
h.logger.Error("error sending vacancy to moderation",
slog.String("error", err.Error()),
slog.String("handler", handlerName),
)
return
}
go h.createSendVacancyToModerationEvent(
context.Background(),
distId,
vacancyId,
handlerName,
)
w.WriteHeader(http.StatusNoContent)
}