284 lines
10 KiB
Python
284 lines
10 KiB
Python
from datetime import datetime
|
|
from enum import Enum
|
|
import uuid
|
|
from decimal import Decimal
|
|
|
|
from sqlalchemy.ext.hybrid import hybrid_property
|
|
from sqlalchemy import (
|
|
Column,
|
|
Integer,
|
|
Boolean,
|
|
Unicode,
|
|
DateTime,
|
|
Numeric,
|
|
ForeignKey,
|
|
UniqueConstraint,
|
|
case,
|
|
)
|
|
from sqlalchemy.orm import relationship, backref, synonym
|
|
from sqlalchemy.dialects.postgresql import UUID
|
|
from .meta import Base
|
|
|
|
|
|
class VoucherType(Enum):
|
|
KOT = 0
|
|
REGULAR_BILL = 1
|
|
NO_CHARGE = 2
|
|
STAFF = 4
|
|
VOID = 5
|
|
|
|
|
|
class GuestBook(Base):
|
|
__tablename__ = "guest_book"
|
|
id = Column("id", UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
|
customer_id = Column("customer_id", UUID(as_uuid=True), ForeignKey("customers.id"), nullable=False)
|
|
pax = Column("pax", Numeric, nullable=False)
|
|
date = Column("creation_date", DateTime(timezone=True), nullable=False)
|
|
|
|
customer = relationship("Customer")
|
|
|
|
def __init__(self, pax=None, id_=None, customer_id=None, customer=None):
|
|
self.customer_id = customer_id
|
|
self.pax = pax
|
|
self.id = id_
|
|
self.date = datetime.utcnow()
|
|
if customer is None:
|
|
self.customer_id = customer_id
|
|
else:
|
|
self.customer = customer
|
|
|
|
|
|
|
|
class Overview(Base):
|
|
__tablename__ = "overview"
|
|
id = Column("id", UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
|
voucher_id = Column("voucher_id", UUID(as_uuid=True), ForeignKey("vouchers.id"), nullable=False, unique=True)
|
|
food_table_id = Column("food_table_id", UUID(as_uuid=True), ForeignKey("food_tables.id"), nullable=False, unique=True,)
|
|
guest_book_id = Column("guest_book_id", UUID(as_uuid=True), ForeignKey("guest_book.id"), unique=True)
|
|
status = Column("status", Unicode(255), nullable=False)
|
|
|
|
voucher = relationship("Voucher", backref=backref("status", uselist=False))
|
|
food_table = relationship("FoodTable", backref=backref("status", uselist=False))
|
|
guest = relationship("GuestBook", backref=backref("status", uselist=False))
|
|
|
|
def __init__(self, voucher_id, food_table_id, guest_book_id, status, id_=None):
|
|
self.voucher_id = voucher_id
|
|
self.food_table_id = food_table_id
|
|
self.guest_book_id = guest_book_id
|
|
self.status = status
|
|
self.id = id_
|
|
|
|
|
|
class InventoryModifier(Base):
|
|
__tablename__ = "inventory_modifiers"
|
|
__table_args__ = (UniqueConstraint("inventory_id", "modifier_id"),)
|
|
|
|
id = Column("id", UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
|
inventory_id = Column("inventory_id", UUID(as_uuid=True), ForeignKey("inventories.id"), nullable=False)
|
|
modifier_id = Column("modifier_id", UUID(as_uuid=True), ForeignKey("modifiers.id"), nullable=False)
|
|
price = Column("price", Numeric, nullable=False)
|
|
|
|
inventory = relationship("Inventory", backref="modifiers")
|
|
modifier = relationship("Modifier")
|
|
|
|
def __init__(self, inventory_id, modifier_id, price):
|
|
self.inventory_id = inventory_id
|
|
self.modifier_id = modifier_id
|
|
self.price = price
|
|
|
|
|
|
class Voucher(Base):
|
|
__tablename__ = "vouchers"
|
|
__table_args__ = (UniqueConstraint("bill_id", "voucher_type"),)
|
|
|
|
id = Column("id", UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
|
date = Column("date", DateTime, nullable=False, index=True)
|
|
pax = Column("pax", Numeric, nullable=False)
|
|
bill_id = Column("bill_id", Numeric)
|
|
kot_id = Column("kot_id", Numeric, nullable=False, unique=True)
|
|
creation_date = Column("creation_date", DateTime(timezone=True), nullable=False)
|
|
last_edit_date = Column("last_edit_date", DateTime(timezone=True), nullable=False)
|
|
food_table_id = Column("food_table_id", UUID(as_uuid=True), ForeignKey("food_tables.id"), nullable=False)
|
|
customer_id = Column("customer_id", UUID(as_uuid=True), ForeignKey("customers.id"))
|
|
narration = Column("narration", Unicode(1000), nullable=False)
|
|
reason = Column("reason", Unicode(255))
|
|
_voucher_type = Column("voucher_type", Integer, nullable=False)
|
|
user_id = Column("user_id", UUID(as_uuid=True), ForeignKey("users.id"), nullable=False)
|
|
|
|
user = relationship("User", backref="vouchers")
|
|
food_table = relationship("FoodTable", backref="vouchers")
|
|
customer = relationship("Customer", backref="vouchers")
|
|
|
|
kots = relationship("Kot", backref="voucher", cascade="delete, delete-orphan", cascade_backrefs=False,)
|
|
settlements = relationship(
|
|
"Settlement", backref="voucher", cascade="delete, delete-orphan", cascade_backrefs=False,
|
|
)
|
|
reprints = relationship("Reprint", backref="voucher", cascade="delete, delete-orphan", cascade_backrefs=False,)
|
|
|
|
def _get_voucher_type(self):
|
|
return VoucherType(self._voucher_type)
|
|
|
|
def _set_voucher_type(self, voucher_type):
|
|
self._voucher_type = voucher_type.value
|
|
|
|
voucher_type = property(_get_voucher_type, _set_voucher_type)
|
|
voucher_type = synonym("_voucher_type", descriptor=voucher_type)
|
|
|
|
def __init__(
|
|
self, date, pax, bill_id, kot_id, food_table_id, customer_id, voucher_type, user_id,
|
|
):
|
|
self.date = date
|
|
self.pax = pax
|
|
self.creation_date = date
|
|
self.last_edit_date = date
|
|
self.bill_id = bill_id
|
|
self.kot_id = kot_id
|
|
self.food_table_id = food_table_id
|
|
self.customer_id = customer_id
|
|
self.narration = ""
|
|
self.voucher_type = voucher_type
|
|
self.user_id = user_id
|
|
|
|
@property
|
|
def full_bill_id(self):
|
|
if self.voucher_type == VoucherType.KOT:
|
|
return "K-" + str(self.kot_id)
|
|
if self.voucher_type == VoucherType.NO_CHARGE:
|
|
return "NC-" + str(self.bill_id)
|
|
if self.voucher_type == VoucherType.STAFF:
|
|
return "ST-" + str(self.bill_id)
|
|
if self.voucher_type == VoucherType.REGULAR_BILL:
|
|
return str(self.bill_id // 10000) + "-" + str(self.bill_id % 10000)
|
|
if self.voucher_type == VoucherType.VOID:
|
|
return "K-" + str(self.kot_id)
|
|
else:
|
|
raise Exception
|
|
|
|
@property
|
|
def amount(self):
|
|
return round(sum(i.amount for k in self.kots for i in k.inventories), 2)
|
|
|
|
|
|
class Kot(Base):
|
|
__tablename__ = "kots"
|
|
|
|
id = Column("id", UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
|
voucher_id = Column("voucher_id", UUID(as_uuid=True), ForeignKey("vouchers.id"), nullable=False, index=True)
|
|
code = Column("code", Numeric, nullable=False, unique=True)
|
|
food_table_id = Column("food_table_id", UUID(as_uuid=True), ForeignKey("food_tables.id"), nullable=False)
|
|
date = Column("date", DateTime, nullable=False, index=True)
|
|
user_id = Column("user_id", UUID(as_uuid=True), ForeignKey("users.id"), nullable=False)
|
|
|
|
user = relationship("User", backref="kots")
|
|
food_table = relationship("FoodTable", backref="kots")
|
|
|
|
def __init__(
|
|
self, voucher_id=None, code=None, food_table_id=None, date=None, user_id=None, id_=None,
|
|
):
|
|
self.id = id_
|
|
self.voucher_id = voucher_id
|
|
self.code = code
|
|
self.food_table_id = food_table_id
|
|
self.date = date
|
|
self.user_id = user_id
|
|
|
|
|
|
class Settlement(Base):
|
|
__tablename__ = "settlements"
|
|
__table_args__ = (UniqueConstraint("voucher_id", "settled"),)
|
|
|
|
id = Column("id", UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
|
voucher_id = Column("voucher_id", UUID(as_uuid=True), ForeignKey("vouchers.id"), nullable=False, index=True)
|
|
settled = Column("settled", ForeignKey("settle_options.id"), nullable=False)
|
|
amount = Column("amount", Numeric, nullable=False)
|
|
|
|
settle_option = relationship("SettleOption")
|
|
|
|
def __init__(self, voucher_id=None, settled=None, amount=None, id_=None):
|
|
self.id = id_
|
|
self.voucher_id = voucher_id
|
|
self.settled = settled
|
|
self.amount = amount
|
|
|
|
|
|
class Reprint(Base):
|
|
__tablename__ = "reprints"
|
|
|
|
id = Column("id", UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
|
date = Column("date", DateTime, nullable=False, index=True)
|
|
voucher_id = Column("voucher_id", UUID(as_uuid=True), ForeignKey("vouchers.id"), nullable=False, index=True)
|
|
user_id = Column("user_id", UUID(as_uuid=True), ForeignKey("users.id"), nullable=False)
|
|
|
|
user = relationship("User", backref="reprints")
|
|
|
|
def __init__(self, voucher_id=None, user_id=None, id_=None):
|
|
self.id = id_
|
|
self.date = datetime.now()
|
|
self.voucher_id = voucher_id
|
|
self.user_id = user_id
|
|
|
|
|
|
class Inventory(Base):
|
|
__tablename__ = "inventories"
|
|
__table_args__ = (UniqueConstraint("kot_id", "product_id", "is_happy_hour", "price"),)
|
|
|
|
id = Column("id", UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
|
kot_id = Column("kot_id", UUID(as_uuid=True), ForeignKey("kots.id"), nullable=False, index=True)
|
|
product_id = Column("product_id", UUID(as_uuid=True), ForeignKey("products.id"), nullable=False)
|
|
quantity = Column("quantity", Numeric)
|
|
price = Column("price", Numeric)
|
|
is_happy_hour = Column("is_happy_hour", Boolean, nullable=False)
|
|
tax_rate = Column("tax_rate", Numeric)
|
|
tax_id = Column("tax_id", UUID(as_uuid=True), ForeignKey("taxes.id"), nullable=False)
|
|
discount = Column("discount", Numeric)
|
|
sort_order = Column("sort_order", Numeric, nullable=False)
|
|
|
|
kot = relationship("Kot", backref="inventories")
|
|
tax = relationship("Tax", foreign_keys=tax_id)
|
|
product = relationship("Product", backref="inventories")
|
|
|
|
def __init__(
|
|
self, kot_id, product_id, quantity, price, discount, is_hh, tax_id, tax_rate, sort_order,
|
|
):
|
|
self.kot_id = kot_id
|
|
self.product_id = product_id
|
|
self.quantity = quantity
|
|
self.price = price
|
|
self.discount = discount
|
|
self.is_happy_hour = is_hh
|
|
self.tax_id = tax_id
|
|
self.tax_rate = tax_rate
|
|
self.sort_order = sort_order
|
|
|
|
@hybrid_property
|
|
def effective_price(self):
|
|
return 0 if self.is_happy_hour else self.price
|
|
|
|
@effective_price.expression
|
|
def effective_price(cls):
|
|
return case([(cls.is_happy_hour == True, 0)], else_=cls.price)
|
|
|
|
@hybrid_property
|
|
def net(self):
|
|
return self.effective_price * self.quantity * (1 - self.discount)
|
|
|
|
@net.expression
|
|
def net(cls):
|
|
return cls.effective_price * cls.quantity * (1 - cls.discount)
|
|
|
|
@hybrid_property
|
|
def tax_amount(self):
|
|
return self.net * self.tax_rate
|
|
|
|
@tax_amount.expression
|
|
def tax_amount(cls):
|
|
return cls.net * cls.tax_rate
|
|
|
|
@hybrid_property
|
|
def amount(self):
|
|
return Decimal(self.net * (1 + self.tax_rate))
|
|
|
|
@amount.expression
|
|
def amount(cls):
|
|
return cls.net * (1 + cls.tax_rate)
|