package handlers import ( "encoding/json" "net/http" "mgit.msbls.de/m/KanzlAI-mGMT/internal/auth" "mgit.msbls.de/m/KanzlAI-mGMT/internal/services" ) // DeadlineHandlers holds handlers for deadline CRUD endpoints type DeadlineHandlers struct { deadlines *services.DeadlineService } // NewDeadlineHandlers creates deadline handlers func NewDeadlineHandlers(ds *services.DeadlineService) *DeadlineHandlers { return &DeadlineHandlers{deadlines: ds} } // Get handles GET /api/deadlines/{deadlineID} func (h *DeadlineHandlers) Get(w http.ResponseWriter, r *http.Request) { tenantID, ok := auth.TenantFromContext(r.Context()) if !ok { writeError(w, http.StatusForbidden, "missing tenant") return } deadlineID, err := parsePathUUID(r, "deadlineID") if err != nil { writeError(w, http.StatusBadRequest, "invalid deadline ID") return } deadline, err := h.deadlines.GetByID(tenantID, deadlineID) if err != nil { internalError(w, "failed to fetch deadline", err) return } if deadline == nil { writeError(w, http.StatusNotFound, "deadline not found") return } writeJSON(w, http.StatusOK, deadline) } // ListAll handles GET /api/deadlines func (h *DeadlineHandlers) ListAll(w http.ResponseWriter, r *http.Request) { tenantID, ok := auth.TenantFromContext(r.Context()) if !ok { writeError(w, http.StatusForbidden, "missing tenant") return } deadlines, err := h.deadlines.ListAll(tenantID) if err != nil { internalError(w, "failed to list deadlines", err) return } writeJSON(w, http.StatusOK, deadlines) } // ListForCase handles GET /api/cases/{caseID}/deadlines func (h *DeadlineHandlers) ListForCase(w http.ResponseWriter, r *http.Request) { tenantID, ok := auth.TenantFromContext(r.Context()) if !ok { writeError(w, http.StatusForbidden, "missing tenant") return } caseID, err := parsePathUUID(r, "caseID") if err != nil { writeError(w, http.StatusBadRequest, "invalid case ID") return } deadlines, err := h.deadlines.ListForCase(tenantID, caseID) if err != nil { internalError(w, "failed to list deadlines for case", err) return } writeJSON(w, http.StatusOK, deadlines) } // Create handles POST /api/cases/{caseID}/deadlines func (h *DeadlineHandlers) Create(w http.ResponseWriter, r *http.Request) { tenantID, ok := auth.TenantFromContext(r.Context()) if !ok { writeError(w, http.StatusForbidden, "missing tenant") return } caseID, err := parsePathUUID(r, "caseID") if err != nil { writeError(w, http.StatusBadRequest, "invalid case ID") return } var input services.CreateDeadlineInput if err := json.NewDecoder(r.Body).Decode(&input); err != nil { writeError(w, http.StatusBadRequest, "invalid request body") return } input.CaseID = caseID if input.Title == "" || input.DueDate == "" { writeError(w, http.StatusBadRequest, "title and due_date are required") return } if msg := validateStringLength("title", input.Title, maxTitleLen); msg != "" { writeError(w, http.StatusBadRequest, msg) return } deadline, err := h.deadlines.Create(r.Context(), tenantID, input) if err != nil { internalError(w, "failed to create deadline", err) return } writeJSON(w, http.StatusCreated, deadline) } // Update handles PUT /api/deadlines/{deadlineID} func (h *DeadlineHandlers) Update(w http.ResponseWriter, r *http.Request) { tenantID, ok := auth.TenantFromContext(r.Context()) if !ok { writeError(w, http.StatusForbidden, "missing tenant") return } deadlineID, err := parsePathUUID(r, "deadlineID") if err != nil { writeError(w, http.StatusBadRequest, "invalid deadline ID") return } var input services.UpdateDeadlineInput if err := json.NewDecoder(r.Body).Decode(&input); err != nil { writeError(w, http.StatusBadRequest, "invalid request body") return } deadline, err := h.deadlines.Update(r.Context(), tenantID, deadlineID, input) if err != nil { internalError(w, "failed to update deadline", err) return } if deadline == nil { writeError(w, http.StatusNotFound, "deadline not found") return } writeJSON(w, http.StatusOK, deadline) } // Complete handles PATCH /api/deadlines/{deadlineID}/complete func (h *DeadlineHandlers) Complete(w http.ResponseWriter, r *http.Request) { tenantID, ok := auth.TenantFromContext(r.Context()) if !ok { writeError(w, http.StatusForbidden, "missing tenant") return } deadlineID, err := parsePathUUID(r, "deadlineID") if err != nil { writeError(w, http.StatusBadRequest, "invalid deadline ID") return } deadline, err := h.deadlines.Complete(r.Context(), tenantID, deadlineID) if err != nil { internalError(w, "failed to complete deadline", err) return } if deadline == nil { writeError(w, http.StatusNotFound, "deadline not found") return } writeJSON(w, http.StatusOK, deadline) } // Delete handles DELETE /api/deadlines/{deadlineID} func (h *DeadlineHandlers) Delete(w http.ResponseWriter, r *http.Request) { tenantID, ok := auth.TenantFromContext(r.Context()) if !ok { writeError(w, http.StatusForbidden, "missing tenant") return } deadlineID, err := parsePathUUID(r, "deadlineID") if err != nil { writeError(w, http.StatusBadRequest, "invalid deadline ID") return } <<<<<<< HEAD err = h.deadlines.Delete(r.Context(), tenantID, deadlineID) if err != nil { writeError(w, http.StatusNotFound, err.Error()) ||||||| 8e65463 <<<<<<< HEAD if err := h.deadlines.Delete(tenantID, deadlineID); err != nil { writeError(w, http.StatusNotFound, "deadline not found") ||||||| 82878df err = h.deadlines.Delete(tenantID, deadlineID) if err != nil { writeError(w, http.StatusNotFound, err.Error()) ======= err = h.deadlines.Delete(r.Context(), tenantID, deadlineID) if err != nil { writeError(w, http.StatusNotFound, err.Error()) >>>>>>> mai/knuth/p0-audit-trail-append ======= if err := h.deadlines.Delete(r.Context(), tenantID, deadlineID); err != nil { writeError(w, http.StatusNotFound, "deadline not found") >>>>>>> mai/ritchie/p1-document-templates return } writeJSON(w, http.StatusOK, map[string]string{"status": "deleted"}) }