116 lines
3.5 KiB
Go
116 lines
3.5 KiB
Go
// Package caseoverviewapi ist die HTTP-Bindung der workflow-eigenen
|
|
// Akten-Uebersicht (VOR-05). Nutzeridentitaet kommt uebergangsweise aus
|
|
// X-User-Id, wie bereits bei caseapi (VOR-01) und backchannelapi (VOR-04)
|
|
// etabliert.
|
|
package caseoverviewapi
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"net/http"
|
|
"time"
|
|
|
|
"gitea.perlbach24.de/scripte/nexarch/workflow/internal/caseobj"
|
|
"gitea.perlbach24.de/scripte/nexarch/workflow/internal/caseoverview"
|
|
"gitea.perlbach24.de/scripte/nexarch/workflow/internal/reminder"
|
|
)
|
|
|
|
type Server struct {
|
|
svc *caseoverview.Service
|
|
now func() time.Time
|
|
}
|
|
|
|
func NewServer(svc *caseoverview.Service) *Server {
|
|
return &Server{svc: svc, now: time.Now}
|
|
}
|
|
|
|
// RegisterRoutes bindet die Uebersichts-Routen. Alle Routen verlangen
|
|
// X-User-Id, wie die uebrige workflow-eigene API.
|
|
func (s *Server) RegisterRoutes(mux *http.ServeMux) {
|
|
mux.HandleFunc("GET /cases", s.requireUser(s.handleList))
|
|
mux.HandleFunc("GET /cases/{id}/overview", s.requireUser(s.handleDetail))
|
|
mux.HandleFunc("GET /reminders/kanban", s.requireUser(s.handleKanban))
|
|
mux.HandleFunc("POST /reminders/{id}/move", s.requireUser(s.handleMove))
|
|
}
|
|
|
|
func (s *Server) requireUser(next func(w http.ResponseWriter, r *http.Request)) http.HandlerFunc {
|
|
return func(w http.ResponseWriter, r *http.Request) {
|
|
if r.Header.Get("X-User-Id") == "" {
|
|
writeError(w, http.StatusUnauthorized, "X-User-Id fehlt")
|
|
return
|
|
}
|
|
next(w, r)
|
|
}
|
|
}
|
|
|
|
func (s *Server) handleList(w http.ResponseWriter, r *http.Request) {
|
|
status := r.URL.Query().Get("status")
|
|
responsible := r.URL.Query().Get("responsible")
|
|
cases, err := s.svc.List(r.Context(), status, responsible)
|
|
if err != nil {
|
|
writeError(w, http.StatusInternalServerError, "akten konnten nicht gelesen werden")
|
|
return
|
|
}
|
|
if cases == nil {
|
|
cases = []caseobj.Case{}
|
|
}
|
|
writeJSON(w, http.StatusOK, cases)
|
|
}
|
|
|
|
func (s *Server) handleDetail(w http.ResponseWriter, r *http.Request) {
|
|
id := r.PathValue("id")
|
|
detail, err := s.svc.Detail(r.Context(), id)
|
|
switch {
|
|
case err == nil:
|
|
writeJSON(w, http.StatusOK, detail)
|
|
case errors.Is(err, caseobj.ErrNotFound):
|
|
writeError(w, http.StatusNotFound, "akte nicht gefunden")
|
|
default:
|
|
writeError(w, http.StatusInternalServerError, "akte konnte nicht gelesen werden")
|
|
}
|
|
}
|
|
|
|
func (s *Server) handleKanban(w http.ResponseWriter, r *http.Request) {
|
|
items, err := s.svc.Kanban(r.Context(), s.now())
|
|
if err != nil {
|
|
writeError(w, http.StatusInternalServerError, "wiedervorlagen konnten nicht gelesen werden")
|
|
return
|
|
}
|
|
if items == nil {
|
|
items = []caseoverview.KanbanItem{}
|
|
}
|
|
writeJSON(w, http.StatusOK, items)
|
|
}
|
|
|
|
type moveRequest struct {
|
|
Target string `json:"target"`
|
|
}
|
|
|
|
func (s *Server) handleMove(w http.ResponseWriter, r *http.Request) {
|
|
id := r.PathValue("id")
|
|
var req moveRequest
|
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
|
writeError(w, http.StatusBadRequest, "ungueltiger anfrage-koerper")
|
|
return
|
|
}
|
|
err := s.svc.Move(r.Context(), id, caseoverview.KanbanColumn(req.Target))
|
|
switch {
|
|
case err == nil:
|
|
w.WriteHeader(http.StatusNoContent)
|
|
case errors.Is(err, reminder.ErrNotFound):
|
|
writeError(w, http.StatusNotFound, "wiedervorlage nicht gefunden")
|
|
default:
|
|
writeError(w, http.StatusInternalServerError, "wiedervorlage konnte nicht verschoben werden")
|
|
}
|
|
}
|
|
|
|
func writeJSON(w http.ResponseWriter, status int, v any) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.WriteHeader(status)
|
|
_ = json.NewEncoder(w).Encode(v)
|
|
}
|
|
|
|
func writeError(w http.ResponseWriter, status int, message string) {
|
|
writeJSON(w, status, map[string]string{"error": message})
|
|
}
|