fix(holdings): /holdings/cost-basis WAC row에 fee_amount 편입 (QC보정)
get_holdings_cost_basis 핸들러의 row dict에 fee_amount 누락으로 /holdings/cost-basis의 cost_basis_per_unit이 매수 수수료 미편입값을 반환하던 버그 수정. /pnl/realized 핸들러와 동일하게 e.fee_amount 포함. 테스트: buy fee>0 케이스(1000.5 단언) + fee=0 회귀 케이스 추가. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VHtM5Ws1HKCKQ4JGi6GRb5
This commit is contained in:
@@ -78,6 +78,7 @@ def _make_entry(
|
||||
quantity: float,
|
||||
price: float,
|
||||
executed_at: datetime,
|
||||
fee_amount: float = 0.0,
|
||||
) -> LedgerEntry:
|
||||
return LedgerEntry(
|
||||
ledger_entry_id=ledger_entry_id,
|
||||
@@ -87,7 +88,7 @@ def _make_entry(
|
||||
side=side,
|
||||
quantity=quantity,
|
||||
price=price,
|
||||
fee_amount=0.0,
|
||||
fee_amount=fee_amount,
|
||||
tax_amount=0.0,
|
||||
executed_at=executed_at,
|
||||
recorded_at=executed_at,
|
||||
@@ -535,3 +536,68 @@ def test_portfolio_id_in_response_matches_request() -> None:
|
||||
resp = client.get(_PATH, headers={"Authorization": "Bearer tok"})
|
||||
assert resp.status_code == 200
|
||||
assert resp.json()["portfolio_id"] == _PORTFOLIO_ID
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# QC보정: buy fee>0 케이스 — cost_basis_per_unit이 fee 편입값인지 확인
|
||||
# buy 10@1000 fee=5 → cost_basis_per_unit = (10*1000 + 5) / 10 = 1000.5
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def test_cost_basis_per_unit_includes_buy_fee() -> None:
|
||||
"""buy fee>0 케이스: cost_basis_per_unit이 매수 fee 편입값을 반환한다.
|
||||
|
||||
buy 10주 @ 1,000원, fee=5원 → WAC = (10*1000 + 5) / 10 = 1000.5
|
||||
REQ-043 Notes: 매수 fee를 cost basis에 포함.
|
||||
"""
|
||||
settings = _make_settings()
|
||||
trades = [
|
||||
_make_entry(
|
||||
ledger_entry_id=1,
|
||||
side="buy",
|
||||
quantity=10,
|
||||
price=1_000,
|
||||
fee_amount=5.0,
|
||||
executed_at=datetime(2026, 6, 1, 9, 0, tzinfo=timezone.utc),
|
||||
),
|
||||
]
|
||||
repo = _make_service_repo(
|
||||
portfolio=_make_portfolio(asset_quantity=10.0),
|
||||
trades=trades,
|
||||
)
|
||||
with _with_repo(repo):
|
||||
client = _make_client(settings)
|
||||
resp = client.get(_PATH, headers={"Authorization": "Bearer tok"})
|
||||
assert resp.status_code == 200
|
||||
body = resp.json()
|
||||
# (10 * 1000 + 5) / 10 = 1000.5
|
||||
assert body["cost_basis_per_unit"] == pytest.approx(1000.5)
|
||||
assert body["total_cost_basis"] == pytest.approx(10_005.0)
|
||||
|
||||
|
||||
def test_cost_basis_per_unit_zero_fee_unchanged() -> None:
|
||||
"""buy fee=0 케이스: fee 편입 추가 후에도 fee=0이면 기존 값 그대로.
|
||||
|
||||
buy 10주 @ 1,000원, fee=0 → WAC = 1000.0 (회귀 확인)
|
||||
"""
|
||||
settings = _make_settings()
|
||||
trades = [
|
||||
_make_entry(
|
||||
ledger_entry_id=1,
|
||||
side="buy",
|
||||
quantity=10,
|
||||
price=1_000,
|
||||
fee_amount=0.0,
|
||||
executed_at=datetime(2026, 6, 1, 9, 0, tzinfo=timezone.utc),
|
||||
),
|
||||
]
|
||||
repo = _make_service_repo(
|
||||
portfolio=_make_portfolio(asset_quantity=10.0),
|
||||
trades=trades,
|
||||
)
|
||||
with _with_repo(repo):
|
||||
client = _make_client(settings)
|
||||
resp = client.get(_PATH, headers={"Authorization": "Bearer tok"})
|
||||
assert resp.status_code == 200
|
||||
body = resp.json()
|
||||
assert body["cost_basis_per_unit"] == pytest.approx(1000.0)
|
||||
assert body["total_cost_basis"] == pytest.approx(10_000.0)
|
||||
|
||||
Reference in New Issue
Block a user