feat: add portfolio item symbol to v1 responses
This commit is contained in:
@@ -20,7 +20,8 @@
|
||||
- **body 스키마** (`PortfolioCreateRequest` 신규):
|
||||
- 필수: `asset_id`, `broker`
|
||||
- 선택: `name`, `cash_balance`, `asset_quantity`, `asset_price`, `profit_buffer`, `strategy_name`, `strategy_params`, `managed_by_daemon_id`, `user_id`(admin 분기 전용)
|
||||
- 응답: HTTP 201 + 생성된 portfolio의 `PortfolioItem`(`portfolio_id`, `asset_id`, `owner_user_id`, ...).
|
||||
- 응답: HTTP 201 + 생성된 portfolio의 `PortfolioItem`(`portfolio_id`, `asset_id`, `symbol`, `owner_user_id`, ...).
|
||||
- 응답의 `symbol` 값은 생성된 `portfolios.asset_id`가 가리키는 `assets.symbol`을 기준으로 server-side join 결과에서 채운다. 클라이언트가 별도 catalog lookup으로 복원하는 방식은 본 REQ 범위의 정식 계약이 아니다.
|
||||
- catalog 검증 위치(서비스 계층 공통 진입점 vs v1 라우터 레이어 한정)는 본 REQ 구현 시점에 결정. dcy-003 R-5 트레이드오프 reference 참조.
|
||||
|
||||
## Acceptance Criteria
|
||||
@@ -31,6 +32,7 @@
|
||||
5. Given body `asset_id`가 catalog에 미존재 또는 `status='inactive'`, When `POST /v1/portfolios`, Then HTTP 422 또는 403로 거부되고 portfolio row가 생성되지 않는다.
|
||||
6. Given Bearer token 없음, When `POST /v1/portfolios`, Then HTTP 401.
|
||||
7. Given non-admin token + body `user_id` 지정, When `POST /v1/portfolios`, Then `user_id`는 무시되어 `owner_user_id == auth.user_id`로 생성되거나 HTTP 422.
|
||||
8. Given active catalog asset(`asset_id=<uuid>`, `symbol="005930"`), When `POST /v1/portfolios`, Then HTTP 201 응답의 `PortfolioItem.symbol == "005930"` 이고 값은 해당 asset row join 결과와 일치한다.
|
||||
|
||||
## Impacted Area
|
||||
- Docs:
|
||||
@@ -54,6 +56,64 @@
|
||||
|
||||
## Change Log
|
||||
|
||||
### CHG-20260524-02
|
||||
- Date: 2026-05-24
|
||||
- Author: Hermes Agent
|
||||
|
||||
#### Change Summary
|
||||
- Status: Approved → Implemented
|
||||
|
||||
#### Intent
|
||||
- BAT-014 verification 완료. `PortfolioItem.symbol` 응답 계약이 코드, 테스트, baseline 문서에 반영되었고 REQ-025 acceptance criteria 전부가 trace 가능해졌다.
|
||||
|
||||
#### Acceptance Criteria Delta
|
||||
- No change
|
||||
|
||||
#### Impacted Area Delta
|
||||
- No change
|
||||
|
||||
#### Delivery Trace Delta
|
||||
- Batches: BAT-014 (release-candidate); BAT-009 response-contract evidence superseded by BAT-014
|
||||
- Releases: pending
|
||||
|
||||
#### Revalidation Impact
|
||||
- Reverification Needed: no
|
||||
- Existing Implementation Invalidated: no
|
||||
- Status Recommendation: promote-to-implemented
|
||||
- Follow-up Action: release 단계에서 smoke 확인
|
||||
|
||||
### CHG-20260524-01
|
||||
- Date: 2026-05-24
|
||||
- Author: Hermes Agent
|
||||
|
||||
#### Change Summary
|
||||
- `PortfolioItem.symbol` 응답 계약 추가에 따라 REQ-025 생성 응답 contract를 보강하고 상태를 Implemented → Approved로 되돌림.
|
||||
|
||||
#### Intent
|
||||
- trex-orbit 팀 이슈(`docs/issues/20260524_portfolio-hub-ticket-symbol-in-portfolios.md`) 후속. 생성 응답만 `asset_id`를 반환하고 `symbol`을 생략하면 클라이언트가 별도 asset catalog 조회/캐시를 유지해야 하므로, 생성 직후 응답에서도 joined asset의 `symbol`을 즉시 반환하도록 계약을 확장한다.
|
||||
|
||||
#### Acceptance Criteria Delta
|
||||
- Added:
|
||||
- AC-8: POST 응답의 `PortfolioItem.symbol` 이 `assets.symbol` join 결과와 일치해야 함
|
||||
|
||||
#### Impacted Area Delta
|
||||
- Docs: `docs/interface-contract.md` 의 POST `/v1/portfolios` 응답 예시에 `symbol` 추가 필요 (REQ-032 후속)
|
||||
- Modules: `app/schemas/v1.py`, `app/api/v1_portfolios.py` (`_portfolio_to_item`), `app/repositories/postgres.py:get()` join 응답 확인
|
||||
- Tests: `tests/test_v1_portfolios_crud.py` 에 POST 응답 `symbol` 검증 추가 필요
|
||||
|
||||
#### Delivery Trace Delta
|
||||
- Batches: BAT-009 evidence partially superseded; follow-up BAT-014 예정
|
||||
- Releases: REL-001 response-contract evidence 일부 재검토 필요
|
||||
|
||||
#### Revalidation Impact
|
||||
- Reverification Needed: yes
|
||||
- Existing Implementation Invalidated: yes (response schema evidence partial)
|
||||
- Status Recommendation: revert-to-approved
|
||||
- Follow-up Action: BAT-014에서 POST/PATCH/DELETE/GET portfolio 응답 `symbol` 회귀 검증 추가
|
||||
|
||||
#### Validation Plan
|
||||
- `tests/test_v1_portfolios_crud.py` 에서 POST 201 응답 body의 `symbol` 존재 및 `asset_id`가 가리키는 asset row의 `symbol` 일치 여부를 검증한다.
|
||||
|
||||
### CHG-20260521-01
|
||||
- Date: 2026-05-21
|
||||
- Author: Justin Ko
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
- 수정 가능 필드는 기존 `UpdatePortfolioRequest` 범위: `broker`, `status`, `name`, `symbol`, `strategy_name`, `strategy_params`, `asset_price`, `managed_by_daemon_id` 등.
|
||||
- **disabled portfolio 보호** (REQ-027 soft delete 정책 정합): `portfolios.status == 'disabled'`인 portfolio에 대해 status 전이(`'enabled'`로 복구) 외 다른 필드 변경 시 HTTP 409 또는 422로 거부.
|
||||
- 응답: HTTP 200 + 갱신된 `PortfolioItem`.
|
||||
- 응답의 `symbol` 값은 수정 대상 portfolio가 참조하는 `assets.symbol`을 기준으로 server-side join 결과에서 채운다.
|
||||
|
||||
## Acceptance Criteria
|
||||
1. Given admin token + 본인 또는 타 user portfolio, When `PATCH /v1/portfolios/{id}` body `{"strategy_name": "..."}`, Then HTTP 200 + 갱신된 portfolio 반환.
|
||||
@@ -31,6 +32,7 @@
|
||||
7. Given 비존재 `portfolio_id`, When `PATCH /v1/portfolios/{id}`, Then HTTP 404.
|
||||
8. Given `status='disabled'` portfolio + body `{"strategy_name": "..."}`(status 외 필드), When `PATCH`, Then HTTP 409 또는 422 (disabled write 차단).
|
||||
9. Given `status='disabled'` portfolio + body `{"status": "enabled"}` (admin), When `PATCH`, Then HTTP 200 + status 복구.
|
||||
10. Given portfolio가 active asset(`symbol="005930"`)을 참조, When `PATCH /v1/portfolios/{id}` 성공, Then HTTP 200 응답의 `PortfolioItem.symbol == "005930"` 이고 값은 joined asset row와 일치한다.
|
||||
|
||||
## Impacted Area
|
||||
- Docs:
|
||||
@@ -51,6 +53,64 @@
|
||||
|
||||
## Change Log
|
||||
|
||||
### CHG-20260524-02
|
||||
- Date: 2026-05-24
|
||||
- Author: Hermes Agent
|
||||
|
||||
#### Change Summary
|
||||
- Status: Approved → Implemented
|
||||
|
||||
#### Intent
|
||||
- BAT-014 verification 완료. PATCH 성공 응답의 `PortfolioItem.symbol` 계약이 코드/테스트/문서에 반영되어 REQ-026 acceptance criteria 전부가 다시 충족되었다.
|
||||
|
||||
#### Acceptance Criteria Delta
|
||||
- No change
|
||||
|
||||
#### Impacted Area Delta
|
||||
- No change
|
||||
|
||||
#### Delivery Trace Delta
|
||||
- Batches: BAT-014 (release-candidate); BAT-009 response-contract evidence superseded by BAT-014
|
||||
- Releases: pending
|
||||
|
||||
#### Revalidation Impact
|
||||
- Reverification Needed: no
|
||||
- Existing Implementation Invalidated: no
|
||||
- Status Recommendation: promote-to-implemented
|
||||
- Follow-up Action: release 단계에서 smoke 확인
|
||||
|
||||
### CHG-20260524-01
|
||||
- Date: 2026-05-24
|
||||
- Author: Hermes Agent
|
||||
|
||||
#### Change Summary
|
||||
- `PortfolioItem.symbol` 응답 계약 추가에 따라 REQ-026 수정 응답 contract를 보강하고 상태를 Implemented → Approved로 되돌림.
|
||||
|
||||
#### Intent
|
||||
- trex-orbit 팀이 portfolio mutation 후에도 추가 catalog lookup 없이 즉시 symbol을 사용해야 하는 요구를 제기했다. PATCH 응답이 기존 portfolio state만 되돌리고 joined asset 식별자(`symbol`)를 생략하면 CRUD 응답 contract가 비대칭이므로, 수정 응답에도 동일 필드를 포함하도록 정의를 확장한다.
|
||||
|
||||
#### Acceptance Criteria Delta
|
||||
- Added:
|
||||
- AC-10: PATCH 성공 응답의 `PortfolioItem.symbol` 이 joined `assets.symbol` 과 일치해야 함
|
||||
|
||||
#### Impacted Area Delta
|
||||
- Docs: `docs/interface-contract.md` 의 PATCH `/v1/portfolios/{id}` 응답 예시에 `symbol` 추가 필요 (REQ-032 후속)
|
||||
- Modules: `app/schemas/v1.py`, `app/api/v1_portfolios.py` (`_portfolio_to_item`)
|
||||
- Tests: `tests/test_v1_portfolios_crud.py` 에 PATCH 응답 `symbol` 검증 추가 필요
|
||||
|
||||
#### Delivery Trace Delta
|
||||
- Batches: BAT-009 evidence partially superseded; follow-up BAT-014 예정
|
||||
- Releases: REL-001 response-contract evidence 일부 재검토 필요
|
||||
|
||||
#### Revalidation Impact
|
||||
- Reverification Needed: yes
|
||||
- Existing Implementation Invalidated: yes (response schema evidence partial)
|
||||
- Status Recommendation: revert-to-approved
|
||||
- Follow-up Action: BAT-014에서 PATCH 응답 contract 회귀 검증 추가
|
||||
|
||||
#### Validation Plan
|
||||
- `tests/test_v1_portfolios_crud.py` 에서 PATCH 200 응답 body의 `symbol` 존재 및 joined asset symbol 일치 여부를 검증한다.
|
||||
|
||||
### CHG-20260521-01
|
||||
- Date: 2026-05-21
|
||||
- Author: Justin Ko
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
- 비존재 `portfolio_id`는 HTTP 404. ownership 불일치는 HTTP 403.
|
||||
- 이미 `disabled` 상태인 portfolio에 재호출 시 HTTP 200 + 멱등 응답(또는 HTTP 409 — 본 REQ 구현 시 확정).
|
||||
- 응답: HTTP 200 또는 204 + (HTTP 200 시) disabled 상태 portfolio 또는 확정 응답.
|
||||
- HTTP 200 응답을 반환하는 구현에서는 `PortfolioItem.symbol` 도 함께 포함해야 하며, 값은 soft delete 이후에도 linked asset row join 결과와 동일해야 한다.
|
||||
|
||||
## Acceptance Criteria
|
||||
1. Given session token + 본인 active portfolio, When `DELETE /v1/portfolios/{id}`, Then HTTP 200/204 + `portfolios.status='disabled'` + `managed_by_daemon_id IS NULL` 사후 상태.
|
||||
@@ -41,6 +42,7 @@
|
||||
8. Given 비존재 `portfolio_id`, When `DELETE /v1/portfolios/{id}`, Then HTTP 404.
|
||||
9. Given disabled portfolio + admin `PATCH status='enabled'`, When `PATCH`, Then HTTP 200 + 복구. (REQ-026 AC-9와 연계)
|
||||
10. Given AC-1 실행 후 disabled portfolio에 ledger trade/tag/comment write 시도, When 시도, Then 모두 차단(HTTP 409 또는 422). (REQ-029/030/031과 연계 검증)
|
||||
11. Given active asset(`symbol="005930"`)을 참조하던 portfolio, When `DELETE /v1/portfolios/{id}` 가 HTTP 200 응답을 반환, Then 응답의 `PortfolioItem.symbol == "005930"` 이고 값은 joined asset row와 일치한다.
|
||||
|
||||
## Impacted Area
|
||||
- Docs:
|
||||
@@ -62,6 +64,64 @@
|
||||
|
||||
## Change Log
|
||||
|
||||
### CHG-20260524-02
|
||||
- Date: 2026-05-24
|
||||
- Author: Hermes Agent
|
||||
|
||||
#### Change Summary
|
||||
- Status: Approved → Implemented
|
||||
|
||||
#### Intent
|
||||
- BAT-014 verification 완료. DELETE(soft delete) HTTP 200 응답의 `PortfolioItem.symbol` 계약이 코드/테스트/문서에 반영되어 REQ-027 acceptance criteria 전부가 다시 충족되었다.
|
||||
|
||||
#### Acceptance Criteria Delta
|
||||
- No change
|
||||
|
||||
#### Impacted Area Delta
|
||||
- No change
|
||||
|
||||
#### Delivery Trace Delta
|
||||
- Batches: BAT-014 (release-candidate); BAT-009 response-contract evidence superseded by BAT-014
|
||||
- Releases: pending
|
||||
|
||||
#### Revalidation Impact
|
||||
- Reverification Needed: no
|
||||
- Existing Implementation Invalidated: no
|
||||
- Status Recommendation: promote-to-implemented
|
||||
- Follow-up Action: release 단계에서 smoke 확인
|
||||
|
||||
### CHG-20260524-01
|
||||
- Date: 2026-05-24
|
||||
- Author: Hermes Agent
|
||||
|
||||
#### Change Summary
|
||||
- `PortfolioItem.symbol` 응답 계약 추가에 따라 REQ-027 soft delete 응답 contract를 보강하고 상태를 Implemented → Approved로 되돌림.
|
||||
|
||||
#### Intent
|
||||
- trex-orbit 팀 이슈 후속으로, delete/disable 응답에서도 client가 별도 asset lookup 없이 포트폴리오 식별 symbol을 유지할 수 있어야 한다. soft delete는 asset reference를 제거하지 않으므로 HTTP 200 응답이 있는 경우 `symbol`을 함께 반환하는 계약이 자연스럽다.
|
||||
|
||||
#### Acceptance Criteria Delta
|
||||
- Added:
|
||||
- AC-11: DELETE(HTTP 200) 응답의 `PortfolioItem.symbol` 이 joined `assets.symbol` 과 일치해야 함
|
||||
|
||||
#### Impacted Area Delta
|
||||
- Docs: `docs/interface-contract.md` 의 DELETE `/v1/portfolios/{id}` 응답 예시에 `symbol` 추가 필요 (REQ-032 후속)
|
||||
- Modules: `app/schemas/v1.py`, `app/api/v1_portfolios.py` (`_portfolio_to_item`)
|
||||
- Tests: `tests/test_v1_portfolios_crud.py` 에 DELETE 200 응답 `symbol` 검증 추가 필요
|
||||
|
||||
#### Delivery Trace Delta
|
||||
- Batches: BAT-009 evidence partially superseded; follow-up BAT-014 예정
|
||||
- Releases: REL-001 response-contract evidence 일부 재검토 필요
|
||||
|
||||
#### Revalidation Impact
|
||||
- Reverification Needed: yes
|
||||
- Existing Implementation Invalidated: yes (response schema evidence partial)
|
||||
- Status Recommendation: revert-to-approved
|
||||
- Follow-up Action: BAT-014에서 DELETE 응답 contract 회귀 검증 추가
|
||||
|
||||
#### Validation Plan
|
||||
- `tests/test_v1_portfolios_crud.py` 에서 DELETE 200 응답 body의 `symbol` 존재 및 joined asset symbol 일치 여부를 검증한다.
|
||||
|
||||
### CHG-20260521-01
|
||||
- Date: 2026-05-21
|
||||
- Author: Justin Ko
|
||||
|
||||
@@ -19,7 +19,8 @@
|
||||
- `permission ∈ {read, trade-write}` → `owner_user_id = auth.user_id` 필터, 본인 portfolio만 반환.
|
||||
- **`?market=<code>` 필터**: 모든 토큰 타입에서 지원. `<code> = ANY(assets.markets)`인 portfolio만 반환(catalog와 join).
|
||||
- **`?include_disabled=true` 옵션** (dcy-003 R-2 완화): 기본 응답은 `status='disabled'`인 portfolio 제외. opt-in 시에만 포함.
|
||||
- 응답 항목 schema: 신규 `PortfolioItem` (`portfolio_id`, `asset_id`, `owner_user_id`, `broker`, `status`, `cash_balance`, ..., `tag_ids`, `managed_by_daemon_id`, ...). `asset_id`는 catalog의 `assets.asset_id`(UUID) 참조.
|
||||
- 응답 항목 schema: 신규 `PortfolioItem` (`portfolio_id`, `asset_id`, `symbol`, `owner_user_id`, `broker`, `status`, `cash_balance`, ..., `tag_ids`, `managed_by_daemon_id`, ...). `asset_id`는 catalog의 `assets.asset_id`(UUID) 참조.
|
||||
- `GET /v1/portfolios` 의 각 item은 반드시 `portfolios JOIN assets` 결과를 기반으로 직렬화되어야 한다. 특히 `symbol` 은 linked asset row의 `assets.symbol` 을 그대로 노출해야 하며, 클라이언트 캐시나 후속 catalog lookup으로 복원하는 모델은 정식 응답 계약이 아니다.
|
||||
- 응답: HTTP 200 + `PortfolioListResponse` (`portfolios: list[PortfolioItem]`, `total: int`).
|
||||
|
||||
## Acceptance Criteria
|
||||
@@ -34,6 +35,7 @@
|
||||
9. Given client token, When `GET /v1/portfolios`, Then HTTP 403 fail-closed.
|
||||
10. Given Bearer token 없음, When `GET /v1/portfolios`, Then HTTP 401.
|
||||
11. Given 응답 portfolio 항목, When `asset_id` 필드 확인, Then `assets.asset_id`(catalog UUID)를 참조한다.
|
||||
12. Given `GET /v1/portfolios` 응답 item, When `symbol` 필드를 확인, Then 값은 같은 row의 `asset_id`가 가리키는 joined `assets.symbol` 과 일치한다.
|
||||
|
||||
## Impacted Area
|
||||
- Docs:
|
||||
@@ -57,6 +59,64 @@
|
||||
|
||||
## Change Log
|
||||
|
||||
### CHG-20260524-02
|
||||
- Date: 2026-05-24
|
||||
- Author: Hermes Agent
|
||||
|
||||
#### Change Summary
|
||||
- Status: Approved → Implemented
|
||||
|
||||
#### Intent
|
||||
- BAT-014 verification 완료. GET `/v1/portfolios` 응답이 `portfolios JOIN assets` 결과에서 `symbol` 을 직접 반환함이 코드/테스트/문서로 재검증되었다.
|
||||
|
||||
#### Acceptance Criteria Delta
|
||||
- No change
|
||||
|
||||
#### Impacted Area Delta
|
||||
- No change
|
||||
|
||||
#### Delivery Trace Delta
|
||||
- Batches: BAT-014 (release-candidate); BAT-009 response-contract evidence superseded by BAT-014
|
||||
- Releases: pending
|
||||
|
||||
#### Revalidation Impact
|
||||
- Reverification Needed: no
|
||||
- Existing Implementation Invalidated: no
|
||||
- Status Recommendation: promote-to-implemented
|
||||
- Follow-up Action: release 단계에서 smoke 확인
|
||||
|
||||
### CHG-20260524-01
|
||||
- Date: 2026-05-24
|
||||
- Author: Hermes Agent
|
||||
|
||||
#### Change Summary
|
||||
- `GET /v1/portfolios` 응답을 joined asset result 기반으로 명확히 고정하고 `PortfolioItem.symbol` 계약을 추가하기 위해 REQ-028을 augment. 상태를 Implemented → Approved로 되돌림.
|
||||
|
||||
#### Intent
|
||||
- trex-orbit 자동매매 데몬은 `GET /v1/portfolios` 응답만으로 외부 시세 API 호출 대상 symbol을 바로 얻어야 한다. 기존 계약은 `asset_id`만 제공해 클라이언트 측 catalog cache를 강제했으므로, server-side asset join 결과(`assets.symbol`)를 직접 응답에 포함하도록 명시한다.
|
||||
|
||||
#### Acceptance Criteria Delta
|
||||
- Added:
|
||||
- AC-12: GET 응답 item의 `symbol` 은 joined `assets.symbol` 과 일치해야 함
|
||||
|
||||
#### Impacted Area Delta
|
||||
- Docs: `docs/interface-contract.md` GET `/v1/portfolios` 예시/필드 정의에 `symbol` 및 join 기반 응답 설명 추가 필요 (REQ-032 후속)
|
||||
- Modules: `app/schemas/v1.py`, `app/api/v1_portfolios.py` (`_portfolio_to_item`), `app/repositories/postgres.py` (`_SELECT_PORTFOLIO` join 결과를 응답까지 전달)
|
||||
- Tests: `tests/test_v1_portfolios_list.py` 에 list 응답 `symbol` 검증 추가 필요
|
||||
|
||||
#### Delivery Trace Delta
|
||||
- Batches: BAT-009 evidence partially superseded; follow-up BAT-014 예정
|
||||
- Releases: REL-001 response-contract evidence 일부 재검토 필요
|
||||
|
||||
#### Revalidation Impact
|
||||
- Reverification Needed: yes
|
||||
- Existing Implementation Invalidated: yes (response schema evidence partial)
|
||||
- Status Recommendation: revert-to-approved
|
||||
- Follow-up Action: BAT-014에서 GET `/v1/portfolios` 응답이 asset join 결과를 직접 반환하는지 회귀 검증
|
||||
|
||||
#### Validation Plan
|
||||
- `tests/test_v1_portfolios_list.py` 에서 각 item의 `symbol` 필드 존재와 `asset_id`가 가리키는 joined asset row의 `symbol` 일치 여부를 검증한다.
|
||||
|
||||
### CHG-20260521-01
|
||||
- Date: 2026-05-21
|
||||
- Author: Justin Ko
|
||||
|
||||
Reference in New Issue
Block a user