from datetime import datetime from decimal import Decimal from typing import Dict from sqlalchemy import JSON, BigInteger, ForeignKey, Numeric, String from sqlalchemy.ext.asyncio import AsyncAttrs from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship __all__ = [ "Base", "Item", "Provider", "Order", "LocationType", "Location", "ItemBatch", "Discount", "Customer", "Cart", "ItemOnShelf", ] class Base(AsyncAttrs, DeclarativeBase): pass class Provider(Base): __tablename__ = "providers" id: Mapped[int] = mapped_column(primary_key=True) name: Mapped[str] address: Mapped[str] phone: Mapped[str] vat: Mapped[str] def __repr__(self) -> str: return f"" class Item(Base): __tablename__ = "items" sku: Mapped[int] = mapped_column(primary_key=True) upc: Mapped[int] = mapped_column(BigInteger, nullable=False) provider: Mapped[int] = mapped_column(ForeignKey("providers.id")) name: Mapped[str] = mapped_column(nullable=False) package: Mapped[str] = mapped_column(unique=False) current: Mapped[bool] = mapped_column( comment="True if the item can be still requested to a provider, " "False if it has been discontinued" ) # unit_weight: Mapped[int] = mapped_column( # comment="Unit weight in grams not including additional packaging" # ) To be added as exercise volume_unpacked: Mapped[int] = mapped_column( comment="Volume of the item unpacked in cubic decimeters" ) volume_packed: Mapped[int] = mapped_column( comment="Volume of each unit item when packaged in cubic decimeters" ) def __repr__(self) -> str: return f"" class Order(Base): __tablename__ = "orders" id: Mapped[int] = mapped_column(primary_key=True) sku: Mapped[int] = mapped_column(ForeignKey("items.sku")) placed: Mapped[datetime] qty: Mapped[int] = mapped_column(nullable=False) provider: Mapped[int] = mapped_column(ForeignKey("providers.id")) class LocationType(Base): __tablename__ = "locationtypes" id: Mapped[int] = mapped_column(primary_key=True) name: Mapped[str] retail: Mapped[bool] class Location(Base): __tablename__ = "locations" id: Mapped[int] = mapped_column(primary_key=True) loctype: Mapped[int] = mapped_column(ForeignKey("locationtypes.id")) name: Mapped[str] capacity: Mapped[int] class ItemBatch(Base): __tablename__ = "batches" id: Mapped[int] = mapped_column(primary_key=True) lot: Mapped[str] = mapped_column(String(128), nullable=False) order: Mapped[str] = mapped_column(ForeignKey("orders.id"), nullable=True) received: Mapped[datetime] = mapped_column(nullable=True) unit_cost: Mapped[Decimal] = mapped_column(Numeric(9, 2), nullable=False) price: Mapped[Decimal] = mapped_column(Numeric(9, 2), nullable=False) best_until: Mapped[datetime] quantity: Mapped[int] sku: Mapped[id] = mapped_column(ForeignKey("items.sku")) item: Mapped[Item] = relationship() class Discount(Base): __tablename__ = "discounts" id: Mapped[int] = mapped_column(primary_key=True) name: Mapped[str] = mapped_column(unique=True, nullable=False) definition: Mapped[Dict[str, Dict[str, int]]] = mapped_column(JSON, nullable=True) def __repr__(self) -> str: return f"Type: {self.name} at {id(self)}" class TaskOwner(Base): __tablename__ = "taskowners" id: Mapped[int] = mapped_column(primary_key=True) name: Mapped[str] = mapped_column(unique=True, nullable=False) class Task(Base): __tablename__ = "tasks" id: Mapped[int] = mapped_column(primary_key=True) taskowner: Mapped[int] = mapped_column(ForeignKey("taskowners.id"), nullable=False) location: Mapped[int] = mapped_column(ForeignKey("locations.id"), nullable=False) sku: Mapped[int] = mapped_column(ForeignKey("items.sku"), nullable=False) description: Mapped[str] class Customer(Base): __tablename__ = "customers" id: Mapped[int] = mapped_column(primary_key=True) document: Mapped[str] = mapped_column(nullable=False) info: Mapped[Dict[str, str]] = mapped_column(JSON, nullable=True) class Cart(Base): __tablename__ = "carts" id: Mapped[int] = mapped_column(primary_key=True) checkout: Mapped[datetime] = mapped_column(nullable=True) location: Mapped[int] = mapped_column(ForeignKey("locations.id"), nullable=False) customer: Mapped[int] = mapped_column(ForeignKey("customers.id"), nullable=True) class ItemOnCart(Base): __tablename__ = "itemsoncart" id: Mapped[int] = mapped_column(primary_key=True) cart: Mapped[int] = mapped_column(ForeignKey("carts.id"), nullable=False) upc: Mapped[int] = mapped_column(nullable=False) # Not FK to avoid sync issues quantity: Mapped[int] = mapped_column(nullable=True) unitprice: Mapped[Decimal] = mapped_column(Numeric(9, 2), nullable=True) discount: Mapped[Decimal] = mapped_column(Numeric(9, 2), nullable=True) class ItemOnShelf(Base): __tablename__ = "itemsonshelf" id: Mapped[int] = mapped_column(primary_key=True) batch: Mapped[int] = mapped_column(ForeignKey("batches.id"), nullable=True) discount: Mapped[int] = mapped_column(ForeignKey("discounts.id"), nullable=True) quantity: Mapped[int] = mapped_column(nullable=False) location: Mapped[int] = mapped_column(ForeignKey("locations.id"), nullable=False) batches: Mapped[ItemBatch] = relationship()