Files
carvalho-finances/apps/api/internal/service/dashboard.go
T
Mlcavalho1andClaude Sonnet 4.6 fbcb1d76aa feat(#20): dashboard financeiro mensal — 4 widgets + endpoint de agregação
Adiciona GET /api/dashboard?month=YYYY-MM com resumo mensal (% poupado,
gastos por categoria, evolução 6 meses, últimas 10 transações, recorrências
pendentes). HomeView.vue reescrita com 4 widgets e gráficos CSS nativos.

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
2026-05-26 20:32:05 -03:00

83 lines
1.9 KiB
Go

package service
import (
"context"
"financeiro-carvalho/internal/model"
)
type DashboardRepo interface {
MonthlySummary(ctx context.Context, month string) (income, expenses float64, err error)
ByCategory(ctx context.Context, month string) ([]model.CategoryTotal, error)
MonthlyEvolution(ctx context.Context, month string) ([]model.MonthEvolution, error)
RecentTransactions(ctx context.Context, month string) ([]model.RecentTransaction, error)
}
type DashboardService struct {
repo DashboardRepo
recurrSvc *RecurringService
}
func NewDashboardService(repo DashboardRepo, recurrSvc *RecurringService) *DashboardService {
return &DashboardService{repo: repo, recurrSvc: recurrSvc}
}
func (s *DashboardService) Get(ctx context.Context, month string) (*model.DashboardData, error) {
income, expenses, err := s.repo.MonthlySummary(ctx, month)
if err != nil {
return nil, err
}
byCategory, err := s.repo.ByCategory(ctx, month)
if err != nil {
return nil, err
}
evolution, err := s.repo.MonthlyEvolution(ctx, month)
if err != nil {
return nil, err
}
recent, err := s.repo.RecentTransactions(ctx, month)
if err != nil {
return nil, err
}
var savingsPct float64
if income > 0 {
savingsPct = (income - expenses) / income * 100
}
statuses, err := s.recurrSvc.MonthlyStatus(ctx, month)
if err != nil {
return nil, err
}
pending := 0
for _, s := range statuses {
if !s.Covered {
pending++
}
}
if byCategory == nil {
byCategory = []model.CategoryTotal{}
}
if evolution == nil {
evolution = []model.MonthEvolution{}
}
if recent == nil {
recent = []model.RecentTransaction{}
}
return &model.DashboardData{
Month: month,
TotalIncome: income,
TotalExpenses: expenses,
SavingsPct: savingsPct,
ByCategory: byCategory,
MonthlyEvolution: evolution,
RecentTransactions: recent,
PendingRecurring: pending,
}, nil
}