from datetime import UTC, datetime from decimal import Decimal import pytest from broker_sync.models import ( Account, AccountType, Activity, ActivityType, FxRateSource, ) def test_account_type_covers_uk_wrappers() -> None: assert { AccountType.ISA, AccountType.SIPP, AccountType.GIA, AccountType.LISA, AccountType.JISA, AccountType.WORKPLACE_PENSION, } <= set(AccountType) def test_activity_type_covers_wealthfolio_types() -> None: # Mirrors Wealthfolio docs/activities/activity-types.md for name in ( "BUY", "SELL", "DIVIDEND", "INTEREST", "DEPOSIT", "WITHDRAWAL", "TRANSFER_IN", "TRANSFER_OUT", "CONVERSION_IN", "CONVERSION_OUT", "FEE", "TAX", ): assert hasattr(ActivityType, name), f"missing {name}" def test_activity_minimal_construct() -> None: a = Activity( external_id="t212:order:1", account_id="t212-isa", account_type=AccountType.ISA, date=datetime(2026, 1, 15, tzinfo=UTC), activity_type=ActivityType.BUY, symbol="VUAG", quantity=Decimal("10"), unit_price=Decimal("85.5"), currency="GBP", ) assert a.external_id == "t212:order:1" assert a.fee == Decimal("0") assert a.fx_rate_source is None def test_buy_requires_qty_and_price() -> None: with pytest.raises(ValueError, match="BUY.*quantity"): Activity( external_id="x", account_id="a", account_type=AccountType.GIA, date=datetime(2026, 1, 1, tzinfo=UTC), activity_type=ActivityType.BUY, symbol="VUAG", currency="GBP", ) def test_dividend_requires_amount() -> None: with pytest.raises(ValueError, match="DIVIDEND.*amount"): Activity( external_id="x", account_id="a", account_type=AccountType.GIA, date=datetime(2026, 1, 1, tzinfo=UTC), activity_type=ActivityType.DIVIDEND, currency="GBP", ) def test_wealthfolio_csv_row_shape() -> None: a = Activity( external_id="ie:2026-04:0001", account_id="ie-isa", account_type=AccountType.ISA, date=datetime(2026, 4, 1, 10, 30, tzinfo=UTC), activity_type=ActivityType.BUY, symbol="VWRP", quantity=Decimal("2.5"), unit_price=Decimal("110.00"), currency="GBP", fee=Decimal("0.50"), amount_gbp=Decimal("275.50"), fx_rate_gbp=Decimal("1.0"), fx_rate_source=FxRateSource.ECB_LIVE, notes="sync:invest-engine:ie:2026-04:0001", ) row = a.to_wealthfolio_csv_row() # Wealthfolio activity import columns (from docs): # date, activity_type, symbol, quantity, unit_price, currency, fee, amount, notes, ... assert row["date"] == "2026-04-01T10:30:00+00:00" assert row["activity_type"] == "BUY" assert row["symbol"] == "VWRP" assert row["quantity"] == "2.5" assert row["unit_price"] == "110.00" assert row["currency"] == "GBP" assert row["fee"] == "0.50" assert row["notes"] == "sync:invest-engine:ie:2026-04:0001" def test_account_construct() -> None: acc = Account( id="t212-isa", name="Trading212 ISA", account_type=AccountType.ISA, currency="GBP", provider="trading212", ) assert acc.id == "t212-isa" assert acc.account_type is AccountType.ISA