sinks: match Wealthfolio NewAccount camelCase schema + required booleans

Wealthfolio 3.2's POST /api/v1/accounts was 422ing on live traffic — its
NewAccount struct uses camelCase field names and requires isDefault +
isActive as booleans. Reference:
https://github.com/afadil/wealthfolio/blob/main/apps/server/src/models.rs#L~145

Sends trackingMode=TRANSACTIONS so Wealthfolio computes holdings from
our imported activities (vs HOLDINGS mode which requires periodic
holdings snapshots). Populates providerAccountId so the broker account
is traceable back to our sync's id scheme.

Test plan:
  poetry run pytest -q   →  70 passed
  poetry run mypy        →  clean
  poetry run ruff check  →  clean

Live re-run of the backfill Job follows this commit's image rebuild.
This commit is contained in:
Viktor Barzin 2026-04-17 20:29:43 +00:00
parent 1d0769c9e6
commit ea881e272b
2 changed files with 11 additions and 2 deletions

View file

@ -126,15 +126,22 @@ class WealthfolioSink:
existing = await self.list_accounts()
if any(a.get("id") == account.id for a in existing):
return
# Wealthfolio 3.2's NewAccount is camelCase with required booleans.
# See apps/server/src/models.rs#NewAccount.
resp = await self._request(
"POST",
_ACCOUNTS_PATH,
json={
"id": account.id,
"name": account.name,
"account_type": str(account.account_type),
"accountType": str(account.account_type),
"currency": account.currency,
"isDefault": False,
"isActive": True,
"isArchived": False,
"trackingMode": "TRANSACTIONS",
"provider": account.provider,
"providerAccountId": account.id,
},
)
resp.raise_for_status()

View file

@ -183,8 +183,10 @@ async def test_ensure_account_creates_if_missing(tmp_path: Path) -> None:
await sink.ensure_account(acc)
assert len(posted) == 1
assert posted[0]["id"] == "t212-isa"
assert posted[0]["account_type"] == "ISA"
assert posted[0]["accountType"] == "ISA"
assert posted[0]["currency"] == "GBP"
assert posted[0]["isActive"] is True
assert posted[0]["isDefault"] is False
# -- Activity import --