Add imap-ingest CLI + ImapProvider: route emails to IE/Schwab parsers

Wires the IE + Schwab email parsers into an actual runnable sync. Walks
the IMAP mailbox, routes each message by sender domain:
  - *@investengine.com → invest_engine.parse_invest_engine_email
  - *@schwab.com       → schwab.parse_schwab_email
then pushes the resulting Activities through the shared pipeline.

broker-sync imap-ingest — new CLI command taking IMAP_HOST/USER/PASSWORD/
DIRECTORY (mirrors the old wealthfolio-sync image's env shape so the
Terraform CronJob's existing env wiring works unchanged).

Verified: poetry run pytest -q → 109 passed + 1 skipped; mypy strict
clean (37 files); ruff + yapf clean.
This commit is contained in:
Viktor Barzin 2026-04-17 22:12:05 +00:00
parent f089b8b93a
commit 6efd03570a
6 changed files with 290 additions and 35 deletions

View file

@ -89,9 +89,7 @@ async def sync_provider_to_wealthfolio(
)
async def _ensure_accounts(
sink: WealthfolioSink, accounts: list[Account]
) -> dict[str, str]:
async def _ensure_accounts(sink: WealthfolioSink, accounts: list[Account]) -> dict[str, str]:
"""Return {our_account_id: wealthfolio_uuid}."""
out: dict[str, str] = {}
for account in accounts:
@ -134,7 +132,9 @@ async def _flush_batch(
for original_account_id, a in batch:
wf_id = by_external.get(a.external_id)
dedup.record(
provider_name, original_account_id, a.external_id,
provider_name,
original_account_id,
a.external_id,
wealthfolio_activity_id=wf_id,
)
ok += 1