# /opt/docker/dev/service_finder/backend/app/schemas/fleet_finance.py """ Pydantic sémák a flotta pénzügyi modelljeihez. - AssetFinancials: Beszerzés, finanszírozás, értékcsökkenés - InsuranceProvider: Biztosítók katalógusa - VehicleInsurancePolicy: Jármű biztosítási kötvények - VehicleTaxObligation: Jármű adókötelezettségek """ from pydantic import BaseModel, ConfigDict, Field, field_validator from typing import Optional, Dict, Any, List from uuid import UUID from datetime import datetime, date # ============================================================================= # AssetFinancials sémák # ============================================================================= class AssetFinancialsUpdate(BaseModel): """AssetFinancials frissítése - minden mező opcionális.""" purchase_price_net: Optional[float] = Field(None, ge=0, description="Nettó vételár") purchase_price_gross: Optional[float] = Field(None, ge=0, description="Bruttó vételár") vat_rate: Optional[float] = Field(None, ge=0, le=100, description="ÁFA kulcs (%)") activation_date: Optional[datetime] = Field(None, description="Aktiválás dátuma") verified_purchase_date: Optional[datetime] = Field(None, description="Ellenőrzött vásárlási dátum") financing_type: Optional[str] = Field(None, max_length=50, description="Finanszírozás típusa (cash, loan, lease)") accounting_details: Optional[Dict[str, Any]] = Field(None, description="Számviteli részletek (JSONB)") # Finanszírozás down_payment: Optional[float] = Field(None, ge=0, description="Önerő") monthly_installment: Optional[float] = Field(None, ge=0, description="Havi törlesztő") residual_value: Optional[float] = Field(None, ge=0, description="Maradványérték") contract_number: Optional[str] = Field(None, max_length=100, description="Szerződésszám") financing_provider: Optional[str] = Field(None, max_length=200, description="Finanszírozó") interest_rate: Optional[float] = Field(None, ge=0, le=100, description="Kamatláb (%)") total_contract_value: Optional[float] = Field(None, ge=0, description="Teljes szerződéses érték") lease_start_date: Optional[date] = Field(None, description="Lízing kezdete") lease_end_date: Optional[date] = Field(None, description="Lízing vége") model_config = ConfigDict(from_attributes=True) class AssetFinancialsResponse(BaseModel): """AssetFinancials teljes válaszmodell.""" id: int asset_id: UUID # Beszerzés purchase_price_net: float purchase_price_gross: float vat_rate: float activation_date: Optional[datetime] = None verified_purchase_date: Optional[datetime] = None financing_type: str accounting_details: Dict[str, Any] = Field(default_factory=dict) # Finanszírozás down_payment: Optional[float] = None monthly_installment: Optional[float] = None residual_value: Optional[float] = None contract_number: Optional[str] = None financing_provider: Optional[str] = None interest_rate: Optional[float] = None total_contract_value: Optional[float] = None lease_start_date: Optional[date] = None lease_end_date: Optional[date] = None model_config = ConfigDict(from_attributes=True) # ============================================================================= # InsuranceProvider sémák # ============================================================================= class InsuranceProviderResponse(BaseModel): """Biztosító teljes válaszmodell.""" id: int name: str country_code: Optional[str] = Field(None, max_length=2, description="ISO 3166-1 alpha-2 országkód (pl. 'HU'). Ha None, akkor globális.") claim_phone: Optional[str] = None claim_url: Optional[str] = None services_offered: Dict[str, Any] = Field(default_factory=dict) is_active: bool = True model_config = ConfigDict(from_attributes=True) class InsuranceProviderCreate(BaseModel): """Új biztosító létrehozása.""" name: str = Field(..., min_length=1, max_length=150, description="Biztosító neve") country_code: Optional[str] = Field(None, max_length=2, description="ISO 3166-1 alpha-2 országkód (pl. 'HU'). Ha None, akkor globális.") claim_phone: Optional[str] = Field(None, max_length=50, description="Kárbejelentő telefonszám") claim_url: Optional[str] = Field(None, max_length=255, description="Kárbejelentő URL") services_offered: Optional[Dict[str, Any]] = Field(None, description="Kínált szolgáltatások (JSONB)") is_active: bool = Field(default=True, description="Aktív-e") model_config = ConfigDict(from_attributes=True) class InsuranceProviderUpdate(BaseModel): """Biztosító frissítése - minden mező opcionális.""" name: Optional[str] = Field(None, min_length=1, max_length=150, description="Biztosító neve") country_code: Optional[str] = Field(None, max_length=2, description="ISO 3166-1 alpha-2 országkód (pl. 'HU'). Ha None, akkor globális.") claim_phone: Optional[str] = Field(None, max_length=50, description="Kárbejelentő telefonszám") claim_url: Optional[str] = Field(None, max_length=255, description="Kárbejelentő URL") services_offered: Optional[Dict[str, Any]] = Field(None, description="Kínált szolgáltatások (JSONB)") is_active: Optional[bool] = Field(None, description="Aktív-e") model_config = ConfigDict(from_attributes=True) # ============================================================================= # VehicleInsurancePolicy sémák # ============================================================================= class VehicleInsurancePolicyCreate(BaseModel): """Új biztosítási kötvény létrehozása.""" provider_id: int = Field(..., description="Biztosító ID (insurance_providers tábla)") insurance_type: str = Field(..., max_length=20, description="Biztosítás típusa (KGFB, CASCO)") policy_number: str = Field(..., max_length=100, description="Kötvényszám") start_date: date = Field(..., description="Biztosítás kezdete") expiry_date: date = Field(..., description="Biztosítás lejárata") premium_amount: float = Field(..., ge=0, description="Díj összege") currency: str = Field(default="HUF", max_length=3, description="Pénznem") document_id: Optional[UUID] = Field(None, description="Kapcsolódó dokumentum ID (PDF kötvény)") @field_validator('insurance_type') @classmethod def validate_insurance_type(cls, v: str) -> str: """insurance_type csak KGFB vagy CASCO lehet.""" allowed = {"KGFB", "CASCO"} cleaned = v.strip().upper() if cleaned not in allowed: raise ValueError(f'A biztosítás típusa csak {allowed} lehet, kapott: "{v}"') return cleaned @field_validator('expiry_date') @classmethod def validate_expiry_after_start(cls, v: date, info): """expiry_date nem lehet a start_date előtt.""" values = info.data start = values.get('start_date') if start and v <= start: raise ValueError('A biztosítás lejárati dátuma nem lehet a kezdő dátum előtt vagy azzal egyenlő') return v model_config = ConfigDict(from_attributes=True) class VehicleInsurancePolicyUpdate(BaseModel): """Biztosítási kötvény frissítése - minden mező opcionális.""" provider_id: Optional[int] = Field(None, description="Biztosító ID") insurance_type: Optional[str] = Field(None, max_length=20, description="Biztosítás típusa") policy_number: Optional[str] = Field(None, max_length=100, description="Kötvényszám") start_date: Optional[date] = Field(None, description="Biztosítás kezdete") expiry_date: Optional[date] = Field(None, description="Biztosítás lejárata") premium_amount: Optional[float] = Field(None, ge=0, description="Díj összege") currency: Optional[str] = Field(None, max_length=3, description="Pénznem") document_id: Optional[UUID] = Field(None, description="Kapcsolódó dokumentum ID (PDF kötvény)") model_config = ConfigDict(from_attributes=True) class VehicleInsurancePolicyResponse(BaseModel): """Biztosítási kötvény teljes válaszmodell.""" id: UUID asset_id: UUID provider_id: int insurance_type: str policy_number: str start_date: date expiry_date: date premium_amount: float currency: str document_id: Optional[UUID] = None model_config = ConfigDict(from_attributes=True) # ============================================================================= # VehicleTaxObligation sémák # ============================================================================= class VehicleTaxObligationCreate(BaseModel): """Új adókötelezettség létrehozása.""" tax_type: str = Field(..., max_length=30, description="Adó típusa (WEIGHT_TAX, COMPANY_CAR_TAX)") tax_year: int = Field(..., ge=2000, le=2100, description="Adóév") amount: float = Field(..., ge=0, description="Adó összege") currency: str = Field(default="HUF", max_length=3, description="Pénznem") due_date: Optional[date] = Field(None, description="Fizetési határidő") payment_status: str = Field(default="pending", max_length=20, description="Fizetési státusz") document_id: Optional[UUID] = Field(None, description="Kapcsolódó dokumentum ID (PDF adóbevallás)") @field_validator('tax_type') @classmethod def validate_tax_type(cls, v: str) -> str: """tax_type csak WEIGHT_TAX vagy COMPANY_CAR_TAX lehet.""" allowed = {"WEIGHT_TAX", "COMPANY_CAR_TAX"} cleaned = v.strip().upper() if cleaned not in allowed: raise ValueError(f'Az adó típusa csak {allowed} lehet, kapott: "{v}"') return cleaned @field_validator('payment_status') @classmethod def validate_payment_status(cls, v: str) -> str: """payment_status csak pending, paid, overdue lehet.""" allowed = {"pending", "paid", "overdue"} cleaned = v.strip().lower() if cleaned not in allowed: raise ValueError(f'A fizetési státusz csak {allowed} lehet, kapott: "{v}"') return cleaned model_config = ConfigDict(from_attributes=True) class VehicleTaxObligationUpdate(BaseModel): """Adókötelezettség frissítése - minden mező opcionális.""" tax_type: Optional[str] = Field(None, max_length=30, description="Adó típusa") tax_year: Optional[int] = Field(None, ge=2000, le=2100, description="Adóév") amount: Optional[float] = Field(None, ge=0, description="Adó összege") currency: Optional[str] = Field(None, max_length=3, description="Pénznem") due_date: Optional[date] = Field(None, description="Fizetési határidő") payment_status: Optional[str] = Field(None, max_length=20, description="Fizetési státusz") document_id: Optional[UUID] = Field(None, description="Kapcsolódó dokumentum ID (PDF adóbevallás)") model_config = ConfigDict(from_attributes=True) class VehicleTaxObligationResponse(BaseModel): """Adókötelezettség teljes válaszmodell.""" id: UUID asset_id: UUID tax_type: str tax_year: int amount: float currency: str due_date: Optional[date] = None payment_status: str document_id: Optional[UUID] = None model_config = ConfigDict(from_attributes=True)