186 lines
6.5 KiB
Python
186 lines
6.5 KiB
Python
import traceback
|
|
import uuid
|
|
|
|
from datetime import datetime, timedelta
|
|
from decimal import Decimal
|
|
|
|
import barker.schemas.voucher as schemas
|
|
|
|
from fastapi import APIRouter, HTTPException, Security, status
|
|
from sqlalchemy import and_, func, or_, select
|
|
from sqlalchemy.exc import SQLAlchemyError
|
|
from sqlalchemy.orm import Session
|
|
|
|
from ...core.config import settings
|
|
from ...core.security import get_current_active_user as get_user
|
|
from ...db.session import SessionFuture
|
|
from ...models.guest_book import GuestBook
|
|
from ...models.inventory import Inventory
|
|
from ...models.inventory_modifier import InventoryModifier
|
|
from ...models.kot import Kot
|
|
from ...models.product_version import ProductVersion
|
|
from ...models.voucher import Voucher
|
|
from ...models.voucher_type import VoucherType
|
|
from ...printing.bill import print_bill
|
|
from ...printing.kot import print_kot
|
|
from ...routers.voucher import (
|
|
check_permissions,
|
|
do_update_bill_numbers,
|
|
do_update_settlements,
|
|
do_update_table,
|
|
get_guest_book,
|
|
get_tax,
|
|
happy_hour_has_discount,
|
|
happy_hour_items_balanced,
|
|
)
|
|
from ...schemas.user_token import UserToken
|
|
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
@router.post("/save")
|
|
def save(
|
|
data: schemas.VoucherIn,
|
|
u: bool, # Update table?
|
|
p: int, # Print type
|
|
g: uuid.UUID | None = None, # Guest book id
|
|
user: UserToken = Security(get_user),
|
|
):
|
|
try:
|
|
with SessionFuture() as db:
|
|
update_table = u
|
|
voucher_type = VoucherType(p)
|
|
guest_book = get_guest_book(g, db)
|
|
item: Voucher = do_save(data, voucher_type, guest_book, db, user)
|
|
need_to_print_kot = sum(len(k.inventories) for k in item.kots) > 0
|
|
if update_table:
|
|
do_update_table(item, guest_book, db)
|
|
db.commit()
|
|
voucher_id = item.id
|
|
with SessionFuture() as db:
|
|
if need_to_print_kot:
|
|
print_kot(voucher_id, db)
|
|
if need_to_print_kot and item.voucher_type != VoucherType.KOT:
|
|
print_bill(voucher_id, db)
|
|
except SQLAlchemyError as e:
|
|
traceback.print_exc()
|
|
raise HTTPException(
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
detail=str(e),
|
|
)
|
|
|
|
|
|
def do_save(
|
|
data: schemas.VoucherIn,
|
|
voucher_type: VoucherType,
|
|
guest_book: GuestBook | None,
|
|
db: Session,
|
|
user: UserToken,
|
|
):
|
|
now = datetime.utcnow()
|
|
product_date = (now + timedelta(minutes=settings.TIMEZONE_OFFSET_MINUTES - settings.NEW_DAY_OFFSET_MINUTES)).date()
|
|
check_permissions(None, voucher_type, user.permissions)
|
|
|
|
kot_id = db.execute(select(func.coalesce(func.max(Voucher.kot_id), 0) + 1)).scalar_one()
|
|
|
|
item = Voucher(
|
|
now,
|
|
guest_book.pax if guest_book is not None else data.pax,
|
|
kot_id,
|
|
data.table.id_,
|
|
data.customer.id_ if data.customer is not None else None,
|
|
voucher_type,
|
|
user.id_,
|
|
)
|
|
db.add(item)
|
|
for dk in data.kots:
|
|
# Filter out nil inventories
|
|
dk.inventories = [dki for dki in dk.inventories if round(dki.quantity, 2) != 0]
|
|
# Filter out nil kots
|
|
data.kots = [k for k in data.kots if len(k.inventories) > 0]
|
|
for k in data.kots:
|
|
if not happy_hour_items_balanced(k.inventories):
|
|
raise HTTPException(
|
|
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
|
detail="Happy hour products are not balanced.",
|
|
)
|
|
if happy_hour_has_discount(k.inventories):
|
|
raise HTTPException(
|
|
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
|
detail="Discount is not allowed on happy hour products.",
|
|
)
|
|
code = db.execute(select(func.coalesce(func.max(Kot.code), 0) + 1)).scalar_one()
|
|
kot = Kot(item.id, code, item.food_table_id, item.date, item.user_id)
|
|
item.kots.append(kot)
|
|
db.add(kot)
|
|
for index, i in enumerate(k.inventories):
|
|
if round(i.quantity, 2) == 0:
|
|
continue
|
|
total_quantity: Decimal = round(
|
|
Decimal(
|
|
sum(inv.quantity for ko in data.kots for inv in ko.inventories if inv.product.id_ == i.product.id_)
|
|
),
|
|
2,
|
|
)
|
|
product: ProductVersion = db.execute(
|
|
select(ProductVersion).where(
|
|
and_(
|
|
ProductVersion.product_id == i.product.id_,
|
|
or_(
|
|
ProductVersion.valid_from == None, # noqa: E711
|
|
ProductVersion.valid_from <= product_date,
|
|
),
|
|
or_(
|
|
ProductVersion.valid_till == None, # noqa: E711
|
|
ProductVersion.valid_till >= product_date,
|
|
),
|
|
)
|
|
)
|
|
).scalar_one()
|
|
if total_quantity < 0:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
|
detail=f"Quantity of {product.full_name} cannot be less than 0",
|
|
)
|
|
if round(i.quantity, 2) < 0:
|
|
if "edit-printed-product" not in user.permissions:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_403_FORBIDDEN,
|
|
detail=f"You are not allowed to delete printed products."
|
|
f"\n In this case {product.full_name}",
|
|
)
|
|
tax_rate = get_tax(product.sale_category.tax.rate, voucher_type)
|
|
inv = Inventory(
|
|
kot.id,
|
|
product.product_id,
|
|
round(i.quantity, 2),
|
|
product.price,
|
|
round(min(i.discount, product.sale_category.discount_limit), 5),
|
|
i.is_happy_hour,
|
|
product.sale_category.tax_id,
|
|
tax_rate,
|
|
index,
|
|
)
|
|
kot.inventories.append(inv)
|
|
db.add(inv)
|
|
for m in i.modifiers:
|
|
mod = InventoryModifier(None, m.id_, Decimal(0))
|
|
inv.modifiers.append(mod)
|
|
db.add(mod)
|
|
db.flush()
|
|
do_update_settlements(item, [], db)
|
|
do_update_bill_numbers(item, db)
|
|
|
|
if (
|
|
sum(len(k.inventories) for k in item.kots) == 0
|
|
and guest_book is None
|
|
and data.pax == 0
|
|
and data.customer is None
|
|
):
|
|
raise HTTPException(
|
|
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
|
detail="Please add some products",
|
|
)
|
|
return item
|