PyConES24/src/retailtwin/models.py
2024-05-08 21:55:08 +00:00

161 lines
5.5 KiB
Python

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"<Provider ({self.name}) at {hex(id(self))}>"
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"<Item {self.name} at {hex(id(self))}>"
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()