from datetime import date, datetime from decimal import Decimal from typing import Literal from pydantic import BaseModel, ConfigDict, Field, model_validator # Corporate actions (stock_consolidation-only, issue #34) class CorporateActionRequest(BaseModel): model_config = ConfigDict(extra="forbid") action_type: Literal["stock_consolidation"] = "stock_consolidation" effective_date: date quantity_before: Decimal = Field(..., gt=0, max_digits=20, decimal_places=8) quantity_after: Decimal = Field(..., gt=0, max_digits=20, decimal_places=8) evidence_ref: str = Field(..., min_length=1, max_length=500) confirm_daemon_managed: bool = False resume_partial: bool = False @model_validator(mode="after") def valid_ratio(self): if self.quantity_after >= self.quantity_before: raise ValueError("quantity_after must be less than quantity_before") return self class CorporateActionResponse(BaseModel): corporate_action_id: str ledger_entry_id: int portfolio_id: str action_type: Literal["stock_consolidation"] effective_date: date quantity_before: Decimal quantity_after: Decimal average_price_before: Decimal average_price_after: Decimal total_cost_basis: Decimal cash_balance: Decimal profit_buffer: Decimal evidence_ref: str actor_user_id: str | None = None recorded_at: datetime idempotent_replay: bool = False