chore(release): prepare v0.3.1

This commit is contained in:
2026-09-13 15:32:27 +09:00
parent 5b443f718e
commit 1010d257ad
18 changed files with 176 additions and 42 deletions
+14 -5
View File
@@ -24,15 +24,19 @@ from app.core.auth import AuthContext, Permission, require_read, require_trade_w
from app.core.config import get_settings
from app.domain.errors import DaemonInactiveError, DaemonNotFoundError
from app.domain.models import CorporateAction, Portfolio, PortfolioComment
from app.domain.services import PORTFOLIO_NOT_FOUND_MESSAGE
from app.domain.pnl import calculate_current_wac, calculate_realized_pnl
from app.domain.services import PORTFOLIO_NOT_FOUND_MESSAGE
from app.repositories.factory import get_portfolio_repository_from_settings
from app.schemas.corporate_actions import (
CorporateActionRequest,
CorporateActionResponse,
)
from app.schemas.v1 import (
CorporateActionLedgerHistoryItem,
DividendLedgerHistoryItem,
DividendManualLedgerResponse,
HoldingsCostBasisResponse,
LedgerHistoryItem,
CorporateActionLedgerHistoryItem,
LedgerHistoryResponse,
LedgerTradeRequest,
LedgerTradeResponse,
@@ -57,7 +61,6 @@ from app.schemas.v1 import (
TradeHistoryItem,
TradeHistoryResponse,
)
from app.schemas.corporate_actions import CorporateActionRequest, CorporateActionResponse
from app.services.strategy_set_service import (
StrategyInactiveError,
StrategyNotFoundError,
@@ -1313,7 +1316,13 @@ def get_holdings_cost_basis(
@router.post("/{portfolio_id}/corporate-actions", response_model=CorporateActionResponse, status_code=status.HTTP_201_CREATED)
def create_corporate_action(portfolio_id: str, payload: CorporateActionRequest, response: Response, auth: AuthContext = Depends(require_trade_write), idempotency_key: str = Header(..., alias="Idempotency-Key")):
def create_corporate_action(
portfolio_id: str,
payload: CorporateActionRequest,
response: Response,
auth: AuthContext = Depends(require_trade_write), # noqa: B008 - FastAPI dependency declaration
idempotency_key: str = Header(..., alias="Idempotency-Key"),
):
if not idempotency_key or not idempotency_key.strip():
raise HTTPException(status_code=422, detail="Idempotency-Key must not be empty")
repo = _get_repo()
@@ -1328,7 +1337,7 @@ def create_corporate_action(portfolio_id: str, payload: CorporateActionRequest,
from app.domain.corporate_actions import canonical_payload_hash
digest = canonical_payload_hash(payload)
# The repository derives all WAC and immutable snapshot fields under its row lock.
action = CorporateAction(str(uuid.uuid4()), portfolio_id, portfolio.asset_id, payload.action_type, payload.effective_date, payload.quantity_before, payload.quantity_after, Decimal("0"), Decimal("0"), Decimal("0"), Decimal(str(portfolio.cash_balance)), Decimal(str(portfolio.profit_buffer)), payload.evidence_ref, idempotency_key, digest, 0, auth.user_id)
action = CorporateAction(str(uuid.uuid4()), portfolio_id, portfolio.asset_id, payload.action_type, payload.effective_date, payload.quantity_before, payload.quantity_after, Decimal(0), Decimal(0), Decimal(0), Decimal(str(portfolio.cash_balance)), Decimal(str(portfolio.profit_buffer)), payload.evidence_ref, idempotency_key, digest, 0, auth.user_id)
saved = repo.record_corporate_action(portfolio_id, action=action, idempotency_key=idempotency_key, payload_hash=digest)
return CorporateActionResponse(**saved.__dict__)
except ValueError as exc: