feat: add portfolio item symbol to v1 responses

This commit is contained in:
2026-05-24 13:09:37 +09:00
parent 3a78e5c138
commit 136ae16885
17 changed files with 655 additions and 11 deletions
+8 -4
View File
@@ -300,21 +300,24 @@
- Auth: any valid token; service/client → HTTP 403
- Body: `{"asset_id": "<uuid>", "broker": "<str>", "name": "<str|null>", "cash_balance": <float>, "asset_quantity": <float>, "asset_price": <float>, "profit_buffer": <float>, "strategy_name": "<str|null>", "strategy_params": {<dict>}, "managed_by_daemon_id": "<str|null>", "user_id": "<str|null> (admin only)"}`
- Response: HTTP 201 `PortfolioItem`
- Response: HTTP 201 `PortfolioItem {"portfolio_id": "<uuid>", "asset_id": "<uuid>", "symbol": "<assets.symbol|null>", "owner_user_id": "<str|null>", "broker": "<str>", "status": "<str>", "name": "<str>", ...}`
- Note: `symbol` is populated from the server-side joined asset row (`portfolios.asset_id -> assets.asset_id -> assets.symbol`), not from client-side catalog reconstruction.
- Error: HTTP 422 if asset not found or inactive; HTTP 403 if service/client token
### Endpoint: `PATCH /v1/portfolios/{portfolio_id}`
- Auth: any valid token; service/client → HTTP 403; ownership required
- Body: `{"broker": "<str|null>", "status": "<str|null>", "name": "<str|null>", "strategy_name": "<str|null>", "strategy_params": {<dict|null>}, "asset_price": <float|null>, "managed_by_daemon_id": "<str|null>"}`
- Response: HTTP 200 `PortfolioItem`
- Response: HTTP 200 `PortfolioItem {"portfolio_id": "<uuid>", "asset_id": "<uuid>", "symbol": "<assets.symbol|null>", ...}`
- Note: response `symbol` is emitted from the joined asset row referenced by `asset_id`.
- Error: HTTP 403 if service/client or ownership mismatch; HTTP 404 if portfolio not found; HTTP 409 if portfolio is disabled and non-status fields are provided
### Endpoint: `DELETE /v1/portfolios/{portfolio_id}` (Soft Delete)
- Auth: any valid token; service/client → HTTP 403; ownership required
- Body: none
- Response: HTTP 200 `PortfolioItem` with `status="disabled"`, `managed_by_daemon_id=null`
- Response: HTTP 200 `PortfolioItem` with `status="disabled"`, `managed_by_daemon_id=null`, `symbol="<assets.symbol|null>"`
- Note: soft delete does not break the asset join; `symbol` remains the linked `assets.symbol` value in the HTTP 200 response.
- Dependent data: portfolio_comments and tag_ids are preserved on soft delete; only status and daemon assignment change
- Error: HTTP 403 if service/client or ownership mismatch; HTTP 404 if not found
@@ -325,7 +328,8 @@
- Branching by token type:
- `service`: returns portfolios where `managed_by_daemon_id = token.daemon_id`; NULL daemon_id → HTTP 403
- `user/admin`: returns owner's own portfolios; admin may override with `?user_id=<id>`
- Response: HTTP 200 `PortfolioListResponse {"portfolios": [...], "total": <int>}`
- Response: HTTP 200 `PortfolioListResponse {"portfolios": [{"portfolio_id": "<uuid>", "asset_id": "<uuid>", "symbol": "<assets.symbol|null>", ...}], "total": <int>}`
- Note: list items are serialized from the server-side `portfolios JOIN assets` result; `symbol` must equal the joined `assets.symbol` for each returned `asset_id`.
### Endpoint: `GET /v1/portfolios/{portfolio_id}/tags`