from datetime import datetime from typing import Literal from pydantic import BaseModel # -- settings -- class SettingsLocalDB(BaseModel): filepath: str class SettingsOrderUpload(BaseModel): filepath: str class SettingsCurrency(BaseModel): default: str now_payments: str class Settings(BaseModel): git_repo: str document_match: list[str] document_exclude: list[str] block_types: list[str] local_db: SettingsLocalDB order_upload: SettingsOrderUpload currency: SettingsCurrency # -- cart -- # session-related data structures class CartSessionMeta(BaseModel): order_id: str currency: str subtotal: int = 0 total_weight: int = 0 shipping: float = 0.0 total: float = 0.0 item_amount: int = 0 class CartSessionItemOptions(BaseModel): product_variation_id: str | None = None size: Literal["s", "m", "l", "xl", "xxl"] | None style: str | None weight: int | None class CartSessionItem(BaseModel): product_id: str options: CartSessionItemOptions price: int = 0 quantity: int = 0 availability: bool = False class CartSession(BaseModel): meta: CartSessionMeta items: dict[str, CartSessionItem] class CartUpdate(BaseModel): operation: Literal["add", "remove", "delete", "manual"] product_id: str options: CartSessionItemOptions price: int = 0 # view-related data structures class CheckoutItemImage(BaseModel): url: str width: int height: int class CheckoutItem(CartSessionItem): path: str title: str image: CheckoutItemImage product_id: str options: CartSessionItemOptions price: int = 0 weight: int quantity: int = 0 total: int = 0 availability: bool = False is_selectable: bool = False class CheckoutItemUpdate(BaseModel): quantity: int = 0 total: int = 0 is_selectable: bool = False class CartOrderInfo(BaseModel): code: str title: str price: int = 0 quantity: int = 0 options: CartSessionItemOptions class ProductInfoCode(BaseModel): path: str options: CartSessionItemOptions quantity: int # -- shipping info class ShippingInfo(BaseModel): email: str first_name: str | None = None last_name: str address: str address_no: str address_extra: str | None = None postal_code: str city: str country: str phone_number: str | None = None note: str | None = None # -- shipping cost class ShippingCostEntry(BaseModel): price: float min: int max: int | None class ShippingRate(BaseModel): price: float area: str class ProductShippingMeta(BaseModel): weight: int customs_tariff_code: str origin_country_iso: str # -- documents -- class DocumentBlockImageInfo(BaseModel): width: int height: int class DocumentBlock(BaseModel): type: str value: str | None = None url: str | None = None caption: str | None = None info: DocumentBlockImageInfo | None = None # -- document: site class DocumentMetaLink(BaseModel): label: str url: str class DocumentSiteMeta(BaseModel): type: str title: str template: str path: str | None = None footer: list[DocumentMetaLink] class DocumentSite(BaseModel): meta: DocumentSiteMeta blocks: list[DocumentBlock] # -- document: index class DocumentIndexMeta(BaseModel): type: str title: str template: str path: str | None = None class DocumentIndex(BaseModel): meta: DocumentIndexMeta blocks: list[DocumentBlock] # -- document: page -- class DocumentPageMeta(BaseModel): type: str title: str template: str category: str | None = None path: str | None = None class DocumentPage(BaseModel): meta: DocumentPageMeta blocks: list[DocumentBlock] # -- document: products index -- class DocumentProductIndexMeta(BaseModel): type: str title: str template: str path: str | None = None class DocumentProductIndex(BaseModel): meta: DocumentProductIndexMeta blocks: list[DocumentBlock] # -- document: product class DocumentProductMetaOptions(BaseModel): size: list[str] | None = None style: list[str] | None = None class DocumentProductMetaInventory(BaseModel): product_variation_id: str | None = None size: str | None = None style: str | None = None amount: int class DocumentProductMeta(BaseModel): type: str title: str template: str code: str product_id: str price: int weight: int customs_tariff_code: str origin_country_iso: str category: str inventory: list[DocumentProductMetaInventory] options: DocumentProductMetaOptions | None = None path: str | None = None class DocumentProduct(BaseModel): meta: DocumentProductMeta blocks: list[DocumentBlock] # -- document: orders class DocumentOrdersMeta(BaseModel): type: str title: str template: str path: str | None = None class OrdersBlockItem(BaseModel): code: str title: str quantity: int price: int class OrdersBlockShippingInfo(BaseModel): first_name: str | None last_name: str address: str address_no: str address_extra: str | None postal_code: str city: str country: str note: str | None phone_number: str | None email: str class OrdersBlock(BaseModel): type: str date: datetime order_id: str product_list: str payment_provider: str payment_reference: str status: str items: list[OrdersBlockItem] currency: str subtotal: int shipping: float total: float shipping_info: OrdersBlockShippingInfo class DocumentOrders(BaseModel): meta: DocumentOrdersMeta blocks: list[OrdersBlock] # -- document: checkout class DocumentCheckoutMeta(BaseModel): type: str title: str template: str path: str | None = None class DocumentCheckout(BaseModel): meta: DocumentCheckoutMeta blocks: list[DocumentBlock] # -- document: checkout product info class DocumentCheckoutProductInfo(BaseModel): filename: str quantity: int size: Literal["s", "m", "l", "xl", "xxl"] | None style: str | None # -- document: email class DocumentEmailMeta(BaseModel): type: str title: str template: str sender: str path: str | None = None class DocumentEmail(BaseModel): meta: DocumentEmailMeta blocks: list[DocumentBlock] # -- NOW Payments invoice payload class NowPaymentsInvoice(BaseModel): price_amount: float price_currency: str ipn_callback_url: str order_id: str success_url: str | None = None cancel_url: str | None = None