From 0b55ac1fac537288be44d2aaca3321ec261e1021 Mon Sep 17 00:00:00 2001 From: cclohmar Date: Mon, 1 Jun 2026 23:30:56 +0000 Subject: [PATCH] fix: normalize ImagePath for old database entries with storage/ prefix - Added normalizeImagePath() helper that strips legacy storage/ prefix - Applied in ViewEventExpenses, SaveExpense, UpdateExpense, EditExpense - Prevents double storage/storage/ in image URLs for old expenses --- internal/handlers/events.go | 5 +++++ internal/handlers/expenses.go | 11 ++++++++++- internal/handlers/helpers.go | 10 ++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 internal/handlers/helpers.go diff --git a/internal/handlers/events.go b/internal/handlers/events.go index d02a1e7..7e17914 100644 --- a/internal/handlers/events.go +++ b/internal/handlers/events.go @@ -242,6 +242,11 @@ func (h *EventHandler) ViewEventExpenses(w http.ResponseWriter, r *http.Request) } } + // Normalize ImagePath for all expenses (old DB entries may have storage/ prefix). + for i := range expenses { + expenses[i].ImagePath = normalizeImagePath(expenses[i].ImagePath) + } + data := map[string]interface{}{ "Event": event, "Expenses": expenses, diff --git a/internal/handlers/expenses.go b/internal/handlers/expenses.go index d4d5d6c..8b2bba6 100644 --- a/internal/handlers/expenses.go +++ b/internal/handlers/expenses.go @@ -308,6 +308,10 @@ func (h *ExpenseHandler) SaveExpense(w http.ResponseWriter, r *http.Request) { } // 7. Render the expense_list.html fragment. + // Normalize ImagePath for old DB entries that may have storage/ prefix. + for i := range expenses { + expenses[i].ImagePath = normalizeImagePath(expenses[i].ImagePath) + } listTmpl := getTemplate("expense_list.html") var listBuf strings.Builder @@ -363,7 +367,7 @@ func (h *ExpenseHandler) EditExpense(w http.ResponseWriter, r *http.Request) { tmpl := getTemplate("receipt_form.html") data := map[string]interface{}{ - "ImagePath": expense.ImagePath, + "ImagePath": normalizeImagePath(expense.ImagePath), "AIError": "", "Amount": strconv.FormatFloat(expense.Amount, 'f', 2, 64), "Currency": expense.Currency, @@ -375,6 +379,7 @@ func (h *ExpenseHandler) EditExpense(w http.ResponseWriter, r *http.Request) { "ExchangeRate": 0.0, "ConvertedAmount": strconv.FormatFloat(expense.ConvertedAmount, 'f', 2, 64), "EditID": expense.ID, + "ID": expense.ID, } w.Header().Set("Content-Type", "text/html; charset=utf-8") @@ -456,6 +461,10 @@ func (h *ExpenseHandler) UpdateExpense(w http.ResponseWriter, r *http.Request) { http.Error(w, "Failed to fetch expenses", http.StatusInternalServerError) return } + // Normalize ImagePath for old DB entries. + for i := range expenses { + expenses[i].ImagePath = normalizeImagePath(expenses[i].ImagePath) + } listTmpl := getTemplate("expense_list.html") diff --git a/internal/handlers/helpers.go b/internal/handlers/helpers.go new file mode 100644 index 0000000..18d0e9a --- /dev/null +++ b/internal/handlers/helpers.go @@ -0,0 +1,10 @@ +package handlers + +import "strings" + +// normalizeImagePath strips a legacy "storage/" prefix if present, so that +// the template can safely build "/storage/{filename}" URLs regardless of +// whether the database entry was stored as "uuid.jpg" or "storage/uuid.jpg". +func normalizeImagePath(path string) string { + return strings.TrimPrefix(path, "storage/") +}