Match Wealthfolio accounts by providerAccountId, remap accountId on import
Context: Wealthfolio 3.2 generates its own UUIDs on POST /accounts, ignoring any
`id` we supply. Our logical Account.id lives on as `providerAccountId`, which
WF preserves verbatim.
Live run created six duplicate accounts because ensure_account looked up by
our `id`, never found it, and POSTed a new account on every attempt. Deleted
the duplicates manually via DELETE /accounts/{id}.
This change:
- ensure_account now returns Wealthfolio's UUID; matches existing via
(provider, providerAccountId)
- pipeline remaps activity.account_id to the WF UUID at submission time
but keeps dedup keyed on our stable id (WF resets must not blow away
the whole dedup history)
- test updates to the new account-shape + dedup key expectations
poetry run pytest -q 70 passed
poetry run mypy clean
poetry run ruff check clean
This commit is contained in:
parent
ba672a1633
commit
80ca009373
4 changed files with 91 additions and 29 deletions
|
|
@ -73,13 +73,18 @@ async def test_pipeline_skips_dedup_then_imports_new(tmp_path: Path) -> None:
|
|||
|
||||
async def handler(req: httpx.Request) -> httpx.Response:
|
||||
if req.method == "GET" and req.url.path == "/api/v1/accounts":
|
||||
return httpx.Response(200, json=[{"id": "fake-isa"}])
|
||||
# Return account with Wealthfolio-assigned UUID + our providerAccountId.
|
||||
return httpx.Response(
|
||||
200,
|
||||
json=[{
|
||||
"id": "wf-uuid-fake-isa",
|
||||
"provider": "fake",
|
||||
"providerAccountId": "fake-isa",
|
||||
}],
|
||||
)
|
||||
if req.url.path == "/api/v1/activities/import/check":
|
||||
return httpx.Response(200, json={"ok": True})
|
||||
if req.url.path == "/api/v1/activities/import":
|
||||
# The httpx request body is multipart. We don't parse the multipart
|
||||
# properly — we just scan for our dedup tags to confirm the
|
||||
# pipeline pushed the rows it should have.
|
||||
body = req.content.decode()
|
||||
posted_batches.append(body)
|
||||
# Echo back external_ids so dedup.record gets the WF activity id.
|
||||
|
|
@ -135,7 +140,14 @@ async def test_pipeline_records_failure_when_import_rejects(tmp_path: Path) -> N
|
|||
|
||||
async def handler(req: httpx.Request) -> httpx.Response:
|
||||
if req.method == "GET" and req.url.path == "/api/v1/accounts":
|
||||
return httpx.Response(200, json=[{"id": "fake-isa"}])
|
||||
return httpx.Response(
|
||||
200,
|
||||
json=[{
|
||||
"id": "wf-uuid-fake-isa",
|
||||
"provider": "fake",
|
||||
"providerAccountId": "fake-isa",
|
||||
}],
|
||||
)
|
||||
if req.url.path == "/api/v1/activities/import/check":
|
||||
return httpx.Response(400, json={"errors": ["bad row"]})
|
||||
return httpx.Response(500)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue