Finance-Accounts/ar-aging-app/backend/tests/test_fx_dashboard.py

79 lines
3.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

"""
Dual-currency dashboard figures.
The AR Ledger shows every movement in the marketplace's local currency AND in USD,
converted at each TRANSACTION DATE's exchange rate (a daily override when one exists,
the marketplace month rate otherwise). The opening balance has no transaction date, so
it converts at the month rate.
Also the regression for the fx-daily endpoint: after payouts moved out of _daily_rows
into _payout_events, fx_daily still unpacked 4-tuples and crashed on every session with
data — the "Daily exchange rates" table never rendered.
Fixture dates (make_amazon_xlsx, USA, month-end 2026-01-31, lag 2 → cutoff Jan 29):
revenue: Jan 5 +1000 · Jan 10 +300 · Jan 15 +2000 · Jan 20 +80 · Jan 31 +500
payouts: Jan 6 1000 (received) · Jan 12 300 (received) · Jan 30 2000 (in transit)
→ closing = 3880 1300 = 2580
"""
from __future__ import annotations
from fastapi.testclient import TestClient
from app.api.main import app
from app.db.database import init_db
from tests.test_payout_receipts import _fresh
def test_fx_daily_no_longer_crashes_and_covers_payout_dates():
init_db()
with TestClient(app) as c:
sid = _fresh(c, "fx daily regression")
r = c.get(f"/api/sessions/{sid}/fx-daily")
assert r.status_code == 200
data = r.json()
assert data["available"] is True
by_date = {row["date"]: row for row in data["rows"]}
# Revenue sits on its transaction date…
assert by_date["2026-01-15"]["revenue"] == 2000.0
# …and payouts on their effective date, in the same table.
assert by_date["2026-01-06"]["payouts"] == -1000.0
assert by_date["2026-01-30"]["payouts"] == -2000.0
# USA converts 1:1 — USD total equals local total = 3880 3300 net movement.
assert data["month_rate"] == 1.0
assert data["total_local"] == 580.0
assert data["total_usd"] == data["total_local"]
def test_ledger_detail_shows_usd_at_transaction_date_rates():
init_db()
with TestClient(app) as c:
sid = _fresh(c, "dual currency ledger")
# Daily override for the big revenue day; every other date uses the month rate.
assert c.put(f"/api/sessions/{sid}/fx-daily", json=[
{"marketplace": "USA", "rate_date": "2026-01-15", "rate": 1.25},
]).status_code == 200
d = c.get(f"/api/sessions/{sid}/ledger-detail").json()
per = {p["key"]: p for p in d["periods"]}
# Jan 15's revenue converts at ITS OWN day's rate…
assert per["2026-01-15"]["revenue"] == 2000.0
assert per["2026-01-15"]["revenue_usd"] == 2500.0
# …every other date at the month rate (1.0 for USA).
assert per["2026-01-05"]["revenue_usd"] == per["2026-01-05"]["revenue"] == 1000.0
assert per["2026-01-06"]["payouts_received_usd"] == -1000.0
assert per["2026-01-30"]["payouts_in_transit_usd"] == -2000.0
# Opening has no transaction date → month rate; the USD running balance then
# absorbs the daily-rate spread: closing_usd = closing + 2000 × (1.25 1).
assert d["month_rate"] == 1.0
assert d["opening_usd"] == 0.0
assert d["closing"] == 2580.0
assert d["closing_usd"] == 3080.0
assert d["in_transit_total_usd"] == -2000.0
# The local-currency figures are untouched by the daily override.
assert per["2026-01-15"]["balance"] == per["2026-01-15"]["balance_usd"] - 500.0