""" This module contains Pydantic/Database Models that map database tables validate and serialize api responses. If the logic is identical -> SQLModel is used to do both. Otherwise pydantic - for api responses And SQLAlchemy is used for db data validation. TODO: Mapping & validation for: - Clients, Suppliers, Products, payments Done: * Table mappings """ from sqlmodel import SQLModel, Field, UniqueConstraint from datetime import datetime from sqlalchemy import Column, DateTime, func, Enum as SQLEnum from enum import Enum from typing import Optional class TradeType(str, Enum): BUY = "Buy" SELL = "Sell" class Client(SQLModel, table=True): """Clients table mapping, api response validation and serialisation""" id: Optional[int] = Field(default=None, primary_key=True) tin_number: int = Field(nullable=False, unique=True) names: str = Field(max_length=100, nullable=False) phone_number: str = Field(max_length=10, nullable=False) class Supplier(SQLModel, table=True): """Supplier table mapping, api response validation and serialisation""" id: Optional[int] = Field(default=None, primary_key=True) tin_number: int = Field(nullable=False, unique=True) names: str = Field(max_length=100, nullable=False) phone_number: str = Field(max_length=10, nullable=False) class Product(SQLModel, table=True): """Products table mapping, api response validation and serialisation NOTE: purchase price should update every time a supplier credits us goods and price has changed """ __table_args__ = (UniqueConstraint("product_code"),) id: Optional[int] = Field(default=None, primary_key=True) product_code: str = Field(max_length=10, nullable=False) product_name: str = Field(max_length=20, nullable=False, unique=True) purchase_price: int = Field(nullable=False) date_modified: datetime = Field( default=None, sa_column=Column(DateTime, server_default=func.now(), server_onupdate=func.now()) ) class Payment(SQLModel, table=True): """ Payments table mapping, api response validation and serialisation Include both payments to suppliers and from clients """ id: Optional[int] = Field(default=None, primary_key=True) payment_type: TradeType = Field( sa_column=Column(SQLEnum(TradeType), nullable=False) ) product_code: str = Field(nullable=False, foreign_key="product.product_code") client_id: Optional[int] = Field(nullable=False, foreign_key="client.id") supplier_id: Optional[int] = Field(nullable=False, foreign_key="supplier.id") amount: int = Field(nullable=False) payment_method: str = Field(max_length=24, nullable=False) date: datetime = Field( default=None, sa_column=Column(DateTime, server_default=func.now()) ) class Credit(SQLModel, table=True): """Credit table mapping, api response validation and serialisation Include both credit from suppliers and to clients """ id: Optional[int] = Field(default=None, primary_key=True) transcation_type: TradeType = Field( sa_column=Column(SQLEnum(TradeType), nullable=False) ) product_code: str = Field(nullable=False, foreign_key="product.product_code") client_id: Optional[int] = Field(nullable=False, foreign_key="client.id") supplier_id: Optional[int] = Field(nullable=False, foreign_key="supplier.id") qty: int = Field(nullable=False) amount: int = Field(nullable=False) date: datetime = Field( default=None, sa_column=Column(DateTime, server_default=func.now()) )