package repository import ( "context" "github.com/jackc/pgx/v5/pgxpool" "financeiro-carvalho/internal/model" ) type DashboardRepository struct { pool *pgxpool.Pool } func NewDashboardRepository(pool *pgxpool.Pool) *DashboardRepository { return &DashboardRepository{pool: pool} } func (r *DashboardRepository) MonthlySummary(ctx context.Context, month string) (income, expenses float64, err error) { row := r.pool.QueryRow(ctx, ` 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 transactions WHERE to_char(date, 'YYYY-MM') = $1 `, month) err = row.Scan(&income, &expenses) return } func (r *DashboardRepository) ByCategory(ctx context.Context, month string) ([]model.CategoryTotal, error) { rows, err := r.pool.Query(ctx, ` SELECT t.category_id, COALESCE(c.name, 'Sem categoria') AS category_name, COALESCE(c.color, '#6B7280') AS color, SUM(t.amount) AS total FROM transactions t LEFT JOIN categories c ON c.id = t.category_id WHERE to_char(t.date, 'YYYY-MM') = $1 AND t.type = 'expense' GROUP BY t.category_id, c.name, c.color ORDER BY total DESC `, month) if err != nil { return nil, err } defer rows.Close() var out []model.CategoryTotal for rows.Next() { var ct model.CategoryTotal if err := rows.Scan(&ct.CategoryID, &ct.CategoryName, &ct.Color, &ct.Total); err != nil { return nil, err } out = append(out, ct) } return out, rows.Err() } func (r *DashboardRepository) MonthlyEvolution(ctx context.Context, month string) ([]model.MonthEvolution, error) { rows, err := r.pool.Query(ctx, ` SELECT to_char(m.ms, 'YYYY-MM') AS month, COALESCE(SUM(CASE WHEN t.type = 'income' THEN t.amount ELSE 0 END), 0) AS income, COALESCE(SUM(CASE WHEN t.type = 'expense' THEN t.amount ELSE 0 END), 0) AS expenses FROM generate_series( date_trunc('month', ($1 || '-01')::date) - INTERVAL '5 months', date_trunc('month', ($1 || '-01')::date), '1 month'::interval ) AS m(ms) LEFT JOIN transactions t ON date_trunc('month', t.date) = m.ms GROUP BY m.ms ORDER BY m.ms `, month) if err != nil { return nil, err } defer rows.Close() var out []model.MonthEvolution for rows.Next() { var me model.MonthEvolution if err := rows.Scan(&me.Month, &me.Income, &me.Expenses); err != nil { return nil, err } me.Saved = me.Income - me.Expenses out = append(out, me) } return out, rows.Err() } func (r *DashboardRepository) RecentTransactions(ctx context.Context, month string) ([]model.RecentTransaction, error) { rows, err := r.pool.Query(ctx, ` SELECT t.id, t.date::text, t.description, COALESCE(c.name, 'Sem categoria') AS category_name, t.amount, t.type FROM transactions t LEFT JOIN categories c ON c.id = t.category_id WHERE to_char(t.date, 'YYYY-MM') = $1 ORDER BY t.date DESC, t.id DESC LIMIT 10 `, month) if err != nil { return nil, err } defer rows.Close() var out []model.RecentTransaction for rows.Next() { var rt model.RecentTransaction if err := rows.Scan(&rt.ID, &rt.Date, &rt.Description, &rt.CategoryName, &rt.Amount, &rt.Type); err != nil { return nil, err } out = append(out, rt) } return out, rows.Err() }