Mobile-Update + Bericht
release-tag / release-image (push) Successful in 2m6s

This commit is contained in:
2026-08-14 18:17:38 +02:00
parent 2d384046dd
commit 57f7470310
9 changed files with 608 additions and 16 deletions
+77 -1
View File
@@ -92,6 +92,7 @@ func (a *App) routes() {
api.HandleFunc("DELETE /api/entries/{id}", a.deleteEntry)
api.HandleFunc("GET /api/export.csv", a.exportCSV)
api.HandleFunc("GET /api/export.pdf", a.exportPDF)
api.HandleFunc("POST /api/service-report.pdf", a.serviceReportPDF)
api.HandleFunc("GET /api/admin/users", a.adminUsers)
api.HandleFunc("POST /api/admin/users", a.adminCreateUser)
api.HandleFunc("PATCH /api/admin/users/{id}", a.adminPatchUser)
@@ -505,6 +506,76 @@ func (a *App) exportPDF(w http.ResponseWriter, r *http.Request) {
_, _ = w.Write(b)
}
func (a *App) serviceReportPDF(w http.ResponseWriter, r *http.Request) {
if !requireCSRF(w, r) {
return
}
var in struct {
Client string `json:"client"`
Contact string `json:"contact"`
Location string `json:"location"`
OrderNumber string `json:"order_number"`
Subject string `json:"subject"`
Notes string `json:"notes"`
Place string `json:"place"`
ReportDate string `json:"report_date"`
Query string `json:"q"`
FromMS int64 `json:"from_ms"`
ToMS int64 `json:"to_ms"`
}
if !decodeJSON(w, r, &in) {
return
}
in.Client = strings.TrimSpace(in.Client)
if in.Client == "" {
jsonError(w, 400, "client", "Bitte einen Kunden für den Service-Bericht auswählen.")
return
}
if len(in.Client) > 200 || len(in.Contact) > 200 || len(in.Location) > 400 || len(in.OrderNumber) > 120 || len(in.Subject) > 200 || len(in.Notes) > 6000 || len(in.Place) > 120 || len(in.Query) > 200 {
jsonError(w, 400, "too_long", "Ein Feld im Service-Bericht ist zu lang.")
return
}
if in.FromMS < 0 || in.ToMS < 0 || (in.FromMS > 0 && in.ToMS > 0 && in.ToMS <= in.FromMS) {
jsonError(w, 400, "period", "Ungültiger Berichtszeitraum.")
return
}
reportDate := ""
if strings.TrimSpace(in.ReportDate) != "" {
d, err := time.Parse("2006-01-02", in.ReportDate)
if err != nil {
jsonError(w, 400, "report_date", "Ungültiges Berichtsdatum.")
return
}
reportDate = d.Format("02.01.2006")
}
entries, err := a.store.allEntries(r.Context(), sessionOf(r).User.ID, entryFilter{
Query: strings.TrimSpace(in.Query), Client: in.Client, FromMS: in.FromMS, ToMS: in.ToMS, SortAsc: true,
})
if err != nil {
jsonError(w, 500, "db", "Service-Bericht konnte nicht erstellt werden.")
return
}
if len(entries) == 0 {
jsonError(w, 400, "empty", "Für diesen Kunden und Zeitraum wurden keine abgeschlossenen Tätigkeiten gefunden.")
return
}
cfg, err := a.store.settings(r.Context(), sessionOf(r).User.ID)
if err != nil {
jsonError(w, 500, "db", "Einstellungen konnten nicht geladen werden.")
return
}
pdf := makeServiceReportPDF(entries, cfg, sessionOf(r).User, serviceReportMeta{
Client: in.Client, Contact: strings.TrimSpace(in.Contact), Location: strings.TrimSpace(in.Location),
OrderNumber: strings.TrimSpace(in.OrderNumber), Subject: strings.TrimSpace(in.Subject), Notes: strings.TrimSpace(in.Notes),
Place: strings.TrimSpace(in.Place), ReportDate: reportDate,
})
w.Header().Set("Content-Type", "application/pdf")
w.Header().Set("Content-Disposition", `attachment; filename="service-bericht.pdf"`)
w.Header().Set("Cache-Control", "no-store")
_, _ = w.Write(pdf)
}
func (a *App) adminUsers(w http.ResponseWriter, r *http.Request) {
if !requireAdmin(w, r) {
return
@@ -623,7 +694,12 @@ func parseFilter(w http.ResponseWriter, r *http.Request) (entryFilter, bool) {
}
offset = n
}
return entryFilter{Query: q.Get("q"), FromMS: from, ToMS: to, Limit: limit, Offset: offset, SortAsc: q.Get("sort") == "asc", Compact: q.Get("compact") == "1"}, true
client := strings.TrimSpace(q.Get("client"))
if len(client) > 200 {
jsonError(w, 400, "client", "Kunde ist zu lang.")
return entryFilter{}, false
}
return entryFilter{Query: q.Get("q"), Client: client, FromMS: from, ToMS: to, Limit: limit, Offset: offset, SortAsc: q.Get("sort") == "asc", Compact: q.Get("compact") == "1"}, true
}
func parseInt64Param(w http.ResponseWriter, q url.Values, key string) (int64, bool) {
x := q.Get(key)