from decimal import Decimal from typing import Literal from pydantic import BaseModel, Field, field_validator, model_validator from app.schemas.system_setting import SettingsSource, normalize_text LexwareSyncStatus = Literal["pending", "success", "failed", "skipped"] LexwareSyncDirection = Literal["push", "pull"] class LexwareSettingsResponse(BaseModel): enabled: bool = False api_base_url: str = "https://api.lexware.io" api_key_is_set: bool = False organization_name: str = "" default_tax_rate: Decimal = Decimal("19.00") default_payment_terms_days: int = 14 source: SettingsSource class LexwareSettingsUpdate(BaseModel): enabled: bool = False api_base_url: str = Field(default="https://api.lexware.io", max_length=500) api_key: str | None = Field(default=None, max_length=2000) organization_name: str = Field(default="", max_length=255) default_tax_rate: Decimal = Field(default=Decimal("19.00"), ge=Decimal("0"), le=Decimal("100")) default_payment_terms_days: int = Field(default=14, ge=0, le=365) @field_validator("api_base_url", "api_key", "organization_name", mode="before") @classmethod def normalize_strings(cls, value: object) -> str: return normalize_text(value) @field_validator("api_base_url") @classmethod def normalize_base_url(cls, value: str) -> str: return (value or "https://api.lexware.io").rstrip("/") @model_validator(mode="after") def validate_enabled_configuration(self): if self.enabled and not self.api_base_url: raise ValueError("API Base URL ist erforderlich, wenn Lexware aktiviert ist") return self class LexwareTestConnectionResponse(BaseModel): success: bool message: str source: SettingsSource api_base_url: str organization_name: str = "" class LexwareCustomerMapping(BaseModel): name: str email: str phone: str search_strategy: str create_payload: dict class LexwareLineItemMapping(BaseModel): title: str description: str | None quantity: Decimal unit: str unit_price: Decimal tax_rate: Decimal total: Decimal class LexwareInvoicePreparationResponse(BaseModel): ready_for_export: bool payload_summary: dict customer_mapping: LexwareCustomerMapping line_item_mapping: list[LexwareLineItemMapping] tax_mapping: dict warnings: list[str] sync_record_id: int