barker/barker/barker/models/voucher.py

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)