from __future__ import annotations from datetime import date from pydantic import BaseModel, Field, field_validator from typing import List, Optional class Address(BaseModel): street: str postal_code: str city: str country: str = Field(min_length=2, max_length=2) class Party(BaseModel): name: str vat_id: Optional[str] = None tax_number: Optional[str] = None email: Optional[str] = None address: Address @field_validator("email") @classmethod def _email_shape(cls, v: Optional[str]): if v is None: return v if "@" not in v or "." not in v.split("@")[-1]: raise ValueError("email does not look valid") return v class Meta(BaseModel): invoice_number: str = Field(min_length=1) invoice_date: date service_date: date currency: str = Field(min_length=3, max_length=3, default="EUR") language: Optional[str] = "de" notes: Optional[str] = None class Payment(BaseModel): due_date: date reference: str = Field(min_length=1) iban: Optional[str] = None bic: Optional[str] = None bank_name: Optional[str] = None class Item(BaseModel): name: str = Field(min_length=1) description: Optional[str] = None quantity: float = Field(gt=0) unit: str = Field(min_length=1) # e.g. HUR, C62 unit_price_net: float = Field(ge=0) tax_rate: float = Field(ge=0, le=100) class Invoice(BaseModel): meta: Meta seller: Party buyer: Party payment: Payment items: List[Item]