package handlers import ( "net/http" "strconv" "time" "erp_system/internal/models" ) func (h *Handler) ChartOfAccounts(w http.ResponseWriter, r *http.Request) { accounts, err := models.GLAccountGetAll(h.DB) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } data := map[string]interface{}{ "Title": "Chart of Accounts", "Username": h.getUsername(r), "ActivePage": "ledger", "Accounts": accounts, } h.render(w, []string{"layout.html", "ledger/chart_of_accounts.html"}, data) } func (h *Handler) JournalEntries(w http.ResponseWriter, r *http.Request) { page, _ := strconv.Atoi(r.URL.Query().Get("page")) if page < 1 { page = 1 } limit := 20 entries, total, err := models.JournalEntryGetPaginated(h.DB, page, limit) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } totalPages := (total + limit - 1) / limit data := map[string]interface{}{ "Title": "Journal Entries", "Username": h.getUsername(r), "ActivePage": "ledger", "Entries": entries, "Page": page, "TotalPages": totalPages, "HasPrev": page > 1, "HasNext": page < totalPages, "PrevPage": page - 1, "NextPage": page + 1, } h.render(w, []string{"layout.html", "ledger/journal_entries.html"}, data) } func (h *Handler) JournalEntryNew(w http.ResponseWriter, r *http.Request) { accounts, _ := models.GLAccountGetAll(h.DB) data := map[string]interface{}{ "Title": "New Journal Entry", "Username": h.getUsername(r), "ActivePage": "ledger", "Accounts": accounts, "Today": time.Now().Format("2006-01-02"), } h.render(w, []string{"layout.html", "ledger/journal_entry_form.html"}, data) } func (h *Handler) JournalEntryCreate(w http.ResponseWriter, r *http.Request) { r.ParseForm() je := &models.JournalEntry{ EntryDate: r.FormValue("entry_date"), Description: r.FormValue("description"), Reference: r.FormValue("reference"), } // Parse lines from form accountIDs := r.Form["account_id"] debits := r.Form["debit"] credits := r.Form["credit"] for i := range accountIDs { accID, _ := strconv.Atoi(accountIDs[i]) debit, _ := strconv.ParseFloat(debits[i], 64) credit, _ := strconv.ParseFloat(credits[i], 64) if accID == 0 || (debit == 0 && credit == 0) { continue } je.Lines = append(je.Lines, models.JournalLine{ AccountID: accID, Debit: debit, Credit: credit, }) } if len(je.Lines) < 2 { accounts, _ := models.GLAccountGetAll(h.DB) data := map[string]interface{}{ "Title": "New Journal Entry", "Username": h.getUsername(r), "ActivePage": "ledger", "Accounts": accounts, "Today": time.Now().Format("2006-01-02"), "Error": "At least two lines are required", } h.render(w, []string{"layout.html", "ledger/journal_entry_form.html"}, data) return } if err := models.JournalEntryInsert(h.DB, je); err != nil { accounts, _ := models.GLAccountGetAll(h.DB) data := map[string]interface{}{ "Title": "New Journal Entry", "Username": h.getUsername(r), "ActivePage": "ledger", "Accounts": accounts, "Today": time.Now().Format("2006-01-02"), "Error": err.Error(), } h.render(w, []string{"layout.html", "ledger/journal_entry_form.html"}, data) return } if r.Header.Get("HX-Request") == "true" { w.Header().Set("HX-Redirect", "/ledger/journal") return } http.Redirect(w, r, "/ledger/journal", http.StatusSeeOther) } func (h *Handler) JournalEntryDetail(w http.ResponseWriter, r *http.Request) { id, _ := strconv.Atoi(r.PathValue("id")) entry, err := models.JournalEntryGetByID(h.DB, id) if err != nil { http.Error(w, "Journal entry not found", http.StatusNotFound) return } data := map[string]interface{}{ "Title": "Journal Entry #" + strconv.Itoa(id), "Username": h.getUsername(r), "ActivePage": "ledger", "Entry": entry, } h.render(w, []string{"layout.html", "ledger/journal_entry_detail.html"}, data) } func (h *Handler) TrialBalance(w http.ResponseWriter, r *http.Request) { rows, err := models.GetTrialBalance(h.DB) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } var totalDebit, totalCredit float64 for _, row := range rows { totalDebit += row.Debit totalCredit += row.Credit } data := map[string]interface{}{ "Title": "Trial Balance", "Username": h.getUsername(r), "ActivePage": "ledger", "Rows": rows, "TotalDebit": totalDebit, "TotalCredit": totalCredit, } h.render(w, []string{"layout.html", "ledger/trial_balance.html"}, data) }