196 lines
7.2 KiB
Python
196 lines
7.2 KiB
Python
import re
|
|
import uuid
|
|
|
|
from datetime import datetime, timedelta
|
|
|
|
from fastapi import APIRouter, HTTPException, Security, status
|
|
from sqlalchemy import and_, or_, select
|
|
from sqlalchemy.orm import Session, joinedload
|
|
|
|
from ...core.config import settings
|
|
from ...core.security import get_current_active_user as get_user
|
|
from ...db.session import SessionFuture
|
|
from ...models.bill import Bill
|
|
from ...models.food_table import FoodTable
|
|
from ...models.guest_book import GuestBook
|
|
from ...models.overview import Overview
|
|
from ...models.product_version import ProductVersion
|
|
from ...models.regime import Regime
|
|
from ...models.voucher import Voucher
|
|
from ...models.voucher_type import VoucherType
|
|
from ...schemas.user_token import UserToken
|
|
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
@router.get("/from-id/{id_}")
|
|
def from_id(
|
|
id_: str,
|
|
user: UserToken = Security(get_user),
|
|
):
|
|
with SessionFuture() as db:
|
|
item: Voucher = db.execute(select(Voucher).where(Voucher.id == id_)).scalar_one()
|
|
return voucher_info(item, db)
|
|
|
|
|
|
@router.get("/from-bill/{id_}")
|
|
def from_bill(
|
|
id_: str,
|
|
user: UserToken = Security(get_user),
|
|
):
|
|
with SessionFuture() as db:
|
|
match = re.compile(r"^(\w+)-(\d+)$").match(id_)
|
|
if not match or len(match.groups()) != 2:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
|
detail="Bill Number is invalid",
|
|
)
|
|
voucher_id = (
|
|
select(Bill.voucher_id)
|
|
.join(Bill.regime)
|
|
.where(Regime.prefix == match.group(1), Bill.bill_number == int(match.group(2)))
|
|
.options(joinedload(Regime.prefix, innerjoin=True))
|
|
)
|
|
item = db.execute(select(Voucher).where(Voucher.id.in_(voucher_id))).scalars().one_or_none()
|
|
if item is None:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail="Bill not found",
|
|
)
|
|
return voucher_info(item, db)
|
|
|
|
|
|
@router.get("/from-table/{id_}")
|
|
def from_table(
|
|
id_: str, # table id
|
|
v: uuid.UUID | None = None, # voucher id
|
|
g: uuid.UUID | None = None, # guest id
|
|
user: UserToken = Security(get_user),
|
|
):
|
|
with SessionFuture() as db:
|
|
guest = None if g is None else db.execute(select(GuestBook).where(GuestBook.id == g)).scalar_one()
|
|
if v is not None:
|
|
item = (
|
|
db.execute(
|
|
select(Overview).where(
|
|
Overview.voucher_id == v,
|
|
Overview.food_table_id == id_,
|
|
)
|
|
)
|
|
.scalars()
|
|
.one_or_none()
|
|
)
|
|
if item is None:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail="Voucher not found",
|
|
)
|
|
else:
|
|
if guest is not None:
|
|
item.voucher.customer = guest.customer
|
|
return voucher_info(item.voucher, db)
|
|
table = db.execute(select(FoodTable).where(FoodTable.id == id_)).scalar_one()
|
|
return voucher_blank(table, guest)
|
|
|
|
|
|
def voucher_product(product_id: uuid.UUID, date_: datetime, is_happy_hour: bool, db: Session):
|
|
product_date = (
|
|
date_ + timedelta(minutes=settings.TIMEZONE_OFFSET_MINUTES - settings.NEW_DAY_OFFSET_MINUTES)
|
|
).date()
|
|
product: ProductVersion = db.execute(
|
|
select(ProductVersion).where(
|
|
and_(
|
|
ProductVersion.product_id == 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()
|
|
|
|
return {
|
|
"id": product_id,
|
|
"name": ("H H " if is_happy_hour else "") + product.full_name,
|
|
"menuCategory": {
|
|
"id": product.menu_category_id,
|
|
"name": product.menu_category.name,
|
|
},
|
|
"saleCategory": {
|
|
"id": product.sale_category_id,
|
|
"name": product.sale_category.name,
|
|
"discountLimit": product.sale_category.discount_limit,
|
|
},
|
|
}
|
|
|
|
|
|
def voucher_info(item: Voucher, db: Session):
|
|
return {
|
|
"id": item.id,
|
|
"date": (item.date + timedelta(minutes=settings.TIMEZONE_OFFSET_MINUTES)).strftime("%H:%M"),
|
|
"dateTip": (item.date + timedelta(minutes=settings.TIMEZONE_OFFSET_MINUTES)).strftime("%d-%b-%Y %H:%M:%S"),
|
|
"pax": item.pax,
|
|
"user": {"id": item.user_id, "name": item.user.name},
|
|
"creationDate": (item.creation_date + timedelta(minutes=settings.TIMEZONE_OFFSET_MINUTES)).strftime("%H:%M"),
|
|
"creationDateTip": (item.creation_date + timedelta(minutes=settings.TIMEZONE_OFFSET_MINUTES)).strftime(
|
|
"%d-%b-%Y %H:%M:%S"
|
|
),
|
|
"lastEditDate": (item.last_edit_date + timedelta(minutes=settings.TIMEZONE_OFFSET_MINUTES)).strftime("%H:%M"),
|
|
"lastEditDateTip": (item.last_edit_date + timedelta(minutes=settings.TIMEZONE_OFFSET_MINUTES)).strftime(
|
|
"%d-%b-%Y %H:%M:%S"
|
|
),
|
|
"kotId": item.kot_id,
|
|
"billId": ", ".join(f"{x.regime.prefix}-{x.bill_number}" for x in item.bills),
|
|
"table": {"id": item.food_table_id, "name": item.food_table.name},
|
|
"customer": {"id": item.customer.id, "name": item.customer.name} if item.customer is not None else None,
|
|
"narration": item.narration,
|
|
"reason": item.reason,
|
|
"voucherType": item.voucher_type,
|
|
"kots": [
|
|
{
|
|
"id": k.id,
|
|
"code": k.code,
|
|
"date": (k.date + timedelta(minutes=settings.TIMEZONE_OFFSET_MINUTES)).strftime("%d-%b-%Y %H:%M:%S"),
|
|
"user": {"id": k.user_id, "name": k.user.name},
|
|
"inventories": [
|
|
{
|
|
"id": i.id,
|
|
"sortOrder": i.sort_order,
|
|
"product": voucher_product(i.product_id, item.date, i.is_happy_hour, db),
|
|
"quantity": i.quantity,
|
|
"price": i.price,
|
|
"isHappyHour": i.is_happy_hour,
|
|
"taxRate": i.tax_rate,
|
|
"tax": {"id": i.tax_id, "name": i.tax.name},
|
|
"discount": i.discount,
|
|
"modifiers": [
|
|
{
|
|
"id": m.modifier.id,
|
|
"name": m.modifier.name,
|
|
"price": m.price,
|
|
}
|
|
for m in i.modifiers
|
|
],
|
|
}
|
|
for i in k.inventories
|
|
],
|
|
}
|
|
for k in item.kots
|
|
],
|
|
}
|
|
|
|
|
|
def voucher_blank(table: FoodTable, guest: GuestBook | None):
|
|
return {
|
|
"pax": table.seats if guest is None else guest.pax,
|
|
"table": {"id": table.id, "name": table.name},
|
|
"voucherType": VoucherType.KOT,
|
|
"customer": {"id": guest.customer_id, "name": guest.customer.name} if guest is not None else None,
|
|
"kots": [],
|
|
}
|