Files
carvalho-finances/apps/api/internal/migration/migration.go
T
Mlcavalho1andClaude Sonnet 4.6 1d59cb2a0e feat: #45 meta de poupança configurável + conquistas genéricas
- Nova tabela user_settings com savings_goal_pct (default 40%)
- API GET /api/settings, PUT /api/settings
- DashboardService inclui savings_goal_pct no payload
- DashboardHandler dispara savings_checked com goal configurado
- GameService.NotifyAction: checa pct >= goal (sem hardcode de 40%)
- SettingsView: painel META DE POUPANÇA com input configurável
- HomeView: widget mostra meta dinâmica (META: X%) e usa savingsGoal
- stores/settings.ts: store com fetch e update

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
2026-05-28 22:32:08 -03:00

90 lines
2.0 KiB
Go

package migration
import (
"context"
_ "embed"
"fmt"
"github.com/jackc/pgx/v5/pgxpool"
)
//go:embed sql/001_initial.sql
var m001 string
//go:embed sql/002_add_external_id.sql
var m002 string
//go:embed sql/003_recurring_ignores.sql
var m003 string
//go:embed sql/004_accounts.sql
var m004 string
//go:embed sql/005_game_profile.sql
var m005 string
//go:embed sql/006_quests.sql
var m006 string
//go:embed sql/007_achievements.sql
var m007 string
//go:embed sql/008_cosmetics.sql
var m008 string
//go:embed sql/009_recurring_income.sql
var m009 string
//go:embed sql/010_cdi_yield.sql
var m010 string
//go:embed sql/011_credit_bills.sql
var m011 string
//go:embed sql/012_category_is_tax.sql
var m012 string
//go:embed sql/013_transaction_original_date.sql
var m013 string
//go:embed sql/014_profiles.sql
var m014 string
//go:embed sql/015_accounts_cdi_percentage.sql
var m015 string
//go:embed sql/016_pending_bill_imports.sql
var m016 string
//go:embed sql/017_user_settings.sql
var m017 string
func Run(ctx context.Context, pool *pgxpool.Pool) error {
// Bootstrap: ensure schema_migrations table exists before checking versions.
if _, err := pool.Exec(ctx, `
CREATE TABLE IF NOT EXISTS schema_migrations (
version INTEGER PRIMARY KEY,
applied_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW()
)
`); err != nil {
return fmt.Errorf("bootstrap schema_migrations: %w", err)
}
migrations := []string{m001, m002, m003, m004, m005, m006, m007, m008, m009, m010, m011, m012, m013, m014, m015, m016, m017}
for i, sql := range migrations {
version := i + 1
var applied bool
_ = pool.QueryRow(ctx, `SELECT EXISTS(SELECT 1 FROM schema_migrations WHERE version=$1)`, version).Scan(&applied)
if applied {
continue
}
if _, err := pool.Exec(ctx, sql); err != nil {
return fmt.Errorf("migration %03d: %w", version, err)
}
if _, err := pool.Exec(ctx, `INSERT INTO schema_migrations (version) VALUES ($1) ON CONFLICT DO NOTHING`, version); err != nil {
return fmt.Errorf("migration %03d mark applied: %w", version, err)
}
}
return nil
}