package http_router import ( "context" "encoding/json" "errors" "log/slog" "net/http" "strings" "time" "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/constants" "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/integration" "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/types" "github.com/gorilla/mux" filemanager "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/file_manager" rmodel "git-molva.ru/Molva/molva-backend/services/api_gateway/internal/request_model" ) func (h *handler) getSubmissionListAgentHandler(w http.ResponseWriter, r *http.Request) { const handlerName = "getSubmissionListAgentHandler" var ( vars = mux.Vars(r) agentId = vars["agent_id"] ) request, err := new(rmodel.SubmissionListGetRequest).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 } request.AgentId = agentId result, err := h.agentService.GetSubmissionList(r.Context(), request) if err != nil { h.handleAgentError(w, err) h.logger.Error("error getting submission list", slog.String("error", err.Error()), slog.String("handler", handlerName), ) } 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), ) } } func (h *handler) getSubmissionCVHandler(w http.ResponseWriter, r *http.Request) { const handlerName = "getSubmissionCVHandler" var ( vars = mux.Vars(r) submissionId = vars["submission_id"] ) params := filemanager.ParameterTable{ filemanager.SubmissionIdParam: submissionId, } urls, err := h.fileManager.GetFilePaths(r.Context(), filemanager.CVFileType, params) if err != nil { if errors.Is(err, filemanager.ErrFileNotFound) { http.Error(w, constants.ErrNotFound.Error(), http.StatusNotFound) h.logger.Error("CV file not found", slog.String("error", err.Error()), slog.String("submissionId", submissionId), slog.String("handler", handlerName)) return } http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError) h.logger.Error("error while getting file URLs: ", slog.String("error", err.Error()), slog.String("submissionId", submissionId), slog.String("handler", handlerName)) return } if len(urls) == 0 { http.Error(w, constants.ErrNotFound.Error(), http.StatusNotFound) h.logger.Error("No CV URLs found", slog.String("submissionId", submissionId), slog.String("handler", handlerName)) return } response := types.CVURLResponse{ URL: urls[0], SubmissionID: submissionId, ExpiresAt: time.Now().Add(constants.DefaultFileTTL - time.Hour), } h.logger.Debug("CV URL retrieved successfully", slog.String("submissionId", submissionId), slog.String("handler", handlerName)) w.Header().Set("Content-Type", "application/json") if err := json.NewEncoder(w).Encode(response); err != nil { http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError) h.logger.Error("error encoding response: ", slog.String("error", err.Error()), slog.String("submissionId", submissionId), slog.String("handler", handlerName)) } } func (h *handler) deleteSubmissionAgentHandler(w http.ResponseWriter, r *http.Request) { const handlerName = "deleteSubmissionHandler" var ( vars = mux.Vars(r) submissionId = vars["submission_id"] ) result, err := h.agentService.DeleteSubmission(r.Context(), &rmodel.SubmissionDeleteRequest{ Id: submissionId, }) if err != nil { h.handleAgentError(w, err) h.logger.Error("error deleting submission", slog.String("error", err.Error()), slog.String("handler", handlerName), ) return } go func() { if err := h.feed.CancelEvent(r.Context(), submissionId, "Отклик был удален"); err != nil { http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError) h.logger.Error("error cancelling event: ", slog.String("error", err.Error()), slog.String("handler", handlerName)) } }() 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), ) } } func (h *handler) getSubmissionListDistributorHandler(w http.ResponseWriter, r *http.Request) { const handlerName = "getSubmissionsDistributorHandler" var ( vars = mux.Vars(r) vacancyId = vars["vacancy_id"] ) request, err := new(rmodel.SubmissionListForVacancyGetRequest).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 } request.VacancyId = vacancyId result, err := h.distributorService.GetSubmissionListForVacancy(r.Context(), request) if err != nil { h.handleDistributorError(w, err) h.logger.Error("error getting submissions for vacancy", 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), ) } } func (h *handler) updateSubmissionStatusDistributorHandler(w http.ResponseWriter, r *http.Request) { const handlerName = "updateSubmissionStatusDistributorHandler" var ( vars = mux.Vars(r) submissionId = vars["submission_id"] ) var request rmodel.SubmissionStatusUpdateRequest 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 = submissionId if _, err := h.distributorService.UpdateSubmissionStatus(r.Context(), &request); err != nil { h.handleDistributorError(w, err) h.logger.Error("error updating submission status", slog.String("error", err.Error()), slog.String("handler", handlerName), ) return } // TODO: // h.createSetSubmissionStatusFeedEvent(r.Context(), distId, submissionId, status.Status, handlerName) w.WriteHeader(http.StatusNoContent) } //nolint:funlen // TODO: refactor func (h *handler) postAnketaHandler(w http.ResponseWriter, r *http.Request) { handlerName := "postAnketaHandler" var ( agentID = r.FormValue("agent_id") vacancyID = r.FormValue("vacancy_id") cvLink = r.FormValue("cv") name = r.FormValue("name") phone = r.FormValue("phone_number") email = r.FormValue("email") birthday = r.FormValue("birthday") info = r.FormValue("info") firstName, lastName, middleName = splitName(name) ) result, err := h.agentService.CreateSubmission(r.Context(), &rmodel.SubmissionCreateRequest{ AgentId: agentID, VacancyId: vacancyID, CandidateInfo: &rmodel.CandidateInfo{ FirstName: firstName, LastName: lastName, MiddleName: middleName, PhoneNumber: phone, Email: email, Birthday: birthday, CvLink: &cvLink, Resume: &info, }, }) if err != nil { h.handleAgentError(w, err) h.logger.Error("error creating submission", slog.String("error", err.Error()), slog.String("handler", handlerName)) return } file, header, err := r.FormFile("cv_file") if err == nil { params := filemanager.ParameterTable{ filemanager.SubmissionIdParam: result.Id, } if err := h.fileManager.SaveFile( r.Context(), filemanager.CVFileType, file, header, params, ); err != nil { http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError) h.logger.Error("error saving CV to file storage: ", slog.String("error", err.Error()), slog.String("handler", handlerName)) return } } else if header != nil { // CV is provided, but there are other errors http.Error(w, constants.ErrInternalServerError.Error(), http.StatusInternalServerError) h.logger.Error("error while extracting CV from request: ", slog.String("error", err.Error()), slog.String("handler", handlerName)) } go h.createPostAnketaEvent( context.Background(), agentID, result.Id, handlerName, ) go func() { if err := h.integrationClient.HandleVacancyResponse(integration.HandleVacancy{ AgentId: agentID, VacancyId: vacancyID, SourceLid: r.URL.RawPath, Candidate: integration.Candidate{ Id: result.Id, Name: name, Email: email, Phone: phone, Birthday: birthday, Info: info, CvLink: cvLink, }, }); err != nil { h.logger.Error("error while handling vacancy response integration", slog.String("error", err.Error()), slog.String("agent_id", agentID), slog.String("vacancy_id", vacancyID), slog.String("submission_id", result.Id), slog.String("handler", handlerName), ) } }() 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)) } } func splitName(name string) (string, string, string) { var ( parts = strings.SplitN(name, " ", 3) lastName, firstName, middleName string ) if len(parts) > 0 { lastName = parts[0] } if len(parts) > 1 { firstName = parts[1] } if len(parts) > 2 { middleName = parts[2] } return lastName, firstName, middleName }