@@ -18,14 +18,22 @@ func NewReportHandler(db *sql.DB, exchangeService *services.ExchangeService) *Re
1818 return & ReportHandler {db : db , exchangeService : exchangeService }
1919}
2020
21+ type CategoryReport struct {
22+ Category string `json:"category"`
23+ Amount float64 `json:"amount"`
24+ Budget * float64 `json:"budget,omitempty"`
25+ Percentage * float64 `json:"percentage,omitempty"`
26+ Remaining * float64 `json:"remaining,omitempty"`
27+ }
28+
2129type ReportResponse struct {
22- PeriodStart string `json:"period_start"`
23- PeriodEnd string `json:"period_end"`
24- Currency string `json:"currency"`
25- TotalIncome float64 `json:"total_income"`
26- TotalExpenses float64 `json:"total_expenses"`
27- ExpensesByCategory map [ string ] float64 `json:"expenses_by_category"`
28- FirstTransactionDate * string `json:"first_transaction_date"`
30+ PeriodStart string `json:"period_start"`
31+ PeriodEnd string `json:"period_end"`
32+ Currency string `json:"currency"`
33+ TotalIncome float64 `json:"total_income"`
34+ TotalExpenses float64 `json:"total_expenses"`
35+ ExpensesByCategory [] CategoryReport `json:"expenses_by_category"`
36+ FirstTransactionDate * string `json:"first_transaction_date"`
2937}
3038
3139func (h * ReportHandler ) GetReport (w http.ResponseWriter , r * http.Request ) {
@@ -131,7 +139,7 @@ func (h *ReportHandler) GetReport(w http.ResponseWriter, r *http.Request) {
131139 Currency : baseCurrency ,
132140 TotalIncome : 0 ,
133141 TotalExpenses : 0 ,
134- ExpensesByCategory : make ( map [ string ] float64 ) ,
142+ ExpensesByCategory : [] CategoryReport {} ,
135143 }, http .StatusOK )
136144 return
137145 }
@@ -202,13 +210,53 @@ func (h *ReportHandler) GetReport(w http.ResponseWriter, r *http.Request) {
202210 firstTxDate = & dateStr
203211 }
204212
213+ // Fetch user's budgets (only for monthly reports)
214+ budgets := make (map [string ]float64 )
215+ if period == "month" {
216+ budgetRows , err := h .db .Query (`
217+ SELECT category, monthly_limit
218+ FROM category_budgets
219+ WHERE user_id = ?
220+ ` , userID )
221+ if err == nil {
222+ defer budgetRows .Close ()
223+ for budgetRows .Next () {
224+ var category string
225+ var limit float64
226+ if err := budgetRows .Scan (& category , & limit ); err == nil {
227+ budgets [category ] = limit
228+ }
229+ }
230+ }
231+ }
232+
233+ // Build category reports with budget information
234+ categoryReports := make ([]CategoryReport , 0 , len (expensesByCategory ))
235+ for category , amount := range expensesByCategory {
236+ catReport := CategoryReport {
237+ Category : category ,
238+ Amount : amount ,
239+ }
240+
241+ // Add budget info if exists for this category
242+ if budget , hasBudget := budgets [category ]; hasBudget {
243+ catReport .Budget = & budget
244+ percentage := (amount / budget ) * 100
245+ catReport .Percentage = & percentage
246+ remaining := budget - amount
247+ catReport .Remaining = & remaining
248+ }
249+
250+ categoryReports = append (categoryReports , catReport )
251+ }
252+
205253 report := ReportResponse {
206254 PeriodStart : startDate .Format ("2006-01-02" ),
207255 PeriodEnd : endDate .Format ("2006-01-02" ),
208256 Currency : baseCurrency ,
209257 TotalIncome : totalIncome ,
210258 TotalExpenses : totalExpenses ,
211- ExpensesByCategory : expensesByCategory ,
259+ ExpensesByCategory : categoryReports ,
212260 FirstTransactionDate : firstTxDate ,
213261 }
214262
0 commit comments