from datetime import date, datetime from decimal import Decimal from pydantic import BaseModel, ConfigDict, Field, computed_field class InvoiceItemBase(BaseModel): concept: str = Field(..., max_length=60) description: str | None = Field(None, max_length=255) quantity: Decimal = Field(Decimal(1), ge=0, max_digits=12, decimal_places=2) unit_amount: Decimal = Field(Decimal(0), ge=0, max_digits=14, decimal_places=2) class InvoiceItemCreate(InvoiceItemBase): invoice_id: int class InvoiceItemUpdate(BaseModel): concept: str | None = Field(None, max_length=60) description: str | None = Field(None, max_length=255) quantity: Decimal | None = Field(None, ge=0, max_digits=12, decimal_places=2) unit_amount: Decimal | None = Field(None, ge=0, max_digits=14, decimal_places=2) class InvoiceItemResponse(InvoiceItemBase): model_config = ConfigDict(from_attributes=True) id: int invoice_id: int tenant_id: int company_id: int @computed_field @property def line_total(self) -> Decimal: return (self.quantity or Decimal(0)) * (self.unit_amount or Decimal(0)) class PaymentBase(BaseModel): amount: Decimal = Field(..., gt=0, max_digits=14, decimal_places=2) payment_date: date | None = None method: str | None = Field(None, max_length=40) reference: str | None = Field(None, max_length=120) notes: str | None = None class PaymentCreate(PaymentBase): invoice_id: int class PaymentResponse(PaymentBase): model_config = ConfigDict(from_attributes=True) id: int invoice_id: int tenant_id: int company_id: int created_at: datetime class InvoiceBase(BaseModel): reference: str | None = Field(None, max_length=40) shipment_id: int | None = None quote_id: int | None = None account_id: int | None = None currency: str = Field("MXN", max_length=3) issue_date: date | None = None due_date: date | None = None tax_rate: Decimal = Field(Decimal(0), ge=0, le=100, max_digits=5, decimal_places=2) bank_info: str | None = None notes: str | None = None owner_user_id: str | None = Field(None, max_length=64) class InvoiceCreate(InvoiceBase): pass class InvoiceUpdate(BaseModel): reference: str | None = Field(None, max_length=40) shipment_id: int | None = None quote_id: int | None = None account_id: int | None = None currency: str | None = Field(None, max_length=3) issue_date: date | None = None due_date: date | None = None tax_rate: Decimal | None = Field(None, ge=0, le=100, max_digits=5, decimal_places=2) bank_info: str | None = None notes: str | None = None owner_user_id: str | None = Field(None, max_length=64) class InvoiceResponse(InvoiceBase): model_config = ConfigDict(from_attributes=True) id: int status: str subtotal: Decimal tax_amount: Decimal total: Decimal paid_amount: Decimal balance: Decimal sent_at: datetime | None = None paid_at: datetime | None = None created_by: str | None = None updated_by: str | None = None tenant_id: int company_id: int created_at: datetime updated_at: datetime