From 9e063415643ff0e8a871a95c41fd2d8fa5077e85 Mon Sep 17 00:00:00 2001 From: Cosmo Date: Sun, 1 Mar 2026 05:22:56 +0000 Subject: [PATCH] feat: cumulative balance with carried_over in finance summary --- internal/model/finance.go | 1 + internal/repository/finance.go | 23 +++++++++++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/internal/model/finance.go b/internal/model/finance.go index 4a6210e..3fdfc16 100644 --- a/internal/model/finance.go +++ b/internal/model/finance.go @@ -73,6 +73,7 @@ type UpdateFinanceTransactionRequest struct { } type FinanceSummary struct { + CarriedOver float64 `json:"carried_over"` Balance float64 `json:"balance"` TotalIncome float64 `json:"total_income"` TotalExpense float64 `json:"total_expense"` diff --git a/internal/repository/finance.go b/internal/repository/finance.go index 17bcc7a..ac4a885 100644 --- a/internal/repository/finance.go +++ b/internal/repository/finance.go @@ -237,15 +237,34 @@ func (r *FinanceRepository) DeleteTransaction(id, userID int64) error { func (r *FinanceRepository) GetSummary(userID int64, month, year int) (*model.FinanceSummary, error) { summary := &model.FinanceSummary{} + // First day of selected month and last day of selected month + firstDay := time.Date(year, time.Month(month), 1, 0, 0, 0, 0, time.UTC) + lastDay := firstDay.AddDate(0, 1, -1) + + // Carried over: balance of all transactions BEFORE the selected month + err := r.db.QueryRow(`SELECT COALESCE(SUM(CASE WHEN type='income' THEN amount ELSE -amount END), 0) + FROM finance_transactions WHERE user_id=$1 AND date < $2`, + userID, firstDay).Scan(&summary.CarriedOver) + if err != nil { + return nil, err + } + // Total income & expense for the month - err := r.db.QueryRow(`SELECT COALESCE(SUM(CASE WHEN type='income' THEN amount ELSE 0 END),0), + err = r.db.QueryRow(`SELECT COALESCE(SUM(CASE WHEN type='income' THEN amount ELSE 0 END),0), COALESCE(SUM(CASE WHEN type='expense' THEN amount ELSE 0 END),0) FROM finance_transactions WHERE user_id=$1 AND EXTRACT(MONTH FROM date)=$2 AND EXTRACT(YEAR FROM date)=$3`, userID, month, year).Scan(&summary.TotalIncome, &summary.TotalExpense) if err != nil { return nil, err } - summary.Balance = summary.TotalIncome - summary.TotalExpense + + // Cumulative balance: all transactions up to end of selected month + err = r.db.QueryRow(`SELECT COALESCE(SUM(CASE WHEN type='income' THEN amount ELSE -amount END), 0) + FROM finance_transactions WHERE user_id=$1 AND date <= $2`, + userID, lastDay).Scan(&summary.Balance) + if err != nil { + return nil, err + } // By category rows, err := r.db.Query(`SELECT c.id, c.name, c.emoji, t.type, SUM(t.amount) as amount