""" 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 from base import UserRole, PartnerType, TransactionType, TransactionStatus class User(SQLModel, table=True): """ User table mapping, api response validation and serialisation """ id: Optional[int] = Field(default=None, primary_key=True) username: str = Field(nullable=False,unique=True, max_length=100) role: UserRole = Field(nullable=True, default=PartnerType.CLIENT) password_hash: str = Field(nullable=False) class Partner(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) type: PartnerType = Field(nullable=False, default=PartnerType.CLIENT) phone_number: str = Field(max_length=10, nullable=True) class Product(SQLModel, table=True): """Products table mapping, api response validation and serialisation NOTE: Every time a product's purchase price changes, it should be updated here as well """ __table_args__ = (UniqueConstraint("product_code")) id: Optional[int] = Field(default=None, primary_key=True) product_code: str = Field(max_length=10, unique=True, 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(timezone=True), server_default=func.now(), server_onupdate=func.now()) ) class Transaction(SQLModel, table=True): """ Transaction table mapping, api response validation and serialisation Include both business events to/from suppliers and to/from clients """ __tablename__: str = "transactions" id: Optional[int] = Field(default=None, primary_key=True) partner_id: Optional[int] = Field(nullable=False, foreign_key="partner.id") transcation_type: TransactionType = Field( sa_column=Column(SQLEnum(TransactionType), nullable=False) ) transaction_status: TransactionStatus created_on: datetime = Field( default=None, sa_column=Column(DateTime(timezone=True), server_default=func.now()) ) updated_on: datetime = Field( default=None, sa_column=Column( DateTime(timezone=True), onupdate=func.now(), server_default=func.now() ) ) class Transaction_items(SQLModel, table=True): """ Transaction table mapping, api response validation and serialisation Includes transactions details from transactions """ class Payment(SQLModel, table=True): """ """ class Credit_accounts(SQLModel, table=True): """Credit table mapping, api response validation and serialisation Include both credit from suppliers and to clients """ __tablename__: str = "credit_accounts" id: Optional[int] = Field(default=None, primary_key=True) product_code: str = Field(nullable=False, foreign_key="product.product_code") client_id: Optional[int] = Field(nullable=True, foreign_key="client.id") supplier_id: Optional[int] = Field(nullable=True, foreign_key="supplier.id") qty: int = Field(nullable=False) amount: int = Field(nullable=False) date: datetime = Field( default=None, sa_column=Column(DateTime(timezone=True), server_default=func.now()) )