182 lines
6.9 KiB
Python
182 lines
6.9 KiB
Python
import uuid
|
|
|
|
from decimal import Decimal
|
|
from typing import Set
|
|
|
|
import barker.schemas.voucher as schemas
|
|
|
|
from fastapi import HTTPException, status
|
|
from sqlalchemy import func
|
|
from sqlalchemy.orm import Session
|
|
from sqlalchemy.sql import expression
|
|
|
|
from ...models.bill import Bill
|
|
from ...models.guest_book import GuestBook
|
|
from ...models.overview import Overview
|
|
from ...models.regime import Regime
|
|
from ...models.settle_option import SettleOption
|
|
from ...models.settlement import Settlement
|
|
from ...models.voucher import Voucher
|
|
from ...models.voucher_type import VoucherType
|
|
from ...schemas.receive_payment import ReceivePaymentItem as SettleSchema
|
|
|
|
|
|
def get_tax(tax, voucher_type):
|
|
if voucher_type in [VoucherType.STAFF, VoucherType.NO_CHARGE]:
|
|
return 0
|
|
elif voucher_type in [VoucherType.KOT, VoucherType.REGULAR_BILL]:
|
|
return tax
|
|
else:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
|
detail="Unexpected Voucher Type",
|
|
)
|
|
|
|
|
|
def do_update_table(item: Voucher, guest_book: GuestBook | None, db: Session):
|
|
status_ = "running" if item.voucher_type == VoucherType.KOT else "printed"
|
|
if item.status is None:
|
|
item.status = Overview(
|
|
voucher_id=item.id,
|
|
food_table_id=item.food_table_id,
|
|
guest_book_id=guest_book.id if guest_book is not None else None,
|
|
status=status_,
|
|
)
|
|
db.add(item.status)
|
|
else:
|
|
item.status.status = status_
|
|
if guest_book is not None:
|
|
item.status.guest_book_id = guest_book.id
|
|
|
|
|
|
def check_permissions(item: Voucher | None, voucher_type: VoucherType, permissions: list[str]):
|
|
if voucher_type == VoucherType.KOT and "print-kot" not in permissions:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_403_FORBIDDEN,
|
|
detail="You are not allowed to print a kot",
|
|
)
|
|
if voucher_type != VoucherType.KOT and "print-bill" not in permissions:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_403_FORBIDDEN,
|
|
detail="You are not allowed to print bill",
|
|
)
|
|
|
|
if item is None:
|
|
return
|
|
if item.voucher_type != VoucherType.KOT and "edit-printed-bill" not in permissions:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_403_FORBIDDEN,
|
|
detail="You are not allowed to edit a printed bill",
|
|
)
|
|
|
|
if item.voucher_type != VoucherType.KOT and voucher_type == VoucherType.KOT:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_403_FORBIDDEN,
|
|
detail="This Bill is already printed\nCannot add a Kot to it.",
|
|
)
|
|
|
|
if item.voucher_type == VoucherType.VOID:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_403_FORBIDDEN,
|
|
detail=f"This Bill is already void.\nReason: {item.reason}",
|
|
)
|
|
|
|
|
|
def get_guest_book(id_: uuid.UUID | None, db: Session) -> GuestBook | None:
|
|
if id_ is None:
|
|
return id_
|
|
return db.execute(expression.select(GuestBook).where(GuestBook.id == id_)).scalar_one()
|
|
|
|
|
|
def do_update_settlements(voucher: Voucher, others: list[SettleSchema], db: Session) -> bool:
|
|
fully_settled = True
|
|
settlements: list[SettleSchema] = []
|
|
settlements += others
|
|
total_amount = voucher.amount
|
|
settlements.append(SettleSchema(id=SettleOption.AMOUNT(), amount=-total_amount))
|
|
round_off = round(total_amount) - total_amount
|
|
if round_off != 0:
|
|
settlements.append(SettleSchema(id=SettleOption.ROUND_OFF(), amount=-round_off))
|
|
unsettled = sum(x.amount for x in settlements)
|
|
if len(others) and unsettled != 0: # This should not be allowed
|
|
raise HTTPException(
|
|
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
|
detail="Payment received is not equal to bill amount",
|
|
)
|
|
if unsettled != 0:
|
|
settlements.append(SettleSchema(id=SettleOption.UNSETTLED(), amount=unsettled))
|
|
fully_settled = False
|
|
|
|
for settlement in settlements:
|
|
old = [vs for vs in voucher.settlements if vs.settled == settlement.id_]
|
|
if len(old) == 1:
|
|
old[0].amount = settlement.amount
|
|
else:
|
|
ns = Settlement(voucher.id, settlement.id_, settlement.amount)
|
|
voucher.settlements.append(ns)
|
|
db.add(ns)
|
|
|
|
for removable in (os for os in voucher.settlements if os.settled not in [x.id_ for x in settlements]):
|
|
voucher.settlements.remove(removable)
|
|
db.delete(removable)
|
|
return fully_settled
|
|
|
|
|
|
def do_update_bill_numbers(voucher: Voucher, db: Session) -> bool:
|
|
regimes: Set[int] = set()
|
|
old_regimes: Set[int] = set()
|
|
old_regimes = set(
|
|
db.execute(expression.select(Bill.regime_id).where(Bill.voucher_id == voucher.id)).scalars().all()
|
|
)
|
|
if voucher.voucher_type != VoucherType.REGULAR_BILL:
|
|
regimes = set([int(voucher.voucher_type)])
|
|
else:
|
|
regimes = set(i.tax.regime.id for k in voucher.kots for i in k.inventories)
|
|
|
|
db.execute(
|
|
expression.update(Bill)
|
|
.where(Bill.voucher_id == voucher.id, Bill.regime_id.in_(old_regimes - regimes))
|
|
.values(is_valid=False)
|
|
)
|
|
if Regime.KOT() not in old_regimes | regimes:
|
|
regimes.add(Regime.KOT())
|
|
for r in regimes - old_regimes:
|
|
bill_id = db.execute(
|
|
expression.select(func.coalesce(func.max(Bill.bill_number), 0) + 1).where(Bill.regime_id == r)
|
|
).scalar_one()
|
|
bill = Bill(regime_id=r, is_valid=True, bill_number=bill_id)
|
|
voucher.bills.append(bill)
|
|
db.add(bill)
|
|
return True
|
|
|
|
|
|
def happy_hour_items_balanced(inventories: list[schemas.Inventory]) -> bool:
|
|
happy = set((i.product.id_, i.quantity) for i in inventories if i.is_happy_hour)
|
|
products = set(i.product.id_ for i in inventories if i.is_happy_hour)
|
|
other = set((i.product.id_, i.quantity) for i in inventories if not i.is_happy_hour and i.product.id_ in products)
|
|
return happy == other
|
|
|
|
|
|
def happy_hour_has_discount(inventories: list[schemas.Inventory]) -> bool:
|
|
happy = set(i.product.id_ for i in inventories if i.is_happy_hour)
|
|
offenders = [i for i in inventories if i.product.id_ in happy and i.discount != 0]
|
|
return len(offenders) > 0
|
|
|
|
|
|
# This is for the whole bill. eg. Kot 1 => Reg 2 + HH 2; Kot 2 => Reg 4; Kot 3 => Reg - 4
|
|
# This is pass okay in happy hours items balanced, but overall this is wrong. Hence this check
|
|
def happy_hour_items_more_than_regular(kots: list[schemas.Kot]) -> bool:
|
|
inventories = {}
|
|
for kot in kots:
|
|
for inventory in kot.inventories:
|
|
if inventory.product.id_ not in inventories:
|
|
inventories[inventory.product.id_] = {"normal": Decimal(0), "happy": Decimal(0)}
|
|
if inventory.is_happy_hour:
|
|
inventories[inventory.product.id_]["happy"] += inventory.quantity
|
|
else:
|
|
inventories[inventory.product.id_]["normal"] += inventory.quantity
|
|
for value in inventories.values():
|
|
if value["happy"] > value["normal"]:
|
|
return True
|
|
return False
|