96 lines
2.9 KiB
Python
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
|