from datetime import UTC, datetime from decimal import Decimal from pathlib import Path from broker_sync.dedup import SyncRecordStore from broker_sync.models import AccountType, Activity, ActivityType def _buy(external_id: str) -> Activity: return Activity( external_id=external_id, account_id="t212-isa", account_type=AccountType.ISA, date=datetime(2026, 1, 1, tzinfo=UTC), activity_type=ActivityType.BUY, symbol="VUAG", quantity=Decimal("1"), unit_price=Decimal("100"), currency="GBP", ) def test_store_schema_is_idempotent(tmp_path: Path) -> None: db = tmp_path / "s.db" SyncRecordStore(db) # creates schema SyncRecordStore(db) # second open must not raise assert db.exists() def test_has_seen_returns_false_for_new(tmp_path: Path) -> None: s = SyncRecordStore(tmp_path / "s.db") assert s.has_seen("trading212", "t212-isa", "order-1") is False def test_record_then_has_seen(tmp_path: Path) -> None: s = SyncRecordStore(tmp_path / "s.db") s.record("trading212", "t212-isa", "order-1", wealthfolio_activity_id="wf-42") assert s.has_seen("trading212", "t212-isa", "order-1") is True # Same (provider, account, external_id) from a different caller is still seen. assert s.has_seen("trading212", "t212-isa", "order-1") is True def test_record_is_idempotent(tmp_path: Path) -> None: s = SyncRecordStore(tmp_path / "s.db") s.record("trading212", "t212-isa", "order-1", wealthfolio_activity_id="wf-42") s.record("trading212", "t212-isa", "order-1", wealthfolio_activity_id="wf-43") # Second insert must not raise. Original first_seen / wealthfolio id preserved. stored = s.get("trading212", "t212-isa", "order-1") assert stored is not None assert stored["wealthfolio_activity_id"] == "wf-42" def test_scope_per_provider_and_account(tmp_path: Path) -> None: s = SyncRecordStore(tmp_path / "s.db") s.record("trading212", "t212-isa", "order-1", wealthfolio_activity_id="wf-1") # Different provider, same external_id — NOT seen. assert s.has_seen("invest-engine", "t212-isa", "order-1") is False # Different account, same external_id — NOT seen. assert s.has_seen("trading212", "t212-invest", "order-1") is False def test_filter_new_drops_seen(tmp_path: Path) -> None: s = SyncRecordStore(tmp_path / "s.db") s.record("trading212", "t212-isa", "a", wealthfolio_activity_id=None) activities = [_buy("a"), _buy("b"), _buy("c")] fresh = s.filter_new("trading212", activities) assert [a.external_id for a in fresh] == ["b", "c"]