from __future__ import annotations from datetime import date from decimal import Decimal from mousehold_api.schemas import ManualObservationCreate, SplitLineCreate from mousehold_api.services.ingestion import create_observation_with_candidate from mousehold_domain import FinancialEventStatus, FinancialEventType, ObservationStatus, SourceType from sqlalchemy.orm import Session def test_duplicate_observation_is_flagged_without_second_event( session: Session, household_setup: dict[str, str], ) -> None: payload = ManualObservationCreate( household_id=household_setup["household_id"], owner_user_id=household_setup["user_a_id"], source_account_id=household_setup["account_a_id"], source_reference="same-manual-input", amount=Decimal("120.00"), currency="EUR", event_date=date(2026, 1, 1), merchant="Groceries", description="Weekly groceries", split_lines=[ SplitLineCreate(user_id=household_setup["user_a_id"], share_amount=Decimal("60.00")), SplitLineCreate(user_id=household_setup["user_b_id"], share_amount=Decimal("60.00")), ], ) first_observation, first_event = create_observation_with_candidate(session, payload) second_observation, second_event = create_observation_with_candidate(session, payload) assert first_observation.status == ObservationStatus.CANDIDATE_CREATED assert first_event is not None assert second_observation.status == ObservationStatus.DUPLICATE_SOURCE assert second_event is None def test_email_with_due_date_becomes_outstanding_event( session: Session, household_setup: dict[str, str], ) -> None: payload = ManualObservationCreate( household_id=household_setup["household_id"], owner_user_id=household_setup["user_a_id"], source_type=SourceType.KLARNA_EMAIL, amount=Decimal("84.00"), currency="EUR", event_date=date(2026, 1, 3), due_date=date(2026, 2, 2), merchant="Klarna Shop", description="Pay later purchase", ) _observation, event = create_observation_with_candidate(session, payload) assert event is not None assert event.status == FinancialEventStatus.OUTSTANDING def test_bank_provider_debit_becomes_liability_payment( session: Session, household_setup: dict[str, str], ) -> None: payload = ManualObservationCreate( household_id=household_setup["household_id"], owner_user_id=household_setup["user_a_id"], source_account_id=household_setup["account_a_id"], source_type=SourceType.BANK_CSV, amount=Decimal("250.00"), currency="EUR", event_date=date(2026, 1, 15), merchant="Visa Kartenabrechnung", description="Monthly credit card payment", ) _observation, event = create_observation_with_candidate(session, payload) assert event is not None assert event.event_type == FinancialEventType.LIABILITY_PAYMENT assert event.status == FinancialEventStatus.CONFIRMED