mirror of
https://github.com/escalante29/WealthySmart.git
synced 2026-07-17 12:28:48 +02:00
Migrate all 29 money columns from float to NUMERIC/Decimal (BE-02)
Models use Money = Annotated[Decimal, PlainSerializer(float)] so storage is exact NUMERIC(15,2) (rates 15,6) while JSON keeps emitting plain numbers — the frontend contract is unchanged, pinned by test_models_serialization.py. Service layers coerce to float at their boundaries (projection math, rate multipliers, agent tool output, the savings constants become Decimal) so no naive Decimal/float mixing can raise. Migration 7f567c8bafdb applied to dev: per-row values and the table sum byte-identical before/after; endpoints verified live on the new schema. 59/59 tests green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -31,7 +31,7 @@ def get_effective_amount(item: RecurringItem, month: int, year: int) -> float |
|
||||
if freq == RecurringFrequency.MONTHLY:
|
||||
if item.override_amounts and str(month) in item.override_amounts:
|
||||
return float(item.override_amounts[str(month)])
|
||||
return item.amount
|
||||
return float(item.amount)
|
||||
|
||||
if freq == RecurringFrequency.WEEKLY:
|
||||
# Count occurrences of the weekday in this month
|
||||
@@ -39,14 +39,14 @@ def get_effective_amount(item: RecurringItem, month: int, year: int) -> float |
|
||||
weekday = item.day_of_month if item.day_of_month is not None else 0
|
||||
cal = calendar.monthcalendar(year, month)
|
||||
count = sum(1 for week in cal if week[weekday] != 0)
|
||||
return item.amount * count
|
||||
return float(item.amount) * count
|
||||
|
||||
if freq == RecurringFrequency.QUARTERLY:
|
||||
# Active in months 3, 6, 9, 12 by default
|
||||
if month % 3 == 0:
|
||||
if item.override_amounts and str(month) in item.override_amounts:
|
||||
return float(item.override_amounts[str(month)])
|
||||
return item.amount
|
||||
return float(item.amount)
|
||||
return None
|
||||
|
||||
if freq == RecurringFrequency.BIANNUAL:
|
||||
@@ -54,12 +54,12 @@ def get_effective_amount(item: RecurringItem, month: int, year: int) -> float |
|
||||
base = item.month_of_year or 1
|
||||
second = base + 6 if base <= 6 else base - 6
|
||||
if month in (base, second):
|
||||
return item.amount
|
||||
return float(item.amount)
|
||||
return None
|
||||
|
||||
if freq == RecurringFrequency.YEARLY:
|
||||
if month == (item.month_of_year or 12):
|
||||
return item.amount
|
||||
return float(item.amount)
|
||||
return None
|
||||
|
||||
return None
|
||||
@@ -561,13 +561,13 @@ def _get_december_cumulative(session: Session, year: int) -> float:
|
||||
)
|
||||
).first()
|
||||
if override:
|
||||
return override.override_balance
|
||||
return float(override.override_balance)
|
||||
|
||||
# Compute the full year to get December's cumulative
|
||||
overrides = session.exec(
|
||||
select(BalanceOverride).where(BalanceOverride.year == year)
|
||||
).all()
|
||||
override_map = {o.month: o.override_balance for o in overrides}
|
||||
override_map = {o.month: float(o.override_balance) for o in overrides}
|
||||
|
||||
cumulative = 0.0
|
||||
if year > FRESH_START_YEAR:
|
||||
@@ -591,7 +591,7 @@ def compute_yearly_projection_with_cumulative(
|
||||
overrides = session.exec(
|
||||
select(BalanceOverride).where(BalanceOverride.year == year)
|
||||
).all()
|
||||
override_map = {o.month: o.override_balance for o in overrides}
|
||||
override_map = {o.month: float(o.override_balance) for o in overrides}
|
||||
|
||||
# Determine January carryover
|
||||
if year <= FRESH_START_YEAR:
|
||||
|
||||
Reference in New Issue
Block a user