# BAT-018 Implementation ## 구현 결정 사항 ### domain 함수 선택: 신규 함수 분리 (OQ-2 위임 → 분리 채택) - `calculate_current_wac(rows) -> CurrentWacResult` 신규 함수를 `app/domain/pnl.py`에 추가. - `calculate_realized_pnl`의 WAC 누적 로직과 동일 규칙을 따르되, 매도 PnL 집계 없이 최종 running_wac/running_qty만 반환. - 이유: 단일책임 원칙 + 기존 함수 파라미터 과부하 방지. 두 함수는 입력/출력 목적이 다름(매도 PnL vs 현재 평단). ### 소유권 분기 방식 - 핸들러 내에서 `auth.token_type == "service"` 분기로 처리. - service: `managed_by_daemon_id is None` → 403, `auth.daemon_id != managed_by_daemon_id` → 403. - user/admin: `auth.permission != Permission.ADMIN and portfolio.owner_user_id != auth.user_id` → 403. - `_get_portfolio_or_404` 헬퍼는 user token 소유권 검사를 포함하므로 서비스 토큰에는 미사용(직접 `repo.get()` 호출). ### current_quantity 출처 - `portfolio.asset_quantity` 직접 읽기 (REQ-043 Notes 준수). - WAC 산출은 ledger replay 독립 계산(calculate_current_wac). ## 변경 파일 목록 | 파일 | 변경 유형 | 내용 | | --- | --- | --- | | `app/domain/pnl.py` | 수정 | `CurrentWacResult` dataclass + `calculate_current_wac` 함수 추가 | | `app/schemas/v1.py` | 수정 | `HoldingsCostBasisResponse` 스키마 추가 | | `app/api/v1_portfolios.py` | 수정 | `calculate_current_wac` import, `HoldingsCostBasisResponse` import, `get_holdings_cost_basis` 핸들러 추가 | | `tests/test_v1_portfolios_holdings.py` | 신규 | AC-1~11 커버 테스트 20개 | | `docs/batches/index.md` | 수정 | BAT-018 register 행 추가 | | `docs/batches/bat-018_*/index.md` | 신규 | batch index 문서 | | `docs/batches/bat-018_*/planning.md` | 신규 | batch planning 문서 | ## 커밋 SHA - `748aa5d` — feat(holdings): GET /v1/portfolios/{id}/holdings/cost-basis — REQ-043, BAT-018