feat(m3): week close, overtime/undertime delta, frozen settings snapshot
This commit is contained in:
@@ -9,7 +9,7 @@ import (
|
||||
)
|
||||
|
||||
// NewRouter builds the full HTTP router.
|
||||
func NewRouter(authToken string, entrySvc *service.EntryService, daySvc *service.DayService, settingsSvc *service.SettingsService) http.Handler {
|
||||
func NewRouter(authToken string, entrySvc *service.EntryService, daySvc *service.DayService, settingsSvc *service.SettingsService, weekSvc *service.WeekService) http.Handler {
|
||||
r := chi.NewRouter()
|
||||
r.Use(middleware.RequestID)
|
||||
r.Use(middleware.RealIP)
|
||||
@@ -33,6 +33,9 @@ func NewRouter(authToken string, entrySvc *service.EntryService, daySvc *service
|
||||
|
||||
settingsH := NewSettingsHandler(settingsSvc)
|
||||
settingsH.Routes(r)
|
||||
|
||||
weekH := NewWeekHandler(weekSvc)
|
||||
weekH.Routes(r)
|
||||
})
|
||||
|
||||
return r
|
||||
|
||||
81
internal/handler/week_handler.go
Normal file
81
internal/handler/week_handler.go
Normal file
@@ -0,0 +1,81 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/wotra/wotra/internal/service"
|
||||
)
|
||||
|
||||
// WeekHandler serves /api/weeks routes.
|
||||
type WeekHandler struct {
|
||||
svc *service.WeekService
|
||||
}
|
||||
|
||||
func NewWeekHandler(svc *service.WeekService) *WeekHandler {
|
||||
return &WeekHandler{svc: svc}
|
||||
}
|
||||
|
||||
func (h *WeekHandler) Routes(r chi.Router) {
|
||||
r.Get("/weeks", h.List)
|
||||
r.Post("/weeks/{week_key}/close", h.Close)
|
||||
r.Delete("/weeks/{week_key}/close", h.Reopen)
|
||||
}
|
||||
|
||||
// List GET /api/weeks?from=YYYY-Www&to=YYYY-Www
|
||||
func (h *WeekHandler) List(w http.ResponseWriter, r *http.Request) {
|
||||
from := r.URL.Query().Get("from")
|
||||
to := r.URL.Query().Get("to")
|
||||
if from == "" {
|
||||
from = "0000-W01"
|
||||
}
|
||||
if to == "" {
|
||||
to = "9999-W53"
|
||||
}
|
||||
weeks, err := h.svc.ListWeeks(r.Context(), from, to)
|
||||
if err != nil {
|
||||
writeError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
if weeks == nil {
|
||||
writeJSON(w, http.StatusOK, []struct{}{})
|
||||
return
|
||||
}
|
||||
writeJSON(w, http.StatusOK, weeks)
|
||||
}
|
||||
|
||||
// Close POST /api/weeks/{week_key}/close
|
||||
func (h *WeekHandler) Close(w http.ResponseWriter, r *http.Request) {
|
||||
weekKey := chi.URLParam(r, "week_key")
|
||||
cw, err := h.svc.CloseWeek(r.Context(), weekKey)
|
||||
if err != nil {
|
||||
switch {
|
||||
case errors.Is(err, service.ErrWeekAlreadyClosed):
|
||||
writeError(w, http.StatusConflict, err.Error())
|
||||
case errors.Is(err, service.ErrWeekHasUnclosedDays):
|
||||
writeError(w, http.StatusUnprocessableEntity, err.Error())
|
||||
case errors.Is(err, service.ErrNoSettings):
|
||||
writeError(w, http.StatusUnprocessableEntity, err.Error())
|
||||
default:
|
||||
writeError(w, http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
writeJSON(w, http.StatusOK, cw)
|
||||
}
|
||||
|
||||
// Reopen DELETE /api/weeks/{week_key}/close
|
||||
func (h *WeekHandler) Reopen(w http.ResponseWriter, r *http.Request) {
|
||||
weekKey := chi.URLParam(r, "week_key")
|
||||
if err := h.svc.ReopenWeek(r.Context(), weekKey); err != nil {
|
||||
switch {
|
||||
case errors.Is(err, service.ErrWeekNotClosed):
|
||||
writeError(w, http.StatusNotFound, err.Error())
|
||||
default:
|
||||
writeError(w, http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
}
|
||||
Reference in New Issue
Block a user