package web import ( "bytes" "encoding/json" "fmt" "html/template" "io" "log" "marmic/servicetrade-toolbox/internal/api" "net/http" "strings" ) func InvoicesHandler(w http.ResponseWriter, r *http.Request) { session, ok := r.Context().Value("session").(*api.Session) if !ok { http.Error(w, "Unauthorized", http.StatusUnauthorized) return } if r.Method == "GET" { handleInvoiceSearch(w, r, session) return } tmpl := template.Must(template.ParseFiles("templates/layout.html", "templates/partials/invoices.html")) data := map[string]interface{}{ "Title": "Invoices", } if r.Header.Get("HX-Request") == "true" { tmpl.ExecuteTemplate(w, "content", data) } else { tmpl.Execute(w, data) } } func handleInvoiceSearch(w http.ResponseWriter, r *http.Request, session *api.Session) { searchTerm := strings.TrimSpace(r.URL.Query().Get("search")) if searchTerm == "" { log.Println("Empty search term, returning empty response") w.WriteHeader(http.StatusOK) return } log.Printf("Searching for invoice with term: %s", searchTerm) invoice, err := session.GetInvoice(searchTerm) log.Printf("GetInvoice result - invoice: %+v, err: %v", invoice, err) if err != nil { log.Printf("Error fetching invoice: %v", err) w.WriteHeader(http.StatusOK) errorMsg := fmt.Sprintf("Error fetching invoice: %v", err) if strings.Contains(err.Error(), "access forbidden") { errorMsg = "You do not have permission to view this invoice." } tmpl := template.Must(template.ParseFiles("templates/partials/invoice_search_results.html")) tmpl.ExecuteTemplate(w, "invoice_search_results", map[string]interface{}{ "Error": true, "ErrorMsg": errorMsg, "SearchTerm": searchTerm, }) return } if invoice == nil { log.Printf("No invoice found for: %s", searchTerm) w.WriteHeader(http.StatusOK) tmpl := template.Must(template.ParseFiles("templates/partials/invoice_search_results.html")) tmpl.ExecuteTemplate(w, "invoice_search_results", map[string]interface{}{ "NotFound": true, "ErrorMsg": fmt.Sprintf("No invoice found for: %s", searchTerm), "SearchTerm": searchTerm, }) return } if id, ok := invoice["id"].(float64); ok { invoice["id"] = fmt.Sprintf("%.0f", id) } log.Printf("Invoice found: %+v", invoice) tmpl := template.Must(template.ParseFiles("templates/partials/invoice_search_results.html")) err = tmpl.ExecuteTemplate(w, "invoice_search_results", invoice) if err != nil { log.Printf("Error executing template: %v", err) http.Error(w, "Internal Server Error", http.StatusInternalServerError) } } func VoidInvoiceHandler(w http.ResponseWriter, r *http.Request) { session, ok := r.Context().Value("session").(*api.Session) if !ok { http.Error(w, "Unauthorized", http.StatusUnauthorized) return } if r.Method != http.MethodPut { http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) return } // Extract the invoice ID from the URL parts := strings.Split(r.URL.Path, "/") if len(parts) < 3 { http.Error(w, "Invalid request", http.StatusBadRequest) return } invoiceID := parts[len(parts)-1] if invoiceID == "" { http.Error(w, "Invalid invoice ID", http.StatusBadRequest) return } // Prepare the request body requestBody := map[string]string{"status": "void"} jsonBody, err := json.Marshal(requestBody) if err != nil { http.Error(w, "Error preparing request", http.StatusInternalServerError) return } // Send the PUT request to void the invoice endpoint := fmt.Sprintf("/invoice/%s", invoiceID) resp, err := session.DoRequest("PUT", endpoint, bytes.NewBuffer(jsonBody)) if err != nil { log.Printf("Error voiding invoice: %v", err) http.Error(w, fmt.Sprintf("Error voiding invoice: %v", err), http.StatusInternalServerError) return } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { body, _ := io.ReadAll(resp.Body) log.Printf("Failed to void invoice: %s", body) http.Error(w, fmt.Sprintf("Failed to void invoice: %s", body), resp.StatusCode) 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 voiding: %+v", invoice) // Render the updated invoice details tmpl := template.Must(template.ParseFiles("templates/partials/invoice_search_results.html")) err = tmpl.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 } }