"""Split schemas.""" from datetime import datetime from typing import Literal, Optional from pydantic import Field, model_validator from collaborator.constants.split import RateType from collaborator.constants.split_type import SplitTypeId from collaborator.schemas import BaseSchema, BaseTableSchema class SplitSchema(BaseTableSchema): """Schema for Split table entity.""" id: int = Field(alias="split_id") identifier: str split_rate: float split_type_id: SplitTypeId collaborator_id: int rate_type: RateType created_date: datetime created_by: Optional[str] = None updated_date: Optional[datetime] = None updated_by: Optional[str] = None source: Optional[str] = None # # Replace Splits # class ReplaceTrackSplitSchema(BaseSchema): """A single split within a track on the /splits/replace request.""" id: Optional[int] = None collaborator_id: int split_rate: float split_type_id: int rate_type: str class ReplaceTrackSplitsSchema(BaseSchema): """A track and its splits on the /splits/replace request.""" tuid: str splits: list[ReplaceTrackSplitSchema] class ReplaceSplitsBody(BaseSchema): """Request body for /splits/replace.""" dp_splits_agreed: Optional[bool] = None tracks: list[ReplaceTrackSplitsSchema] = Field(..., min_length=1) class ReplacementSplitSchema(BaseSchema): """A split in the /splits/replace request.""" collaborator_id: int split_rate: float rate_type: str class ReplacementSplitsSchema(BaseSchema): """An identifier and its splits on the /splits/replace request.""" identifier: str split_type_id: SplitTypeId splits: list[ReplacementSplitSchema] class ReplaceSplitsRequestSchema(BaseSchema): """Request body for /splits/replace.""" vendor_id: int dp_splits_agreed: Optional[bool] = None replacements: list[ReplacementSplitsSchema] = Field(..., min_length=1) # # Bulk Ingest # class BulkSplitRow(BaseSchema): """Schema for a single bulk split row. Attributes: collaborator_id (int): The ID of the collaborator. collaborator_name (str): The name of the collaborator. product_id (int): The product ID for product-level expansion. tuid (str): The track unique identifier. rate_type (str): The type of rate (GROSS or NET). vendor_id (int): The ID of the vendor. split_rate (float): The rate of the split. """ collaborator_id: Optional[int] = None collaborator_name: Optional[str] = None product_id: Optional[int] = None tuid: Optional[str] = None rate_type: Literal["GROSS", "NET"] vendor_id: int split_rate: float @model_validator(mode="after") def validate_identifier(self) -> "BulkSplitRow": """Validate that at least one of product_id or tuid is provided.""" if not self.product_id and not self.tuid: raise ValueError("At least one of 'product_id' or 'tuid' must be provided.") return self class BulkIngestTemplateRowSchema(BaseSchema): """A single row in the bulk split ingestion template response.""" vendor_id: int product_id: int product_upc: Optional[str] product_title: Optional[str] tuid: str track_name: Optional[str] track_isrc: Optional[str] class OverwrittenSplitSchema(BaseSchema): """Details of an existing split that is overwritten by the ingest.""" product_id: Optional[int] tuid: str collaborator_name: Optional[str] old_split_rate: float new_split_rate: float class IngestSummarySchema(BaseSchema): """Response schema for the bulk split ingest endpoint.""" vendor_id: int input_rows: int expanded_rows: int existing_collaborators_matched: int new_collaborators: int tracks_with_existing_splits_updated: int tracks_with_new_splits: int tracks_with_unaffected_splits: int existing_splits_updated: int new_splits_created: int products_skipped_no_tracks: int vendor_currency: str dry_run: bool splits_ingested: int tracks_impacted: int products_impacted: int collaborators_receiving_new_splits: int overwritten_splits: list[OverwrittenSplitSchema]