from __future__ import annotations from datetime import UTC, datetime from email.message import EmailMessage from email.utils import format_datetime from mousehold_agent.imap_importer import parse_email_message def test_klarna_email_becomes_outstanding_promised_payment() -> None: message = EmailMessage() message["From"] = "Klarna " message["To"] = "user@example.com" message["Subject"] = "Deine Bestellung bei Example Shop" message["Date"] = format_datetime(datetime(2026, 6, 20, 12, 0, tzinfo=UTC)) message["Message-ID"] = "" message.set_content( "Bestellnummer: AB-12345\n" "Gesamtbetrag: 84,00 €\n" "Bitte bezahlen bis 30.06.2026.\n" "Klarna Referenz: KR-98765" ) parsed = parse_email_message( message, household_id="household-1", owner_user_id="user-1", source_account_id="account-1", ) observation = parsed["observation"] assert observation is not None assert observation["source_type"] == "klarna_email" assert observation["event_type"] == "promised_payment" assert observation["status"] == "outstanding" assert observation["amount"] == "84.00" assert observation["due_date"] == "2026-06-30" assert observation["provider_transaction_id"] == "KR-98765" def test_paypal_email_becomes_announced_expense() -> None: message = EmailMessage() message["From"] = "service@paypal.de" message["To"] = "user@example.com" message["Subject"] = "You paid Example Merchant" message["Date"] = format_datetime(datetime(2026, 6, 21, 9, 30, tzinfo=UTC)) message["Message-ID"] = "" message.set_content("Payment to: Example Merchant\nTotal EUR 18.99\nTransaction ID: 7AB123456789") parsed = parse_email_message( message, household_id="household-1", owner_user_id="user-1", source_account_id="account-1", ) observation = parsed["observation"] assert observation is not None assert observation["source_type"] == "paypal_email" assert observation["event_type"] == "expense" assert observation["status"] == "announced" assert observation["amount"] == "18.99" assert observation["provider_transaction_id"] == "7AB123456789" def test_html_order_email_uses_html_body_and_announced_status() -> None: message = EmailMessage() message["From"] = "Shop " message["Subject"] = "Your order from Example Store" message["Date"] = format_datetime(datetime(2026, 6, 22, 18, 15, tzinfo=UTC)) message["Message-ID"] = "" message.set_content( "

Order number: ORD-2026-1

Total: € 1.234,56

", subtype="html", ) parsed = parse_email_message( message, household_id="household-1", owner_user_id=None, source_account_id=None, ) observation = parsed["observation"] assert observation is not None assert observation["source_type"] == "order_confirmation_email" assert observation["status"] == "announced" assert observation["amount"] == "1234.56" assert observation["provider_transaction_id"] == "ORD-2026-1" def test_email_without_amount_is_not_importable() -> None: message = EmailMessage() message["From"] = "Klarna " message["Subject"] = "Newsletter" message.set_content("No transaction amount in this message.") parsed = parse_email_message( message, household_id="household-1", owner_user_id=None, source_account_id=None, ) assert parsed["observation"] is None assert parsed["message"]["importable"] is False assert parsed["message"]["skip_reason"] == "No EUR amount found"