import uuid from datetime import date, datetime, timedelta import barker.schemas.guest_book as schemas from fastapi import APIRouter, Depends, HTTPException, Security, status from sqlalchemy import desc, select from sqlalchemy.exc import SQLAlchemyError from sqlalchemy.orm import joinedload from ..core.config import settings from ..core.security import get_current_active_user as get_user from ..db.session import SessionFuture from ..models.customer import Customer from ..models.guest_book import GuestBook from ..models.voucher import Voucher from ..schemas.user_token import UserToken router = APIRouter() @router.post("", response_model=schemas.GuestBook) def save( data: schemas.GuestBookIn, user: UserToken = Security(get_user, scopes=["customers"]), ) -> schemas.GuestBook: try: with SessionFuture() as db: customer = db.execute(select(Customer).where(Customer.phone == data.phone)).scalars().one_or_none() if customer is None: if len(data.name) == 0: raise HTTPException( status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail="New customer name cannot be blank", ) if len(data.phone) == 0: data.phone = data.name customer = Customer( name=data.name, phone=data.phone, address=data.address, print_in_bill=False, ) db.add(customer) else: customer.name = data.name or customer.name customer.address = data.address or customer.address item = GuestBook( pax=data.pax, customer=customer, date_=data.date_ - timedelta(minutes=settings.TIMEZONE_OFFSET_MINUTES) ) db.add(item) db.commit() return guest_book_info(item) except SQLAlchemyError as e: raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(e), ) @router.put("/{id_}", response_model=schemas.GuestBook) def update_route( id_: uuid.UUID, data: schemas.GuestBookIn, user: UserToken = Security(get_user, scopes=["customers"]), ) -> schemas.GuestBook: try: with SessionFuture() as db: item: GuestBook = db.execute(select(GuestBook).where(GuestBook.id == id_)).scalar_one() item.customer.name = data.name item.customer.phone = data.phone item.customer.address = data.address item.pax = data.pax item.date = data.date_ - timedelta(minutes=settings.TIMEZONE_OFFSET_MINUTES) db.commit() return guest_book_info(item) except SQLAlchemyError as e: raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(e), ) @router.delete("/{id_}", response_model=schemas.GuestBookIn) def delete_route( id_: uuid.UUID, user: UserToken = Security(get_user, scopes=["customers"]), ) -> schemas.GuestBookIn: try: with SessionFuture() as db: item: GuestBook = db.execute(select(GuestBook).where(GuestBook.id == id_)).scalar_one() db.delete(item) db.commit() return blank_guest_book_info() except SQLAlchemyError as e: raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(e), ) @router.get("", response_model=schemas.GuestBookIn) def show_blank( user: UserToken = Security(get_user, scopes=["customers"]), ) -> schemas.GuestBookIn: return blank_guest_book_info() @router.get("/list", response_model=schemas.GuestBookList) def show_list( q: str | None = None, user: UserToken = Depends(get_user), ) -> schemas.GuestBookList: if q is None or q == "": d = date.today() else: d = datetime.strptime(q, "%d-%b-%Y") list_ = ( select(GuestBook) .where( GuestBook.date >= d + timedelta(minutes=settings.NEW_DAY_OFFSET_MINUTES - settings.TIMEZONE_OFFSET_MINUTES) ) .where( GuestBook.date < d + timedelta( minutes=settings.NEW_DAY_OFFSET_MINUTES - settings.TIMEZONE_OFFSET_MINUTES, days=1, ) ) .order_by(GuestBook.date) ) guest_book: list[schemas.GuestBookListItem] = [] with SessionFuture() as db: for i, item in enumerate(db.execute(list_).scalars().all()): gbli = schemas.GuestBookListItem( id=item.id, serial=i + 1, name=item.customer.name, phone=item.customer.phone, pax=item.pax, date=item.date, status=None if item.status is None else item.status.status, tableId=None if item.status is None else item.status.food_table.id, voucherId=None if item.status is None else item.status.voucher_id, tableName=None if item.status is None else item.status.food_table.name, ) if item.status is None: last = ( db.execute( select(Voucher) .where(Voucher.customer_id == item.customer_id) .order_by(desc(Voucher.date)) .options(joinedload(Voucher.food_table, innerjoin=True)) ) .scalars() .first() ) if last is not None: gbli.status = "old" gbli.voucher_id = last.id gbli.table_name = last.food_table.name guest_book.insert(0, gbli) return schemas.GuestBookList(date=d, list=guest_book) @router.get("/{id_}", response_model=schemas.GuestBook) def show_id( id_: uuid.UUID, user: UserToken = Security(get_user, scopes=["customers"]), ) -> schemas.GuestBook: with SessionFuture() as db: item: GuestBook = db.execute(select(GuestBook).where(GuestBook.id == id_)).scalar_one() return guest_book_info(item) def guest_book_info(item: GuestBook) -> schemas.GuestBook: return schemas.GuestBook( id=item.id, name=item.customer.name, phone=item.customer.phone, pax=item.pax, address=item.customer.address, date=item.date + timedelta(minutes=settings.TIMEZONE_OFFSET_MINUTES), ) def blank_guest_book_info() -> schemas.GuestBookIn: return schemas.GuestBookIn( name="", phone="", pax=0, address="", date=datetime.utcnow() + timedelta(minutes=settings.TIMEZONE_OFFSET_MINUTES), )