package service import ( "context" "spend-sparrow/internal/db" "spend-sparrow/internal/types" "time" "github.com/jmoiron/sqlx" ) type Dashboard struct { db *sqlx.DB } func NewDashboard(db *sqlx.DB) *Dashboard { return &Dashboard{ db: db, } } func (s Dashboard) Summary(ctx context.Context, user *types.User, month time.Time) (*types.DashboardMonthlySummary, error) { if user == nil { return nil, ErrUnauthorized } var summary types.DashboardMonthlySummary var value *int64 err := s.db.GetContext(ctx, &value, ` SELECT SUM(value) FROM "transaction" WHERE user_id = $1 AND treasure_chest_id IS NOT NULL AND account_id IS NULL AND error IS NULL AND date(timestamp, 'start of month') = date($2, 'start of month')`, user.Id, month) err = db.TransformAndLogDbError(ctx, "dashboard", nil, err) if err != nil { return nil, err } if value != nil { summary.Savings = *value } err = s.db.GetContext(ctx, &value, ` SELECT SUM(value) FROM "transaction" WHERE user_id = $1 AND account_id IS NOT NULL AND treasure_chest_id IS NULL AND error IS NULL AND date(timestamp, 'start of month') = date($2, 'start of month')`, user.Id, month) err = db.TransformAndLogDbError(ctx, "dashboard", nil, err) if err != nil { return nil, err } if value != nil { summary.Income = *value } err = s.db.GetContext(ctx, &value, ` SELECT SUM(value) FROM "transaction" WHERE user_id = $1 AND account_id IS NOT NULL AND treasure_chest_id IS NOT NULL AND error IS NULL AND date(timestamp, 'start of month') = date($2, 'start of month')`, user.Id, month) err = db.TransformAndLogDbError(ctx, "dashboard", nil, err) if err != nil { return nil, err } if value != nil { summary.Expenses = *value } summary.Total = summary.Income + summary.Expenses summary.Month = month err = s.db.GetContext(ctx, &value, ` SELECT SUM(current_balance) FROM treasure_chest WHERE user_id = $1`, user.Id) err = db.TransformAndLogDbError(ctx, "dashboard", nil, err) if err != nil { return nil, err } if value != nil { summary.SumOfSavings = *value } err = s.db.GetContext(ctx, &value, ` SELECT SUM(current_balance) FROM account WHERE user_id = $1`, user.Id) err = db.TransformAndLogDbError(ctx, "dashboard", nil, err) if err != nil { return nil, err } if value != nil { summary.SumOfAccounts = *value } return &summary, nil } func (s Dashboard) MainChart( ctx context.Context, user *types.User, ) ([]types.DashboardMainChartEntry, error) { if user == nil { return nil, ErrUnauthorized } transactions := make([]types.Transaction, 0) err := s.db.SelectContext(ctx, &transactions, ` SELECT * FROM "transaction" WHERE user_id = ? ORDER BY timestamp`, user.Id) err = db.TransformAndLogDbError(ctx, "dashboard Chart", nil, err) if err != nil { return nil, err } timeEntries := make([]types.DashboardMainChartEntry, 0) var lastEntry *types.DashboardMainChartEntry for _, t := range transactions { if t.Error != nil { continue } newDay := t.Timestamp.Truncate(24 * time.Hour) if lastEntry == nil { lastEntry = &types.DashboardMainChartEntry{ Day: newDay, Value: 0, Savings: 0, } } else if lastEntry.Day != newDay { timeEntries = append(timeEntries, *lastEntry) lastEntry = &types.DashboardMainChartEntry{ Day: newDay, Value: lastEntry.Value, Savings: lastEntry.Savings, } } if t.AccountId != nil { lastEntry.Value += t.Value } if t.TreasureChestId != nil { lastEntry.Savings += t.Value } } if lastEntry != nil { timeEntries = append(timeEntries, *lastEntry) } return timeEntries, nil }