"""One card per scope for the home screen.""" from datetime import timedelta from decimal import Decimal from factories import make_account, make_event, make_instrument, make_price, refresh from fintracker.analytics import today_local from fintracker.models import AccountKind, AccountRole, EventKind URL = "/api/v1/analytics/overview" async def _broker(name: str) -> int: return await make_account( name=name, kind=AccountKind.broker, role=AccountRole.investment, balance=None ) async def _invest(account: int, *, today_price: str) -> None: """10 000 ₽ in, 100 shares at 100; the price is flat until today, when it is `today_price`.""" t = today_local() bought = t - timedelta(days=5) sber = await make_instrument(ticker=f"T{account}") await make_event(bought, account_id=account, kind=EventKind.deposit, amount=10000) await make_event( bought, account_id=account, kind=EventKind.buy, instrument_id=sber, quantity=100, price=100, amount=-10000, ) # fmt: skip d = bought while d < t: await make_price(d, instrument_id=sber, close="100") d += timedelta(days=1) await make_price(t, instrument_id=sber, close=today_price) async def test_cards_carry_value_result_and_the_change_over_the_last_day(client, auth_headers): account = await _broker("Брокер") await _invest(account, today_price="105") await refresh() r = await client.get(URL, headers=auth_headers) assert r.status_code == 200, r.text cards = {c["scope"]: c for c in r.json()} card = cards[f"account:{account}"] assert card["name"] == "Брокер" assert card["kind"] == "account" assert Decimal(card["total_rub"]) == 10500 assert Decimal(card["invested_rub"]) == 10000 assert Decimal(card["pnl_rub"]) == 500 assert Decimal(card["pnl_pct"]) == Decimal("0.05") assert Decimal(card["day_change_rub"]) == 500 assert Decimal(card["day_change_pct"]) == Decimal("500") / Decimal("10000") assert Decimal(card["income_year_rub"]) == 0 async def test_all_comes_first_then_portfolios_then_accounts_by_value(client, auth_headers): small, big = await _broker("Малый"), await _broker("Большой") await _invest(small, today_price="100") await _invest(big, today_price="130") created = await client.post( "/api/v1/portfolios", json={"name": "Мой", "account_ids": [small]}, headers=auth_headers ) assert created.status_code == 201 await refresh() cards = (await client.get(URL, headers=auth_headers)).json() assert [c["kind"] for c in cards] == ["all", "portfolio", "account", "account"] assert [c["name"] for c in cards[2:]] == ["Большой", "Малый"] assert Decimal(cards[0]["total_rub"]) == Decimal(cards[2]["total_rub"]) + Decimal( cards[3]["total_rub"] ) async def test_an_account_switched_off_has_no_card(client, auth_headers): kept, off = await _broker("Оставить"), await _broker("Отключить") await _invest(kept, today_price="100") await _invest(off, today_price="100") await client.patch(f"/api/v1/accounts/{off}", json={"disabled": True}, headers=auth_headers) await refresh() names = [c["name"] for c in (await client.get(URL, headers=auth_headers)).json()] assert "Оставить" in names assert "Отключить" not in names async def test_nothing_built_yet_is_an_empty_list(client, auth_headers): assert (await client.get(URL, headers=auth_headers)).json() == []