from __future__ import annotations from decimal import Decimal from uuid import UUID from pydantic import BaseModel, Field, model_validator class ExpenseItemCreate(BaseModel): description: str amount: Decimal participants: list[str] shares: dict[str, float] | None = None @model_validator(mode="after") def validate_shares(self) -> ExpenseItemCreate: if self.shares is not None: if set(self.shares.keys()) != set(self.participants): raise ValueError("shares keys must match participants exactly") total = sum(self.shares.values()) if abs(total - 100.0) > 0.01: raise ValueError(f"shares must sum to 100, got {total}") if len(self.participants) != len(set(self.participants)): raise ValueError("participants must be unique") return self class ExpenseReportCreate(BaseModel): title: str items: list[ExpenseItemCreate] class ExpenseShareOut(BaseModel): user_sub: str user_name: str | None percentage: float class ExpenseItemOut(BaseModel): id: UUID description: str amount: Decimal shares: list[ExpenseShareOut] class ExpenseReportOut(BaseModel): id: UUID title: str creator_sub: str creator_name: str | None created_at: str items: list[ExpenseItemOut] participants: list[dict[str, str | None]] class ExpenseReportListOut(BaseModel): reports: list[ExpenseReportOut] total_count: int class ErrorResponse(BaseModel): detail: str