From 1096b42258050b26a1c4d97d1460682540601abb Mon Sep 17 00:00:00 2001 From: nic Date: Tue, 25 Mar 2025 08:54:41 -0400 Subject: [PATCH] chore: updated status transition/display rules --- apps/web/main.go | 1 + internal/handlers/web/invoices.go | 83 +++++++++++++++++-------------- 2 files changed, 46 insertions(+), 38 deletions(-) diff --git a/apps/web/main.go b/apps/web/main.go index 7382e1e..e4c89cf 100644 --- a/apps/web/main.go +++ b/apps/web/main.go @@ -40,6 +40,7 @@ func main() { protected.HandleFunc("/jobs", web.JobsHandler).Methods("GET", "POST") protected.HandleFunc("/invoices", web.InvoicesHandler).Methods("GET", "POST") protected.HandleFunc("/ok-invoice/{id}", web.UpdateInvoiceStatusHandler).Methods("PUT") + protected.HandleFunc("/draft-invoice/{id}", web.UpdateInvoiceStatusHandler).Methods("PUT") protected.HandleFunc("/failed-invoice/{id}", web.UpdateInvoiceStatusHandler).Methods("PUT") protected.HandleFunc("/pending_accounting-invoice/{id}", web.UpdateInvoiceStatusHandler).Methods("PUT") protected.HandleFunc("/processed-invoice/{id}", web.UpdateInvoiceStatusHandler).Methods("PUT") diff --git a/internal/handlers/web/invoices.go b/internal/handlers/web/invoices.go index 585d06f..6ac8e9a 100644 --- a/internal/handlers/web/invoices.go +++ b/internal/handlers/web/invoices.go @@ -19,6 +19,11 @@ type StatusButton struct { ConfirmText string } +// Cannot move from draft status to pending_accounting status +// Cannot move from draft status to processed status +// Cannot move from draft status to failed status +// Cannot move from failed status to pending_accounting status +// Cannot move from failed status to processed status var statusButtons = []StatusButton{ {"draft", "Draft Invoice", "success-button", "Are you sure you want to draft this invoice?"}, {"ok", "Ok Invoice", "success-button", "Are you sure you want to mark this invoice as OK?"}, @@ -119,28 +124,44 @@ func handleInvoiceSearch(w http.ResponseWriter, r *http.Request, session *api.Se func getInvoiceStatusButtons(invoiceID, currentStatus string) []map[string]string { var buttons []map[string]string - switch currentStatus { - case "processed": - // Only allow voiding for processed invoices + // Define allowed transitions for each status + allowedTransitions := map[string]map[string]bool{ + "draft": { + "ok": true, + "void": true, + // draft cannot transition to pending_accounting, processed, or failed + }, + "ok": { + "draft": true, + "failed": true, + "pending_accounting": true, + "processed": true, + "void": true, + }, + "failed": { + "draft": true, + "ok": true, + "void": true, + // failed cannot transition to pending_accounting or processed + }, + "pending_accounting": { + "failed": true, + "processed": true, + "void": true, + }, + "processed": { + "void": true, + // processed can only be voided + }, + "void": { + // void has no allowed transitions + }, + } + + // If we have defined transitions for this status, use them + if transitions, exists := allowedTransitions[currentStatus]; exists { for _, button := range statusButtons { - if button.Status == "void" { - buttons = append(buttons, map[string]string{ - "Action": fmt.Sprintf("/%s-invoice/%s", button.Status, invoiceID), - "Label": button.Label, - "Class": button.Class, - "ConfirmText": button.ConfirmText, - }) - break - } - } - case "void": - // No buttons for voided invoices - return buttons - default: - // For all other statuses, show all buttons except the current status - for _, button := range statusButtons { - fmt.Printf("btn status: %s, curr status: %s", button.Status, currentStatus) - if button.Status != currentStatus { + if transitions[button.Status] { buttons = append(buttons, map[string]string{ "Action": fmt.Sprintf("/%s-invoice/%s", button.Status, invoiceID), "Label": button.Label, @@ -223,21 +244,7 @@ func UpdateInvoiceStatusHandler(w http.ResponseWriter, r *http.Request) { return } - // If successful, fetch the updated invoice details - invoice, err := session.GetInvoice(invoiceID) - if err != nil { - log.Printf("Error fetching updated invoice: %v", err) - http.Error(w, fmt.Sprintf("Error fetching updated invoice: %v", err), http.StatusInternalServerError) - return - } - - log.Printf("Updated invoice after status change to %s: %+v", status, invoice) - - // Render the updated invoice details - err = root.WebTemplates.ExecuteTemplate(w, "invoice_search_results", invoice) - if err != nil { - log.Printf("Error executing template: %v", err) - http.Error(w, "Error rendering template", http.StatusInternalServerError) - return - } + mockReq, _ := http.NewRequest("GET", fmt.Sprintf("?search=%s", invoiceID), nil) + mockReq = mockReq.WithContext(r.Context()) + handleInvoiceSearch(w, mockReq, session) }