You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
106 lines
3.8 KiB
106 lines
3.8 KiB
from datetime import date |
|
from decimal import Decimal |
|
|
|
import pytest |
|
from django.urls import reverse |
|
from django.utils import timezone |
|
|
|
from finance.models import Account, Category, Transaction |
|
|
|
|
|
pytestmark = pytest.mark.django_db |
|
|
|
|
|
def make_account(name="Synthetic Bank", *, currency="BRL"): |
|
return Account.objects.create(name=name, kind=Account.Kind.BANK, currency=currency) |
|
|
|
|
|
def post(account, amount, kind, posting_date, *, category=None): |
|
return Transaction.objects.create( |
|
account=account, |
|
amount=Decimal(amount), |
|
kind=kind, |
|
posting_date=posting_date, |
|
category=category, |
|
) |
|
|
|
|
|
def test_monthly_report_renders_exact_totals_category_rows_and_account_balances(client): |
|
bank = make_account() |
|
savings = make_account("Synthetic Savings") |
|
food = Category.objects.create(name="Synthetic Food", kind=Category.Kind.EXPENSE) |
|
post(bank, "500.00", Transaction.Kind.OPENING, date(2025, 12, 31)) |
|
post(bank, "1000.00", Transaction.Kind.INCOME, date(2026, 1, 2)) |
|
post(bank, "-300.00", Transaction.Kind.EXPENSE, date(2026, 1, 3), category=food) |
|
post(bank, "50.00", Transaction.Kind.REFUND, date(2026, 1, 25), category=food) |
|
post(bank, "-20.00", Transaction.Kind.EXPENSE, date(2026, 1, 26)) |
|
post(bank, "-200.00", Transaction.Kind.TRANSFER, date(2026, 1, 27)) |
|
post(savings, "200.00", Transaction.Kind.TRANSFER, date(2026, 1, 27)) |
|
|
|
response = client.get(reverse("monthly-report"), {"month": "2026-01", "currency": "BRL"}) |
|
|
|
assert response.status_code == 200 |
|
body = response.content.decode() |
|
assert "Monthly report" in body |
|
assert "1,000.00" in body |
|
assert "320.00" in body |
|
assert "50.00" in body |
|
assert "270.00" in body |
|
assert "730.00" in body |
|
assert "Synthetic Food" in body |
|
assert "Uncategorized" in body |
|
assert "Synthetic Bank" in body and "1,030.00" in body |
|
assert "Synthetic Savings" in body and "200.00" in body |
|
|
|
|
|
@pytest.mark.parametrize( |
|
("parameters", "expected_error"), |
|
[ |
|
({"month": "01/2026", "currency": "BRL"}, "invalid_month"), |
|
({"month": "2026-01", "currency": "brl"}, "invalid_currency"), |
|
], |
|
) |
|
def test_invalid_report_selection_is_visible_and_not_silently_replaced(client, parameters, expected_error): |
|
response = client.get(reverse("monthly-report"), parameters) |
|
|
|
assert response.status_code == 400 |
|
assert expected_error in response.content.decode() |
|
|
|
|
|
def test_home_defaults_to_local_month_and_first_available_currency(client, monkeypatch): |
|
make_account("Synthetic USD", currency="USD") |
|
make_account("Synthetic BRL", currency="BRL") |
|
monkeypatch.setattr(timezone, "localdate", lambda: date(2026, 4, 17)) |
|
|
|
response = client.get(reverse("home")) |
|
|
|
assert response.status_code == 200 |
|
body = response.content.decode() |
|
assert "Dashboard" in body |
|
assert 'value="2026-04"' in body |
|
assert '<option value="BRL" selected>BRL</option>' in body |
|
assert "Transactions" in body |
|
|
|
|
|
def test_home_uses_brl_when_no_account_currency_exists(client, monkeypatch): |
|
monkeypatch.setattr(timezone, "localdate", lambda: date(2026, 4, 17)) |
|
|
|
response = client.get(reverse("home")) |
|
|
|
assert response.status_code == 200 |
|
assert '<option value="BRL" selected>BRL</option>' in response.content.decode() |
|
|
|
|
|
def test_negative_spending_and_balance_keep_their_sign_and_are_labeled(client): |
|
bank = make_account() |
|
post(bank, "-100.00", Transaction.Kind.OPENING, date(2025, 12, 31)) |
|
post(bank, "25.00", Transaction.Kind.REFUND, date(2026, 1, 3)) |
|
|
|
response = client.get(reverse("monthly-report"), {"month": "2026-01", "currency": "BRL"}) |
|
|
|
body = response.content.decode() |
|
assert response.status_code == 200 |
|
assert "Net spending (negative)" in body |
|
assert "-25.00" in body |
|
assert "Balance (negative)" in body |
|
assert "-75.00" in body
|
|
|