feat(REQ-014): add portfolio-create-user-required requirement and implementation
- Add docs/srs/Interface/req-014_portfolio-create-user-required.md with acceptance criteria - Create docs/batches/bat-004_20260502_portfolio-create-user-required/ delivery batch - Enhance app/cli/commands/portfolio.py: validate user_id parameter before portfolio creation - Add comprehensive CLI tests in tests/test_cli.py for portfolio create validation flows - Update docs/batches/index.md and docs/srs/index.md with new requirement/batch references - Update README.md documentation
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
# BAT-004 Implementation
|
||||
|
||||
- Status: completed
|
||||
- Batch: BAT-004
|
||||
- Profile: batch-lite
|
||||
|
||||
## Plan Summary
|
||||
|
||||
- CLI `pfhub portfolio create`에 `--user <username>` 필수 옵션 추가
|
||||
- BAT-003에서 도입한 `_with_service_and_repo` 헬퍼 재사용
|
||||
- `repository.get_user_by_username(user)` 호출 → None이면 ValueError → exit code 1
|
||||
- `service.create_portfolio(payload, owner_user_id=owner.id)` 실제 user UUID 전달
|
||||
- README 예제 라인 갱신
|
||||
- 기존 테스트 3개 수정 + 신규 3개 추가
|
||||
|
||||
## Changed Files
|
||||
|
||||
| File | Change |
|
||||
|------|--------|
|
||||
| `app/cli/commands/portfolio.py` | `create_portfolio` 함수에 `--user` 옵션 추가, `_with_service` → `_with_service_and_repo` 교체, username→UUID 조회 후 `owner_user_id` 전달 |
|
||||
| `tests/test_cli.py` | `test_cli_create_buy_and_delete_flow`, `test_cli_write_command_prompts_before_create`, `test_cli_write_command_can_abort` 수정; AC 1~3 커버 신규 3개 케이스 추가 |
|
||||
| `README.md` | `pfhub portfolio create` → `pfhub portfolio create ... --user <username>` 갱신 |
|
||||
|
||||
## Execution Log
|
||||
|
||||
### 구현 결정 사항
|
||||
|
||||
- `--user` 옵션: `typer.Option(None, "--user", ...)` + 수동 None 체크로 exit code 1 보장 (BAT-003과 동일 패턴)
|
||||
- `_confirm` 호출 전에 None 체크를 배치하여 owner 미지정 시 확인 프롬프트 없이 즉시 종료
|
||||
- callback 내 username → user_id 조회: `repository.get_user_by_username(user)` → None이면 `ValueError`
|
||||
- `service.create_portfolio(payload, owner_user_id=owner.id)`: `portfolio_service.py` 시그니처 변경 불필요 (기존 키워드 인자 그대로 활용)
|
||||
|
||||
### 기존 테스트 수정
|
||||
|
||||
- `test_cli_create_buy_and_delete_flow`: alice user 생성 + `--user alice` 추가, `owner_user_id` 검증 BUY 전에 배치 (delete 후 `_portfolio`가 None이 되므로)
|
||||
- `test_cli_write_command_prompts_before_create`: alice user 생성 + `--user alice` 추가
|
||||
- `test_cli_write_command_can_abort`: alice user 생성 + `--user alice` 추가
|
||||
|
||||
## Validation
|
||||
|
||||
```
|
||||
pytest tests/test_cli.py -k "test_cli_portfolio_create or test_cli_create or test_cli_write_command" -v
|
||||
```
|
||||
|
||||
```
|
||||
6 passed
|
||||
```
|
||||
|
||||
```
|
||||
pytest tests/test_cli.py -v
|
||||
```
|
||||
|
||||
```
|
||||
44 passed in 1.37s (전체 회귀, 기존 테스트 전원 통과)
|
||||
```
|
||||
|
||||
## Remaining Risks
|
||||
|
||||
- 없음
|
||||
@@ -0,0 +1,42 @@
|
||||
# BAT-004 Index
|
||||
|
||||
- Status: release-candidate
|
||||
- Batch: BAT-004
|
||||
- Profile: batch-lite
|
||||
- Created: 2026-05-02
|
||||
|
||||
## Included REQ
|
||||
|
||||
| REQ | 제목 | Type | Priority |
|
||||
|-----|------|------|----------|
|
||||
| REQ-014 | CLI `portfolio create --user` 필수화 및 소유자 설정 | Interface | Medium |
|
||||
|
||||
## Source Discovery
|
||||
|
||||
- minor-change fast path (Discovery 없음)
|
||||
|
||||
## Scope Summary
|
||||
|
||||
- CLI `pfhub portfolio create` 명령에 `--user <username>` 필수 옵션 추가
|
||||
- `_with_service_and_repo` 헬퍼(REQ-013 도입) 재사용, `repository.get_user_by_username(user)` 호출
|
||||
- `PortfolioService.create_portfolio(owner_user_id=owner.id, ...)` 실제 UUID 전달
|
||||
- `--user` 미입력 시 exit code 1, 미존재 username 시 exit code 1
|
||||
- README 예제 갱신
|
||||
- DB 스키마 변경 없음, HTTP API 변경 없음
|
||||
|
||||
## Impacted Area
|
||||
|
||||
- Docs:
|
||||
- `README.md` — `pfhub portfolio create` 예제 라인 `--user <username>` 추가
|
||||
- Modules:
|
||||
- `app/cli/commands/portfolio.py` — `create_portfolio` 명령 수정
|
||||
- Tests:
|
||||
- `tests/test_cli.py` — 기존 `test_cli_create_buy_and_delete_flow` 수정 + AC 1~4 커버 케이스 추가
|
||||
|
||||
## Stage Documents
|
||||
|
||||
| Stage | File | Status |
|
||||
|-------|------|--------|
|
||||
| Planning | [planning.md](./planning.md) | confirmed |
|
||||
| Implementation | [implementation.md](./implementation.md) | completed |
|
||||
| Verification | [verification.md](./verification.md) | verified |
|
||||
@@ -0,0 +1,50 @@
|
||||
# BAT-004 Planning
|
||||
|
||||
- Status: confirmed
|
||||
- Batch: BAT-004
|
||||
- Profile: batch-lite
|
||||
|
||||
## Included REQ
|
||||
|
||||
- REQ-014: CLI `portfolio create --user` 필수화 및 소유자 설정
|
||||
|
||||
## Out of Scope
|
||||
|
||||
- HTTP API `POST /portfolios` owner 설정 변경
|
||||
- `owner_user_id` 기본값(`"system"`) 서비스 레이어 변경
|
||||
|
||||
## 구현 순서
|
||||
|
||||
### 1단계: CLI 명령 수정
|
||||
|
||||
- `app/cli/commands/portfolio.py` — `create_portfolio` 명령 수정
|
||||
- `user: str | None = typer.Option(None, "--user", help="Owner username (required).")` 추가
|
||||
- `_with_service_and_repo` 콜백으로 교체
|
||||
- callback 내부:
|
||||
- `user is None` → `console.print(...)` + `raise typer.Exit(code=1)`
|
||||
- `repository.get_user_by_username(user)` → `None`이면 `raise ValueError(...)`
|
||||
- `service.create_portfolio(payload, owner_user_id=owner.id)` 호출
|
||||
|
||||
### 2단계: README 수정
|
||||
|
||||
- `README.md` — `pfhub portfolio create` 예제 라인에 `--user alice` 추가
|
||||
|
||||
### 3단계: 테스트
|
||||
|
||||
- `tests/test_cli.py`
|
||||
- `test_cli_create_buy_and_delete_flow`: `--user alice` 추가, repo에 alice 생성
|
||||
- `test_cli_write_command_prompts_before_create`: 동일 수정
|
||||
- `test_cli_write_command_can_abort`: 동일 수정
|
||||
- `test_cli_portfolio_create_without_user_exits_error` (신규)
|
||||
- `test_cli_portfolio_create_with_valid_user_sets_owner` (신규)
|
||||
- `test_cli_portfolio_create_with_unknown_user_exits_error` (신규)
|
||||
|
||||
## Dependencies
|
||||
|
||||
- Internal: `_with_service_and_repo` (BAT-003 도입, 이미 존재)
|
||||
- External: 없음
|
||||
|
||||
## Design Gate
|
||||
|
||||
- Design Required Before Implementation: no
|
||||
- Reason: 기존 `_with_service_and_repo` 패턴 재사용. 구조/스키마 변경 없음.
|
||||
@@ -0,0 +1,65 @@
|
||||
# BAT-004 Verification
|
||||
|
||||
- Status: verified
|
||||
- Batch: BAT-004
|
||||
- Profile: batch-lite
|
||||
|
||||
## Architecture Impact Check
|
||||
|
||||
- Design Gate (from planning.md): no — DB 스키마 변경 없음, HTTP API 변경 없음
|
||||
- Actual Architecture Impact: none confirmed — `app/cli/commands/portfolio.py` 내 기존 `_with_service_and_repo` 헬퍼 재사용, Protocol stub/구현체 변경 없음
|
||||
- Baseline Document Sync Required: no
|
||||
|
||||
## Acceptance Mapping
|
||||
|
||||
### AC 1: `--user` 없이 실행 → exit code 1 + 오류 메시지
|
||||
|
||||
| 항목 | 내용 |
|
||||
|------|------|
|
||||
| Evidence | `test_cli_portfolio_create_without_user_exits_error` |
|
||||
| Verification | `runner.invoke(app, ["portfolio", "create", "005930:tv", "--symbol", "005930", "--force"])` → `exit_code == 1`, `"--user" in result.stdout` |
|
||||
| Result | ✅ PASSED |
|
||||
|
||||
### AC 2: `--user alice` → 생성된 포트폴리오의 `owner_user_id`가 alice UUID로 설정됨
|
||||
|
||||
| 항목 | 내용 |
|
||||
|------|------|
|
||||
| Evidence | `test_cli_portfolio_create_with_valid_user_sets_owner` |
|
||||
| Verification | alice user 생성 → `--user alice --force` 실행 → `repo._portfolio.owner_user_id == user.id` 확인 |
|
||||
| Result | ✅ PASSED |
|
||||
|
||||
### AC 3: 존재하지 않는 username → 오류 메시지 + exit code 1
|
||||
|
||||
| 항목 | 내용 |
|
||||
|------|------|
|
||||
| Evidence | `test_cli_portfolio_create_with_unknown_user_exits_error` |
|
||||
| Verification | `--user nobody` → `exit_code == 1`, `"nobody" in result.stdout` |
|
||||
| Result | ✅ PASSED |
|
||||
|
||||
### AC 4: in-memory 모드에서도 동일 동작
|
||||
|
||||
| 항목 | 내용 |
|
||||
|------|------|
|
||||
| Evidence | `test_cli_portfolio_create_with_valid_user_sets_owner` (FakeRepo 사용) |
|
||||
| Verification | FakeRepo(in-memory) 환경에서 alice UUID가 `owner_user_id`로 설정됨 확인 |
|
||||
| Result | ✅ PASSED |
|
||||
|
||||
### AC 5: 오류 형식이 기존 CLI와 일관성 유지
|
||||
|
||||
| 항목 | 내용 |
|
||||
|------|------|
|
||||
| Evidence | 코드 검토 — BAT-003 `list_portfolios` 구현과 동일한 패턴 사용 |
|
||||
| Verification | `--user` 미입력 → `ctx.obj.console.print(...)` + `raise typer.Exit(code=1)`, 미등록 user → `ValueError` → `execute_command` 핸들러 동일 경로 |
|
||||
| Result | ✅ 충족 |
|
||||
|
||||
## Test Execution
|
||||
|
||||
```
|
||||
pytest tests/test_cli.py -v
|
||||
44 passed in 1.37s
|
||||
```
|
||||
|
||||
## Regression
|
||||
|
||||
- BAT-003 추가 테스트(portfolio list 관련 4개) 전원 PASSED — 회귀 없음
|
||||
- 기존 `test_cli_create_buy_and_delete_flow`, `test_cli_write_command_prompts_before_create`, `test_cli_write_command_can_abort` 수정 후 전원 PASSED
|
||||
@@ -10,4 +10,5 @@
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| BAT-001 | standard | release-candidate | REQ-004, REQ-005, REQ-006, REQ-007, REQ-008, REQ-009, REQ-010 | dcy-002 | [bat-001_20260502_trex-basic-v1-api-contract](./bat-001_20260502_trex-basic-v1-api-contract/) |
|
||||
| BAT-002 | batch-lite | release-candidate | REQ-012 | minor-change | [bat-002_20260502_service-token-rotate-cli](./bat-002_20260502_service-token-rotate-cli/) |
|
||||
| BAT-003 | batch-lite | release-candidate | REQ-013 | dcy-003 | [bat-003_20260502_portfolio-list-user-required](./bat-003_20260502_portfolio-list-user-required/) |
|
||||
| BAT-003 | batch-lite | release-candidate | REQ-013 | dcy-003 | [bat-003_20260502_portfolio-list-user-required](./bat-003_20260502_portfolio-list-user-required/) |
|
||||
| BAT-004 | batch-lite | release-candidate | REQ-014 | minor-change | [bat-004_20260502_portfolio-create-user-required](./bat-004_20260502_portfolio-create-user-required/) |
|
||||
@@ -0,0 +1,78 @@
|
||||
# REQ-014: CLI `portfolio create --user` 필수화 및 소유자 설정
|
||||
|
||||
- Status: Implemented
|
||||
- Type: Interface
|
||||
- Priority: Medium
|
||||
- Owner: repository-maintainers
|
||||
|
||||
## Intent
|
||||
- CLI `pfhub portfolio create`는 현재 `--user` 옵션이 없어 `owner_user_id="system"` 고정값으로 포트폴리오가 생성된다.
|
||||
- 생성 시 `--user <username>` 을 필수로 받아 실제 소유자의 `owner_user_id`(UUID)로 포트폴리오가 생성되도록 강제한다.
|
||||
- REQ-013(`portfolio list --user` 필수화)과 대칭을 이루는 변경으로, 소유자 기반 포트폴리오 관리 정책을 CLI 전반에 일관되게 적용한다.
|
||||
|
||||
## Requirement
|
||||
- CLI `pfhub portfolio create` 명령은 `--user <username>` 옵션을 필수로 받아야 한다.
|
||||
- `--user` 없이 실행하면 오류 메시지를 출력하고 exit code 1로 종료해야 한다.
|
||||
- `--user`로 전달된 username을 `repository.get_user_by_username(username)`으로 조회하여 `owner_user_id`(UUID)를 얻고, 이를 `PortfolioService.create_portfolio(owner_user_id=...)` 호출에 전달해야 한다.
|
||||
- 존재하지 않는 username이 전달되면 기존 CLI 오류 출력 형식과 일관된 오류 메시지를 출력하고 비정상 종료해야 한다.
|
||||
|
||||
## Acceptance Criteria
|
||||
1. Given `--user` 옵션 없이 `pfhub portfolio create <id> --symbol X --force`를 실행할 때, When 명령이 실행되면, Then 오류 메시지가 출력되고 exit code 1로 종료된다.
|
||||
2. Given 유효한 username `alice`로 `pfhub portfolio create <id> --symbol X --user alice --force`를 실행할 때, When 명령이 실행되면, Then 생성된 포트폴리오의 `owner_user_id`가 alice의 UUID로 설정된다.
|
||||
3. Given 존재하지 않는 username으로 실행할 때, When 명령이 실행되면, Then "사용자를 찾을 수 없습니다" 형태의 오류 메시지가 출력되고 exit code 1로 종료된다.
|
||||
4. Given in-memory 모드에서 `--user alice`로 실행할 때, When 명령이 실행되면, Then DB 모드와 동일하게 alice의 UUID가 `owner_user_id`로 설정된다.
|
||||
5. Given 오류 발생 시, When 오류 메시지가 출력될 때, Then 메시지 형식은 기존 CLI 오류 출력 형식(Rich Console)과 일관성을 유지한다.
|
||||
|
||||
## Impacted Area
|
||||
- Docs:
|
||||
- `README.md` — `pfhub portfolio create` 예제 라인에 `--user <username>` 옵션 추가
|
||||
- Modules:
|
||||
- `app/cli/commands/portfolio.py` — `create_portfolio` 명령 시그니처에 `--user` 필수 옵션 추가, `_with_service_and_repo` 콜백 사용, `owner_user_id` 전달
|
||||
- Tests:
|
||||
- `tests/test_cli.py` — 기존 `test_cli_create_buy_and_delete_flow` 수정 + AC 1~4 커버 케이스 추가
|
||||
|
||||
## Notes
|
||||
- `PortfolioService.create_portfolio` 시그니처(`owner_user_id: str = "system"`)는 변경하지 않는다. CLI 호출부에서만 실제 UUID를 전달한다.
|
||||
- REQ-013에서 도입한 `_with_service_and_repo` 헬퍼를 그대로 사용한다. 추가 헬퍼 불필요.
|
||||
- minor-change fast path 적용: Discovery 생략, Approved 직행. 범위는 CLI 옵션 1개 추가이며 기존 서비스/repository 인터페이스 변경 없음.
|
||||
- Source Discovery: 없음 (minor-change fast path)
|
||||
|
||||
## Change Log
|
||||
|
||||
### CHG-20260502-01
|
||||
- Date: 2026-05-02
|
||||
- Author: repository-maintainers
|
||||
|
||||
#### Change Summary
|
||||
- REQ-014 최초 생성 (Approved 직행). minor-change fast path 적용. REQ-012, REQ-013 선례 동일 경로.
|
||||
|
||||
#### Intent
|
||||
- `pfhub portfolio create`의 소유자 설정 누락 문제를 CLI 레벨에서 해결.
|
||||
|
||||
### CHG-20260502-02
|
||||
- Date: 2026-05-02
|
||||
- Author: repository-maintainers
|
||||
|
||||
#### Change Summary
|
||||
- BAT-004 verification(44 passed) 기반으로 Approved → Implemented 전환.
|
||||
|
||||
#### Intent
|
||||
- 구현 및 검증 증거 확보 완료 후 상태 동기화.
|
||||
|
||||
#### Acceptance Criteria Delta
|
||||
- Added: AC 1~5 신규 작성
|
||||
|
||||
#### Impacted Area Delta
|
||||
- Docs: README.md create 예제 갱신
|
||||
- Modules: app/cli/commands/portfolio.py create_portfolio 수정
|
||||
- Tests: tests/test_cli.py 케이스 추가/수정
|
||||
|
||||
#### Delivery Trace Delta
|
||||
- Batches: none (batch 미생성)
|
||||
- Releases: none
|
||||
|
||||
#### Revalidation Impact
|
||||
- Reverification Needed: no
|
||||
- Existing Implementation Invalidated: no
|
||||
- Status Recommendation: keep-current
|
||||
- Follow-up Action: draft-batch 진행
|
||||
+5
-8
@@ -74,7 +74,7 @@
|
||||
|
||||
## Next Requirement ID
|
||||
|
||||
- Current: `REQ-014`
|
||||
- Current: `REQ-015`
|
||||
- Rule: `Requirement Register`에 있는 가장 큰 REQ 번호보다 정확히 1 커야 한다.
|
||||
|
||||
## Requirement Register
|
||||
@@ -94,15 +94,12 @@
|
||||
| REQ-011 | trex-basic 계약 반영을 위한 baseline 문서 갱신 | Documentation | Approved | Medium | repository-maintainers | [REQ-011](./Documentation/req-011_baseline-docs-update-for-trex-basic-contract.md) |
|
||||
| REQ-012 | service-token rotate CLI 명령 구현 | Interface | Approved | Medium | repository-maintainers | [REQ-012](./Interface/req-012_service-token-rotate-cli.md) |
|
||||
| REQ-013 | CLI `portfolio list --user` 필수화 및 소유자 기반 조회 | Interface | Implemented | Medium | repository-maintainers | [REQ-013](./Interface/req-013_portfolio-list-user-required.md) |
|
||||
| REQ-014 | CLI `portfolio create --user` 필수화 및 소유자 설정 | Interface | Implemented | Medium | repository-maintainers | [REQ-014](./Interface/req-014_portfolio-create-user-required.md) |
|
||||
|
||||
## Recent Change Log Summary
|
||||
|
||||
- 2026-05-02: REQ-014 Implemented 전환 — BAT-004 verification evidence 확인 (44 passed)
|
||||
- 2026-05-02: REQ-014 Approved 직행 (minor-change) — CLI `portfolio create --user` 필수화 및 소유자 설정
|
||||
- 2026-05-02: REQ-013 Implemented 전환 — BAT-003 verification evidence 확인 (41 passed)
|
||||
- 2026-05-02: REQ-013 Approved 전환 — CLI `portfolio list --user` 필수화 및 소유자 기반 조회 (source Discovery: dcy-003)
|
||||
- 2026-05-02: REQ-013 Proposed 생성 — CLI `portfolio list --user` 필수화 및 소유자 기반 조회 (source Discovery: dcy-003)
|
||||
- 2026-05-02: REQ-012 Approved 직행 (minor-change) — service-token rotate CLI 명령 구현
|
||||
- 2026-05-02: REQ-011 Approved 전환 — trex-basic 계약 반영을 위한 baseline 문서 갱신 (source Discovery: dcy-002)
|
||||
- 2026-05-02: REQ-010 Approved 전환 — credential_payload Fernet 암호화 및 startup validation (source Discovery: dcy-002)
|
||||
- 2026-05-02: REQ-009 Approved 전환 — v1 API DB 스키마 migration 추가 (source Discovery: dcy-002)
|
||||
- 2026-05-02: REQ-008 Approved 전환 — POST /v1/assets/{asset_id}/ledger/trades 구현 (source Discovery: dcy-002)
|
||||
- 2026-05-02: REQ-007 Approved 전환 — GET /v1/user_info 엔드포인트 구현 (source Discovery: dcy-002)
|
||||
- 2026-05-02: REQ-012 Approved 직행 (minor-change) — service-token rotate CLI 명령 구현
|
||||
Reference in New Issue
Block a user