barker/barker/barker/routers/voucher/change.py

106 lines
3.2 KiB
Python

import uuid
from typing import Optional
import barker.schemas.voucher as schemas
from fastapi import APIRouter, Depends, HTTPException, Security, status
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 SessionLocal
from ...models.overview import Overview
from ...models.reprint import Reprint
from ...models.settle_option import SettleOption
from ...models.voucher import Voucher
from ...models.voucher_type import VoucherType
from ...printing.bill import print_bill
from ...routers.voucher import do_update_settlements, get_guest_book
from ...schemas.receive_payment import ReceivePaymentItem as SettleSchema
from ...schemas.user_token import UserToken
from .save import do_save
router = APIRouter()
# Dependency
def get_db():
try:
db = SessionLocal()
yield db
finally:
db.close()
@router.put("/change/{id_}")
def change(
id_: uuid.UUID,
data: schemas.VoucherIn,
u: bool, # Update table?
g: Optional[uuid.UUID] = None, # Guest book id
db: Session = Depends(get_db),
user: UserToken = Security(get_user, scopes=["edit-printed-bill"]),
):
try:
old: Voucher = db.query(Voucher).filter(Voucher.id == id_).first()
if old.voucher_type == VoucherType.VOID:
raise HTTPException(
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
detail="Voucher cannot be reprinted. It is already void.",
)
bill_changed: bool = (
len(
set((i.id, i.amount) for k in old.kots for i in k.inventories)
^ set((i.id_, i.amount) for k in data.kots for i in k.inventories)
)
!= 0
)
if bill_changed:
id_ = void_and_issue_new_bill(data, u, g, old, db, user)
else:
reprint_bill(id_, user.id_, db)
db.commit()
print_bill(id_, db)
except SQLAlchemyError as e:
db.rollback()
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=str(e),
)
except Exception:
db.rollback()
raise
def reprint_bill(voucher_id: uuid.UUID, user_id: uuid.UUID, db: Session):
item = Reprint(voucher_id=voucher_id, user_id=user_id)
db.add(item)
def void_and_issue_new_bill(
data: schemas.VoucherIn,
u: bool,
g: Optional[uuid.UUID],
old: Voucher,
db: Session,
user: UserToken,
) -> uuid.UUID:
update_table = u
guest_book = get_guest_book(g, db)
item: Voucher = do_save(data, old.voucher_type, guest_book, db, user)
db.flush()
old.bill_id = None
old.voucher_type = VoucherType.VOID
old.reason = f"Bill Discounted / Changed. New Bill ID is {item.full_bill_id}"
do_update_settlements(old, [SettleSchema(id=SettleOption.VOID(), amount=round(old.amount))], db)
if update_table:
if old.status is None:
item.status = Overview(voucher_id=None, food_table_id=item.food_table_id, status="printed")
db.add(item.status)
else:
db.query(Overview).filter(Overview.voucher_id == old.id).update({Overview.voucher_id: item.id})
return item.id