Brokerage data sync (Trading 212, Schwab, Fidelity, IMAP-CSV) → Wealthfolio. Image is published as viktor/wealthfolio-sync per the wealthfolio stack convention.
Find a file
Viktor Barzin f089b8b93a Add Schwab email parser (port from finance/)
Schwab's workplace-RSU confirmation emails have 5 data td elements
with class='dark-background-body' align='right': date, direction, qty,
ticker, price-with-currency-sign. One email → one Activity.

- parse_schwab_email(raw_html) -> list[Activity] (1-item or empty)
- Empty on any parse failure (IMAP batch shouldn't crash on one bad mail)
- Deterministic external_id ('schwab📅ticker:type:qty') — stable
  across re-pulls so dedup works
- Hardcoded to account 'schwab-workplace' / AccountType.GIA / USD
- 6 unit tests: SELL + BUY happy path, malformed, missing cells,
  external-id stability, commas in price

Dropped from the original finance port:
- msg_timestamp-based external id (non-deterministic — would re-import
  on every IMAP walk). Replaced with a hash-stable key.
- Currency.from_sign() currency hack. Schwab US is USD-only; we'll add
  FX when that changes.

poetry run pytest -q   →  109 passed, 1 skipped
poetry run mypy        →  clean (added types-python-dateutil)
poetry run ruff check  →  clean
2026-04-17 22:08:40 +00:00
.github/workflows CI: build image from phase-0-scaffold branch too (bootstrap) 2026-04-17 19:51:09 +00:00
.woodpecker Add GHA build + Woodpecker deploy pipelines 2026-04-17 19:32:00 +00:00
broker_sync Add Schwab email parser (port from finance/) 2026-04-17 22:08:40 +00:00
tests Add Schwab email parser (port from finance/) 2026-04-17 22:08:40 +00:00
.gitignore Initial scaffold + canonical Activity model 2026-04-17 19:16:11 +00:00
Dockerfile Fix live Wealthfolio login + Dockerfile poetry path 2026-04-17 20:17:24 +00:00
poetry.lock Add Schwab email parser (port from finance/) 2026-04-17 22:08:40 +00:00
pyproject.toml Add Schwab email parser (port from finance/) 2026-04-17 22:08:40 +00:00