from decimal import Decimal from pydantic import BaseModel, ConfigDict, Field class Line(BaseModel): model_config = ConfigDict(extra="forbid") sku: str | None = Field(default=None, max_length=100) description: str | None = Field(default=None, max_length=500) quantity: Decimal | None = Field(default=None, ge=0, le=1000000, allow_inf_nan=False) unit_price: Decimal | None = Field(default=None, ge=0, le=1000000000, allow_inf_nan=False) amount: Decimal | None = Field(default=None, ge=0, le=1000000000000, allow_inf_nan=False) class Source(BaseModel): field: str = Field(max_length=100) page: int = Field(ge=1, le=10) excerpt: str = Field(min_length=1, max_length=1000) class Document(BaseModel): model_config = ConfigDict(extra="forbid") vendor: str | None = Field(default=None, max_length=300) number: str | None = Field(default=None, max_length=100) date: str | None = Field(default=None, max_length=40) currency: str | None = Field(default=None, pattern=r"^[A-Z]{3}$") subtotal: Decimal | None = Field(default=None, ge=0, le=1000000000000, allow_inf_nan=False) tax: Decimal | None = Field(default=None, ge=0, le=1000000000000, allow_inf_nan=False) total: Decimal | None = Field(default=None, ge=0, le=1000000000000, allow_inf_nan=False) lines: list[Line] = Field(default_factory=list, max_length=100) sources: list[Source] = Field(default_factory=list, max_length=100) notes: list[str] = Field(default_factory=list, max_length=20) class Review(BaseModel): revision: int = Field(ge=0) invoice: Document purchase: Document | None = None