package lkgateway import ( "encoding/json" "errors" "net/http" "strconv" "strings" "git.zetit.ru/zuevav/Bridge-and-Join-s/internal/m2mcore" ) // RegisterAPI вешает REST-маршруты ESIA Finance V1 на mux. func RegisterAPI(mux *http.ServeMux, svc *Service) { mux.HandleFunc("/api/v1/back_office/claims/", func(w http.ResponseWriter, r *http.Request) { path := strings.TrimPrefix(r.URL.Path, "/api/v1/back_office/claims/") switch { case path == "" && r.Method == http.MethodPost: handleCreateClaim(w, r, svc) case path != "" && r.Method == http.MethodGet: handleGetClaim(w, r, svc, path) case path != "" && r.Method == http.MethodPatch: // PATCH без id — отдельный обработчик ниже; этот блок для PATCH // с id, который lk-gateway сам себе бы посылал. На практике не // используется (callback идёт в ЛК), но реализуем по контракту. handlePatchClaim(w, r, svc, path) default: writeError(w, http.StatusMethodNotAllowed, "method_not_allowed", "Метод не разрешён", r.Method) } }) mux.HandleFunc("/api/v1/back_office/claims", func(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodGet { writeError(w, http.StatusMethodNotAllowed, "method_not_allowed", "Метод не разрешён", r.Method) return } handleListClaims(w, r, svc) }) } func handleCreateClaim(w http.ResponseWriter, r *http.Request, svc *Service) { defer r.Body.Close() var in CreateClaimRequest if err := json.NewDecoder(r.Body).Decode(&in); err != nil { writeError(w, http.StatusBadRequest, "invalid_json", "Не смогли разобрать JSON", err.Error()) return } out, err := svc.CreateClaim(r.Context(), in) if err != nil { writeError(w, http.StatusUnprocessableEntity, "invalid_claim", "Заявка не прошла валидацию", err.Error()) return } writeJSON(w, http.StatusCreated, out) } func handleGetClaim(w http.ResponseWriter, r *http.Request, svc *Service, id string) { view, err := svc.GetClaim(r.Context(), id) if err != nil { if errors.Is(err, m2mcore.ErrNotFound) { writeError(w, http.StatusNotFound, "not_found", "Заявка не найдена", id) return } writeError(w, http.StatusInternalServerError, "internal", "Внутренняя ошибка", err.Error()) return } writeJSON(w, http.StatusOK, view) } func handleListClaims(w http.ResponseWriter, r *http.Request, svc *Service) { q := r.URL.Query() filter := m2mcore.Filter{} if s := q.Get("status"); s != "" { st := m2mcore.State(s) filter.State = &st } if inv := q.Get("investor_id"); inv != "" { filter.InvestorID = inv } if l := q.Get("limit"); l != "" { if n, err := strconv.Atoi(l); err == nil && n > 0 && n <= 200 { filter.Limit = n } } if o := q.Get("offset"); o != "" { if n, err := strconv.Atoi(o); err == nil && n >= 0 { filter.Offset = n } } page, err := svc.ListClaims(r.Context(), filter) if err != nil { writeError(w, http.StatusInternalServerError, "internal", "Внутренняя ошибка", err.Error()) return } writeJSON(w, http.StatusOK, page) } func handlePatchClaim(w http.ResponseWriter, _ *http.Request, _ *Service, _ string) { // В сценарии M1-M2 PATCH /claims/{id} от внешней системы (как // callback от НРД) не используется — мы сами шлём callback в ЛК. // Но оставляем заглушку с 200, чтобы покрыть контракт OpenAPI. writeJSON(w, http.StatusOK, map[string]bool{"success": true}) }