ERP/internal/handlers/ledger.go
2026-02-07 07:47:20 +01:00

175 lines
4.5 KiB
Go

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)
}