mirror of
https://github.com/escalante29/WealthySmart.git
synced 2026-05-19 10:28:48 +02:00
All checks were successful
Deploy to VPS / deploy (push) Successful in 23s
Ahorro was already deducted from gross salary so displaying it in budget projections was misleading. This removes the Ahorro card, summary line, Proyecciones column, and Ahorro Anual card from the UI, and strips all savings fields from budget API responses. Adds SALARY TransactionType so salary deposits can be distinguished from generic DEPOSITO transfers. When a SALARY transaction arrives, the system auto-increments MEMP and MPAT savings account balances (+200K CRC each) once per month via an idempotent accrual log. New CRUD endpoints at /api/v1/savings-accrual/ allow manual correction of the accrual history. Feb+Mar 2026 are seeded as historical baseline. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
82 lines
2.5 KiB
Python
82 lines
2.5 KiB
Python
from sqlalchemy import text
|
|
from sqlmodel import SQLModel, Session, create_engine
|
|
|
|
from app.config import settings
|
|
|
|
engine = create_engine(settings.DATABASE_URL)
|
|
|
|
|
|
def init_db():
|
|
SQLModel.metadata.create_all(engine)
|
|
|
|
|
|
def run_migrations():
|
|
"""Run idempotent schema migrations for columns added after initial create."""
|
|
with engine.connect() as conn:
|
|
try:
|
|
conn.execute(
|
|
text(
|
|
"ALTER TABLE transaction ADD COLUMN IF NOT EXISTS deferred_to_next_cycle BOOLEAN NOT NULL DEFAULT false"
|
|
)
|
|
)
|
|
conn.commit()
|
|
except Exception:
|
|
conn.rollback()
|
|
|
|
try:
|
|
conn.execute(text("ALTER TYPE currency ADD VALUE IF NOT EXISTS 'EUR'"))
|
|
conn.commit()
|
|
except Exception:
|
|
conn.rollback()
|
|
|
|
try:
|
|
conn.execute(
|
|
text("ALTER TYPE transactiontype ADD VALUE IF NOT EXISTS 'SALARY'")
|
|
)
|
|
conn.commit()
|
|
except Exception:
|
|
conn.rollback()
|
|
|
|
try:
|
|
conn.execute(
|
|
text(
|
|
"""
|
|
CREATE TABLE IF NOT EXISTS savingsaccrual (
|
|
id SERIAL PRIMARY KEY,
|
|
year INTEGER NOT NULL,
|
|
month INTEGER NOT NULL,
|
|
memp_amount DOUBLE PRECISION NOT NULL DEFAULT 200000,
|
|
mpat_amount DOUBLE PRECISION NOT NULL DEFAULT 200000,
|
|
trigger_transaction_id INTEGER,
|
|
applied_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
|
notes TEXT,
|
|
CONSTRAINT savingsaccrual_year_month_key UNIQUE (year, month)
|
|
)
|
|
"""
|
|
)
|
|
)
|
|
conn.commit()
|
|
except Exception:
|
|
conn.rollback()
|
|
|
|
try:
|
|
conn.execute(
|
|
text(
|
|
"""
|
|
INSERT INTO savingsaccrual (year, month, memp_amount, mpat_amount, notes)
|
|
VALUES
|
|
(2026, 2, 200000, 200000, 'Seeded: historical baseline'),
|
|
(2026, 3, 200000, 200000, 'Seeded: historical baseline')
|
|
ON CONFLICT (year, month) DO NOTHING
|
|
"""
|
|
)
|
|
)
|
|
conn.commit()
|
|
except Exception:
|
|
conn.rollback()
|
|
|
|
|
|
def get_session():
|
|
with Session(engine) as session:
|
|
yield session
|