barker/barker/barker/models/inventory.py

105 lines
3.1 KiB
Python

import uuid
from decimal import Decimal
from barker.models.meta import Base
from barker.models.product import Product
from sqlalchemy import (
Boolean,
Column,
ForeignKey,
Integer,
Numeric,
UniqueConstraint,
case,
func,
text,
)
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.ext.hybrid import hybrid_property
from sqlalchemy.orm import relationship
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, server_default=text("gen_random_uuid()"), 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(precision=15, scale=2))
price = Column("price", Numeric(precision=15, scale=2))
is_happy_hour = Column("is_happy_hour", Boolean, nullable=False)
tax_rate = Column("tax_rate", Numeric(precision=15, scale=5))
tax_id = Column("tax_id", UUID(as_uuid=True), ForeignKey("taxes.id"), nullable=False)
discount = Column("discount", Numeric(precision=15, scale=5))
sort_order = Column("sort_order", Integer, nullable=False)
kot = relationship("Kot", back_populates="inventories")
tax = relationship("Tax", foreign_keys=tax_id)
product = relationship("ProductVersion", secondary=Product.__table__, back_populates="inventories", viewonly=True)
def __init__(
self,
kot_id,
product_id,
quantity,
price,
discount,
is_hh,
tax_id,
tax_rate,
sort_order,
product=None,
tax=None,
):
self.kot_id = kot_id
if product_id is not None:
self.product_id = product_id
self.quantity = quantity
self.price = price
self.discount = discount
self.is_happy_hour = is_hh
if tax_id is not None:
self.tax_id = tax_id
self.tax_rate = tax_rate
self.sort_order = sort_order
if product is not None:
self.product = product
if tax is not None:
self.tax = tax
@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) # noqa: E712
@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 round(Decimal(self.net * (1 + self.tax_rate)), 2)
@amount.expression
def amount(cls):
return func.round(cls.net * (1 + cls.tax_rate), 2)