207 lines
8.3 KiB
Python
207 lines
8.3 KiB
Python
import traceback
|
|
import uuid
|
|
|
|
from datetime import datetime
|
|
|
|
import barker.schemas.merge_move as schemas
|
|
|
|
from fastapi import APIRouter, HTTPException, Security, status
|
|
from sqlalchemy import delete, func, select, update
|
|
from sqlalchemy.exc import SQLAlchemyError
|
|
from sqlalchemy.orm import Session
|
|
|
|
from ...core.security import get_current_active_user as get_user
|
|
from ...db.session import SessionFuture
|
|
from ...models.bill import Bill
|
|
from ...models.kot import Kot
|
|
from ...models.overview import Overview
|
|
from ...models.settlement import Settlement
|
|
from ...models.voucher import Voucher
|
|
from ...models.voucher_type import VoucherType
|
|
from ...routers.voucher import (
|
|
do_update_bill_numbers,
|
|
do_update_settlements,
|
|
do_update_table,
|
|
)
|
|
from ...schemas.user_token import UserToken
|
|
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
@router.post("/move-kot/merge")
|
|
def merge_kot(
|
|
data: schemas.MergeKot,
|
|
user: UserToken = Security(get_user, scopes=["merge-kots"]),
|
|
):
|
|
try:
|
|
with SessionFuture() as db:
|
|
check_if_voucher_is_unprinted(data.voucher_id, db)
|
|
kots: int = db.execute(select(func.count(Kot.id)).where(Kot.voucher_id == data.voucher_id)).scalar_one()
|
|
if kots <= 1:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
detail="Single kot cannot be used, move table instead. This error should not show up in frontend",
|
|
)
|
|
check_if_voucher_is_unprinted(data.new_voucher_id, db)
|
|
|
|
db.execute(
|
|
update(Kot)
|
|
.where(Kot.id == data.kot_id, Kot.voucher_id == data.voucher_id)
|
|
.values(voucher_id=data.new_voucher_id)
|
|
)
|
|
donor: Voucher = db.execute(select(Voucher).where(Voucher.id == data.voucher_id)).scalar_one()
|
|
recipent: Voucher = db.execute(select(Voucher).where(Voucher.id == data.new_voucher_id)).scalar_one()
|
|
if has_negatives(donor.kots) or happy_hour_exceeds_regular(donor.kots):
|
|
raise HTTPException(
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
detail="Donor voucher will have negative products or too many happy hours",
|
|
)
|
|
if has_negatives(recipent.kots) or happy_hour_exceeds_regular(recipent.kots):
|
|
raise HTTPException(
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
detail="Recipient voucher will have negative products or too many happy hours",
|
|
)
|
|
do_update_settlements(donor, [], db)
|
|
do_update_settlements(recipent, [], db)
|
|
db.commit()
|
|
except SQLAlchemyError as e:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
detail=str(e),
|
|
)
|
|
|
|
|
|
@router.post("/move-kot/move")
|
|
def move_kot(
|
|
data: schemas.MoveKot,
|
|
user: UserToken = Security(get_user, scopes=["move-kot-to-new-table"]),
|
|
):
|
|
try:
|
|
with SessionFuture() as db:
|
|
now = datetime.utcnow()
|
|
check_if_voucher_is_unprinted(data.voucher_id, db)
|
|
kots: int = db.execute(select(func.count(Kot.id)).where(Kot.voucher_id == data.voucher_id)).scalar_one()
|
|
if kots <= 1:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
detail="Single kot cannot be used, move table instead. This error should not show up in frontend",
|
|
)
|
|
kot = db.execute(select(Kot).where(Kot.id == data.kot_id)).scalar_one()
|
|
kot_id = db.execute(select(func.coalesce(func.max(Voucher.kot_id), 0) + 1)).scalar_one()
|
|
|
|
item = Voucher(
|
|
now,
|
|
kot.voucher.pax,
|
|
kot_id,
|
|
data.table_id,
|
|
kot.voucher.customer_id if kot.voucher.customer is not None else None,
|
|
kot.voucher.voucher_type,
|
|
user.id_,
|
|
)
|
|
db.add(item)
|
|
item.kots.append(kot)
|
|
db.flush()
|
|
do_update_bill_numbers(item, db)
|
|
do_update_table(item, None, db)
|
|
donor: Voucher = db.execute(select(Voucher).where(Voucher.id == data.voucher_id)).scalar_one()
|
|
if has_negatives(donor.kots) or happy_hour_exceeds_regular(donor.kots):
|
|
raise HTTPException(
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
detail="Donor voucher will have negative products or too many happy hours",
|
|
)
|
|
if has_negatives(item.kots) or happy_hour_exceeds_regular(item.kots):
|
|
raise HTTPException(
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
detail="Recipient voucher will have negative products or too many happy hours",
|
|
)
|
|
do_update_settlements(donor, [], db)
|
|
do_update_settlements(item, [], db)
|
|
db.commit()
|
|
except SQLAlchemyError as e:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
detail=str(e),
|
|
)
|
|
|
|
|
|
@router.post("/move-table/move")
|
|
def move_table(
|
|
data: schemas.MoveTable,
|
|
user: UserToken = Security(get_user, scopes=["move-table"]),
|
|
):
|
|
try:
|
|
with SessionFuture() as db:
|
|
db.execute(
|
|
update(Overview).where(Overview.voucher_id == data.voucher_id).values(food_table_id=data.table_id)
|
|
)
|
|
db.execute(update(Voucher).where(Voucher.id == data.voucher_id).values(food_table_id=data.table_id))
|
|
db.commit()
|
|
except SQLAlchemyError as e:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
detail=str(e),
|
|
)
|
|
|
|
|
|
@router.post("/move-table/merge")
|
|
def merge_table(
|
|
data: schemas.MergeTable,
|
|
user: UserToken = Security(get_user, scopes=["merge-tables"]),
|
|
):
|
|
try:
|
|
with SessionFuture() as db:
|
|
check_if_voucher_is_unprinted(data.voucher_id, db)
|
|
check_if_voucher_is_unprinted(data.new_voucher_id, db)
|
|
db.execute(update(Kot).where(Kot.voucher_id == data.voucher_id).values(voucher_id=data.new_voucher_id))
|
|
db.execute(delete(Bill).where(Bill.voucher_id == data.voucher_id))
|
|
db.execute(delete(Overview).where(Overview.voucher_id == data.voucher_id))
|
|
db.execute(delete(Settlement).where(Settlement.voucher_id == data.voucher_id))
|
|
db.execute(delete(Voucher).where(Voucher.id == data.voucher_id))
|
|
recipent: Voucher = db.execute(select(Voucher).where(Voucher.id == data.new_voucher_id)).scalar_one()
|
|
do_update_settlements(recipent, [], db)
|
|
db.commit()
|
|
except SQLAlchemyError as e:
|
|
traceback.print_exc()
|
|
raise HTTPException(
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
detail=str(e),
|
|
)
|
|
|
|
|
|
def check_if_voucher_is_unprinted(voucher_id: uuid.UUID, db: Session) -> None:
|
|
voucher_type: VoucherType = db.execute(select(Voucher.voucher_type).where(Voucher.id == voucher_id)).scalar_one()
|
|
if voucher_type is None:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail="Original bill not found",
|
|
)
|
|
if voucher_type != VoucherType.KOT:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_403_FORBIDDEN,
|
|
detail="Bill is printed or void.",
|
|
)
|
|
|
|
|
|
def has_negatives(kots: list[Kot]) -> bool:
|
|
inv = [i for k in kots for i in k.inventories]
|
|
products = set((i.product_id, i.is_happy_hour) for i in inv)
|
|
for id_, hh in products:
|
|
quantity = sum(i.quantity for i in inv if i.product_id == id_ and i.is_happy_hour == hh)
|
|
if quantity < 0:
|
|
return True
|
|
return False
|
|
|
|
|
|
# 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_exceeds_regular(kots: list[Kot]) -> bool:
|
|
inv = [i for k in kots for i in k.inventories]
|
|
products = set(i.product_id for i in inv if i.is_happy_hour)
|
|
for p in products:
|
|
r = sum(i.quantity for i in inv if i.product_id == p and not i.is_happy_hour)
|
|
h = sum(i.quantity for i in inv if i.product_id == p and i.is_happy_hour)
|
|
if r < h:
|
|
return True
|
|
return False
|