fix: align portfolio-hub ledger write adapter to live API contract

REQ-017 CHG-20260606-01. Live portfolio-hub returned 404 for the
trex-orbit-assumed POST /v1/assets/{asset_id}/ledger/trades. Correct to
POST /v1/portfolios/{portfolio_id}/ledger/trades with body keys
quantity/fee_amount/tax_amount (was qty/fee/tax), success 201. Reverified
with live e2e (201 Created, outbox COMPLETED) + durability drain of the
prior 404'd item. Resolves the REL-001 ledger-write release blocker.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-06-06 11:27:30 +09:00
co-authored by Claude Opus 4.7
parent e24de29335
commit 9e64a24441
6 changed files with 81 additions and 19 deletions
+13 -8
View File
@@ -1,12 +1,17 @@
"""portfolio-hub ledger HTTP adapter (REQ-017, dcy-004).
Mirrors trex-orbit `PortfolioHubClient.post_ledger_trade`:
POST /v1/assets/{asset_id}/ledger/trades
body keys: side, qty, price, fee, tax, executed_at, execution_id, order_id
- 2xx => recorded (or duplicate accepted idempotently)
Live portfolio-hub contract (verified against openapi, REQ-017 CHG-04):
POST /v1/portfolios/{portfolio_id}/ledger/trades
body keys: side, quantity, price, fee_amount, tax_amount, executed_at,
execution_id, order_id
- 2xx (201) => recorded (or duplicate accepted idempotently)
- 409 => LedgerConflictError (operator resolution)
- 4xx (other)/5xx => LedgerRetryableError (outbox retries)
- httpx error => LedgerRetryableError
`asset_id` on LedgerTrade carries the portfolio_id value (REQ-018:
asset_id == portfolio_id), so it maps directly onto the {portfolio_id}
path segment.
"""
from __future__ import annotations
@@ -48,10 +53,10 @@ class PortfolioHubLedger:
def _payload(trade: LedgerTrade) -> dict:
return {
"side": trade.side,
"qty": trade.qty,
"quantity": trade.qty,
"price": trade.price,
"fee": trade.fee,
"tax": trade.tax,
"fee_amount": trade.fee,
"tax_amount": trade.tax,
"executed_at": trade.executed_at.isoformat() if trade.executed_at else None,
"execution_id": trade.execution_id,
"order_id": trade.order_id,
@@ -65,7 +70,7 @@ class PortfolioHubLedger:
timeout=self._timeout)
def record_trade(self, trade: LedgerTrade) -> LedgerWriteResult:
url = f"{self._base_url}/v1/assets/{trade.asset_id}/ledger/trades"
url = f"{self._base_url}/v1/portfolios/{trade.asset_id}/ledger/trades"
try:
resp = self._post(url, json=self._payload(trade))
except httpx.HTTPError as exc: