mirror of
https://github.com/escalante29/WealthySmart.git
synced 2026-07-17 10:08:46 +02:00
Analytics: date-range filter + fix category endpoint Decimal crash
by-category and daily-spending accept start_date/end_date (range wins over cycle); Analytics gets a two-month calendar range picker beside the cycle selector. Fixes a latent float/Decimal TypeError that 500'd spending_by_category whenever it had data — the category donut had never rendered. Regression + range tests added. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
62
backend/tests/test_analytics.py
Normal file
62
backend/tests/test_analytics.py
Normal file
@@ -0,0 +1,62 @@
|
||||
"""Analytics endpoints: category aggregation (Decimal regression) and the
|
||||
arbitrary date-range filters added for the Analytics range picker."""
|
||||
|
||||
from datetime import datetime
|
||||
from decimal import Decimal
|
||||
|
||||
from app.api.v1.endpoints.analytics import daily_spending, spending_by_category
|
||||
from app.models.models import Category, Transaction
|
||||
|
||||
from tests.test_installments import make_cc_tx
|
||||
|
||||
|
||||
def seed(session):
|
||||
cat = Category(name="Groceries")
|
||||
session.add(cat)
|
||||
session.commit()
|
||||
make_cc_tx(session, merchant="A", amount="1000.50", reference="a1",
|
||||
date=datetime(2026, 6, 2), category_id=cat.id)
|
||||
make_cc_tx(session, merchant="B", amount="2000.00", reference="b1",
|
||||
date=datetime(2026, 6, 20))
|
||||
return cat
|
||||
|
||||
|
||||
class TestSpendingByCategory:
|
||||
def test_decimal_sum_does_not_crash_and_percentages_add_up(self, session):
|
||||
"""Regression: Decimal grand total vs float row total raised
|
||||
TypeError, 500ing the endpoint whenever it had data."""
|
||||
seed(session)
|
||||
rows = spending_by_category(session=session, _user="t")
|
||||
assert {r.category_name for r in rows} == {"Groceries", "Uncategorized"}
|
||||
assert sum(r.percentage for r in rows) == 100.0
|
||||
|
||||
def test_date_range_overrides_cycle(self, session):
|
||||
seed(session)
|
||||
rows = spending_by_category(
|
||||
start_date="2026-06-01",
|
||||
end_date="2026-06-10",
|
||||
cycle_year=2026,
|
||||
cycle_month=1, # would match nothing; range must win
|
||||
session=session,
|
||||
_user="t",
|
||||
)
|
||||
assert len(rows) == 1
|
||||
assert rows[0].category_name == "Groceries"
|
||||
assert rows[0].total == 1000.50
|
||||
|
||||
|
||||
class TestDailySpending:
|
||||
def test_date_range_filter(self, session):
|
||||
seed(session)
|
||||
rows = daily_spending(
|
||||
start_date="2026-06-15", end_date="2026-07-01",
|
||||
session=session, _user="t",
|
||||
)
|
||||
assert [r.date for r in rows] == ["2026-06-20"]
|
||||
assert rows[0].total == 2000.00
|
||||
|
||||
def test_future_cuotas_excluded(self, session):
|
||||
make_cc_tx(session, merchant="FUTURE", amount="500.00",
|
||||
reference="f1", date=datetime(2030, 1, 19))
|
||||
rows = daily_spending(session=session, _user="t")
|
||||
assert rows == []
|
||||
Reference in New Issue
Block a user