import re import uuid from datetime import datetime, timedelta from typing import Optional from fastapi import APIRouter, HTTPException, Security, status from sqlalchemy import and_, or_, select 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.food_table import FoodTable from ...models.guest_book import GuestBook from ...models.overview import Overview from ...models.product_version import ProductVersion 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: query = select(Voucher) if re.compile(r"^\d{1,3}-\d{1,4}$").match(id_): s, n = id_.split("-") i = (int(s) * 10000) + int(n) query = query.where(Voucher.bill_id == i, Voucher.voucher_type == VoucherType.REGULAR_BILL) elif re.compile(r"^K-\d+$").match(id_): query = query.where( Voucher.kot_id == int(id_.replace("K-", "")), Voucher.voucher_type == VoucherType.KOT, ) elif re.compile(r"^NC-\d+$").match(id_): query = query.where( Voucher.bill_id == int(id_.replace("NC-", "")), Voucher.voucher_type == VoucherType.NO_CHARGE, ) elif re.compile(r"^ST-\d+$").match(id_): query = query.where( Voucher.bill_id == int(id_.replace("ST-", "")), Voucher.voucher_type == VoucherType.STAFF, ) elif re.compile(r"^V-\d+$").match(id_): query = query.where( Voucher.kot_id == int(id_.replace("V-", "")), Voucher.voucher_type == VoucherType.VOID, ) else: raise HTTPException( status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail="Bill Number is invalid", ) item: Voucher = db.execute(query).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: Optional[uuid.UUID] = None, # voucher id g: Optional[uuid.UUID] = None, # guest id user: UserToken = Security(get_user), ): with SessionFuture() as db: 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: return voucher_info(item.voucher, db) table = db.execute(select(FoodTable).where(FoodTable.id == id_)).scalar_one() if g is not None: guest = db.execute(select(GuestBook).where(GuestBook.id == g)).scalar_one() else: guest = None 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": item.full_bill_id, "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, "guest": None, # TODO: Wire this functionality "narration": item.narration, # TODO: Wire this functionality "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: Optional[GuestBook]): 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": [], }