feat(api): add owner-scoped manual ledger endpoint

This commit is contained in:
2026-07-14 19:49:03 +09:00
parent 762cf11376
commit b3447f699e
11 changed files with 1022 additions and 16 deletions
+15
View File
@@ -255,6 +255,21 @@
11. Duplicate key + different payload → HTTP 409.
- 구 path `POST /v1/assets/{asset_id}/ledger/trades`: BAT-011에서 제거. 호출 시 HTTP 404.
## Flow: `v1 API — POST /v1/portfolios/{portfolio_id}/ledger/manual` (REQ-056, BAT-024)
1. DB user/session token auth required. Service/client/env tokens fail closed with HTTP 403.
2. `_get_portfolio_or_404()` enforces owner scope; non-owner receives HTTP 403.
3. Disabled portfolio receives HTTP 409 `PORTFOLIO_DISABLED`.
4. If `managed_by_daemon_id IS NOT NULL` and request lacks `confirm_daemon_managed_manual_write=true`, the API returns HTTP 409 `MANUAL_WRITE_REQUIRES_CONFIRMATION` with daemon id and required confirmation marker.
5. Valid actions dispatch to a single repository transaction that locks the portfolio row (`FOR UPDATE OF p`), calculates the action effect, appends a `portfolio_ledger` row with `source='manual'`, and updates the portfolio snapshot.
6. BUY/SELL require sufficient cash/quantity. BUFFER_OUT/BUFFER_IN/WITHDRAW/PROFIT require sufficient buffer/cash as appropriate. Insufficient state returns HTTP 409 with structured code.
7. REVERSAL requires `target_ledger_entry_id`, rejects duplicate reversal targets, and appends a reversing row instead of mutating/deleting the target.
8. Response includes after-snapshot: `cash_balance_after`, `asset_quantity_after`, `profit_buffer_after`, `total_value_after`.
9. `GET /v1/portfolios/{portfolio_id}/ledger/manual` returns newest manual entries only (`source='manual'`).
10. `GET /v1/portfolios/{portfolio_id}/returns/summary` returns `net_contributed_capital=sum(INVEST)-sum(WITHDRAW)` and `cumulative_profit_withdrawn=sum(PROFIT)` separately.
## Flow: `v1 API — POST /auth/service-tokens`
1. Admin token auth required (`require_admin` dependency).