Olympus/backend/hermes/app/schemas/lexware.py
2026-07-05 13:41:33 +02:00

96 lines
2.9 KiB
Python

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"]
AccountingExportStatus = Literal["prepared", "transferred", "booked", "cancelled"]
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
export_status: AccountingExportStatus
payload_summary: dict
customer_mapping: LexwareCustomerMapping
line_item_mapping: list[LexwareLineItemMapping]
tax_mapping: dict
warnings: list[str]
sync_record_id: int
accounting_note: str = ""
transferred_at: str | None = None
transferred_by_user_id: int | None = None
class AccountingTransferUpdate(BaseModel):
accounting_note: str | None = Field(default=None, max_length=2000)
@field_validator("accounting_note", mode="before")
@classmethod
def normalize_note(cls, value: object) -> str | None:
text = normalize_text(value)
return text or None