From 6c062713151e08139f228fd731b65ee91c84b851 Mon Sep 17 00:00:00 2001 From: tanshu Date: Thu, 24 Sep 2020 07:39:46 +0530 Subject: [PATCH] Ported: Guest Book Save bill Update bill Show bill Fix: Tax details was sending the rate multiplied by 100 but not dividing it on save/update Feature: Updated the auth service to check local storage for the latest user token --- barker/main.py | 7 + barker/routers/printer.py | 4 +- barker/routers/tax.py | 5 +- barker/routers/voucher/__init__.py | 60 ++++--- barker/routers/voucher/save.py | 156 ++++++++++------- barker/routers/voucher/show.py | 90 +++++----- barker/routers/voucher/update.py | 165 ++++++++++-------- barker/schemas/customer.py | 9 + barker/schemas/tax.py | 2 +- barker/schemas/voucher.py | 58 ++++++ bookie/src/app/auth/auth.service.ts | 33 ++-- bookie/src/app/sales/bills/voucher.service.ts | 17 +- 12 files changed, 382 insertions(+), 224 deletions(-) create mode 100644 barker/schemas/voucher.py diff --git a/barker/main.py b/barker/main.py index a5dc8d5..c0e7e8a 100644 --- a/barker/main.py +++ b/barker/main.py @@ -3,6 +3,7 @@ from fastapi import FastAPI from starlette.middleware.sessions import SessionMiddleware from .routers import ( + guest_book, menu_category, modifier, modifier_category, @@ -25,6 +26,7 @@ from .routers.reports import ( sale_report, tax_report ) +from .routers.voucher import show, save, update from .db.base_class import Base from .core.config import settings @@ -66,6 +68,11 @@ app.include_router(product_sale_report.router, prefix="/api/product-sale-report" app.include_router(sale_report.router, prefix="/api/sale-report", tags=["reports"]) app.include_router(tax_report.router, prefix="/api/tax-report", tags=["reports"]) +app.include_router(guest_book.router, prefix="/api/guest-book", tags=["guest-book"]) +app.include_router(show.router, prefix="/api/voucher", tags=["voucher"]) +app.include_router(save.router, prefix="/api/voucher", tags=["voucher"]) +app.include_router(update.router, prefix="/api/voucher", tags=["voucher"]) + # app.include_router(issue_grid.router, prefix="/api/issue-grid", tags=["vouchers"]) # app.include_router(batch.router, prefix="/api/batch", tags=["vouchers"]) # app.include_router(journal.router, prefix="/api/journal", tags=["vouchers"]) diff --git a/barker/routers/printer.py b/barker/routers/printer.py index 620291f..640e496 100644 --- a/barker/routers/printer.py +++ b/barker/routers/printer.py @@ -9,7 +9,7 @@ from ..schemas.auth import UserToken import barker.schemas.master as schemas from ..core.security import get_current_active_user as get_user from ..db.session import SessionLocal -from ..models.master import SaleCategory, Printer +from ..models.master import Printer router = APIRouter() @@ -87,7 +87,7 @@ def delete( @router.get("") def show_blank( - db: Session = Depends(get_db), user: UserToken = Security(get_user, scopes=[""]), + db: Session = Depends(get_db), user: UserToken = Security(get_user, scopes=["printers"]), ): return printer_info(None) diff --git a/barker/routers/tax.py b/barker/routers/tax.py index da5bbce..c4272d2 100644 --- a/barker/routers/tax.py +++ b/barker/routers/tax.py @@ -1,4 +1,5 @@ import uuid +from decimal import Decimal from typing import Optional from fastapi import APIRouter, HTTPException, status, Depends, Security @@ -28,7 +29,7 @@ def save( data: schemas.TaxIn, db: Session = Depends(get_db), user: UserToken = Security(get_user, scopes=["taxes"]), ): try: - item = Tax(name=data.name, rate=data.rate) + item = Tax(name=data.name, rate=round(data.rate / Decimal(100), 4)) db.add(item) db.commit() return tax_info(item) @@ -56,7 +57,7 @@ def update( status_code=status.HTTP_423_LOCKED, detail=f"{item.name} is a fixture and cannot be edited or deleted.", ) item.name = data.name - item.rate = data.rate + item.rate = round(data.rate / Decimal(100), 4) db.commit() return tax_info(item) except SQLAlchemyError as e: diff --git a/barker/routers/voucher/__init__.py b/barker/routers/voucher/__init__.py index 90cb4b6..9eac669 100644 --- a/barker/routers/voucher/__init__.py +++ b/barker/routers/voucher/__init__.py @@ -1,6 +1,9 @@ import uuid +from fastapi import HTTPException from sqlalchemy import func +from sqlalchemy.orm import Session +from starlette import status from barker.models import ( VoucherType, @@ -18,14 +21,16 @@ def get_tax(tax, voucher_type): elif voucher_type in [VoucherType.KOT, VoucherType.REGULAR_BILL]: return tax else: - raise ValidationError("Unexpected Voucher Type") + raise HTTPException( + status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail="Unexpected Voucher Type", + ) -def get_bill_id(voucher_type, dbsession): +def get_bill_id(voucher_type, db): if voucher_type == VoucherType.KOT: return None bill_id = ( - dbsession.query(func.coalesce(func.max(Voucher.bill_id), 0) + 1) + db.query(func.coalesce(func.max(Voucher.bill_id), 0) + 1) .filter(Voucher.voucher_type == voucher_type.value) .scalar() ) @@ -34,46 +39,55 @@ def get_bill_id(voucher_type, dbsession): return bill_id -def do_update_table(item, guest_book, dbsession): - status = "running" if item.voucher_type == VoucherType.KOT else "printed" +def do_update_table(item, guest_book, db): + status_ = "running" if item.voucher_type == VoucherType.KOT else "printed" if item.status is None: item.status = Overview( voucher_id=item.id, food_table_id=item.food_table_id, guest_book_id=guest_book.id if guest_book is not None else None, - status=status, + status=status_, ) - dbsession.add(item.status) + db.add(item.status) else: - item.status.status = status + item.status.status = status_ def check_permissions(item, voucher_type, permissions): - if voucher_type == VoucherType.KOT and "Print Kot" not in permissions: - raise ValidationFailure("You are not allowed to print a kot") - - if voucher_type != VoucherType.KOT and "Print Bill" not in permissions: - raise ValidationFailure("You are not allowed to print bill") + if voucher_type == VoucherType.KOT and "print-kot" not in permissions: + raise HTTPException( + status_code=status.HTTP_403_FORBIDDEN, detail="You are not allowed to print a kot", + ) + if voucher_type != VoucherType.KOT and "print-bill" not in permissions: + raise HTTPException( + status_code=status.HTTP_403_FORBIDDEN, detail="You are not allowed to print bill", + ) if item is None: return if item.voucher_type != VoucherType.KOT and "Edit Printed Bill" not in permissions: - raise ValidationFailure("You are not allowed to edit a printed bill") + raise HTTPException( + status_code=status.HTTP_403_FORBIDDEN, detail="You are not allowed to edit a printed bill", + ) if item.voucher_type != VoucherType.KOT and voucher_type == VoucherType.KOT: - raise ValidationFailure("This Bill is already printed\nCannot add a Kot to it.") + raise HTTPException( + status_code=status.HTTP_403_FORBIDDEN, detail="This Bill is already printed\nCannot add a Kot to it.", + ) if item.voucher_type == VoucherType.VOID: - raise ValidationFailure("This Bill is already void.\nReason: {0}".format(item.reason)) + raise HTTPException( + status_code=status.HTTP_403_FORBIDDEN, detail=f"This Bill is already void.\nReason: {item.reason}", + ) -def get_guest_book(guest_book_id, dbsession): - if guest_book_id is None: - return guest_book_id - return dbsession.query(GuestBook).filter(GuestBook.id == uuid.UUID(guest_book_id)).first() +def get_guest_book(id_: uuid.UUID, db: Session): + if id_ is None: + return id_ + return db.query(GuestBook).filter(GuestBook.id == id_).first() -def do_update_settlements(voucher, dbsession): +def do_update_settlements(voucher, db: Session): settlements = [] total_amount = voucher.amount settlements.append({"id": SettleOption.AMOUNT(), "amount": -total_amount}) @@ -91,8 +105,8 @@ def do_update_settlements(voucher, dbsession): else: s = Settlement(voucher.id, settlement_type_id, amount) voucher.settlements.append(s) - dbsession.add(s) + db.add(s) for i in (i for i in voucher.settlements if i.settled not in [x["id"] for x in settlements]): voucher.settlements.remove(i) - dbsession.delete(i) + db.delete(i) diff --git a/barker/routers/voucher/save.py b/barker/routers/voucher/save.py index 642dee3..45c84dc 100644 --- a/barker/routers/voucher/save.py +++ b/barker/routers/voucher/save.py @@ -1,22 +1,19 @@ -import datetime import uuid +from datetime import datetime from decimal import Decimal +from typing import Optional -import transaction -from pyramid.view import view_config +from fastapi import APIRouter, HTTPException, status, Depends, Security from sqlalchemy import func +from sqlalchemy.exc import SQLAlchemyError +from sqlalchemy.orm import Session -from barker.models import ( - Voucher, - Kot, - Inventory, - InventoryModifier, - VoucherType, - Product, - FoodTable, -) -from barker.models.validation_exception import ValidationError -from barker.views.voucher import ( +from ...schemas.auth import UserToken +import barker.schemas.voucher as schemas +from ...core.security import get_current_active_user as get_user +from ...db.session import SessionLocal +from ...models import Voucher, VoucherType, Kot, Product, Inventory, InventoryModifier +from ...routers.voucher import ( get_tax, do_update_settlements, get_bill_id, @@ -25,61 +22,88 @@ from barker.views.voucher import ( get_guest_book, ) +router = APIRouter() -@view_config(request_method="POST", route_name="v1_vouchers_new", renderer="json", trans=True) -def save(request): - json = request.json_body - now = datetime.datetime.now() - update_table = request.GET["u"] == "true" - voucher_type = VoucherType[request.GET["p"]] - guest_book = get_guest_book(request.GET.get("g", None), request.dbsession) - check_permissions(None, voucher_type, request.effective_principals) +# Dependency +def get_db(): + try: + db = SessionLocal() + yield db + finally: + db.close() - bill_id = get_bill_id(voucher_type, request.dbsession) - kot_id = request.dbsession.query(func.coalesce(func.max(Voucher.kot_id), 0) + 1).scalar() - item = Voucher( - now, - guest_book.pax if guest_book is not None else json["pax"], - bill_id, - kot_id, - json["table"]["id"], - json["customer"]["id"] if "id" in json["customer"] else None, - voucher_type, - uuid.UUID(request.authenticated_userid), - ) - request.dbsession.add(item) - for k in json["kots"]: - code = request.dbsession.query(func.coalesce(func.max(Kot.code), 0) + 1).scalar() - kot = Kot(item.id, code, item.food_table_id, item.date, item.user_id) - item.kots.append(kot) - request.dbsession.add(kot) - for index, i in enumerate(k["inventories"]): - product = request.dbsession.query(Product).filter(Product.id == uuid.UUID(i["product"]["id"])).first() - tax_rate = get_tax(product.sale_category.tax.rate, voucher_type) - inv = Inventory( - kot.id, - product.id, - round(Decimal(i["quantity"]), 2), - product.price, - round(Decimal(i["discount"]), 5), - i["isHappyHour"], - product.sale_category.tax_id, - tax_rate, - index, +@router.post("/save") +def save( + data: schemas.VoucherIn, + u: bool, # Update table? + p: str, # Print type + g: Optional[uuid.UUID] = None, # Guest book id + db: Session = Depends(get_db), + user: UserToken = Security(get_user), +): + try: + now = datetime.now() + update_table = u + voucher_type = VoucherType[p] + guest_book = get_guest_book(g, db) + + check_permissions(None, voucher_type, user.permissions) + + bill_id = get_bill_id(voucher_type, db) + kot_id = db.query(func.coalesce(func.max(Voucher.kot_id), 0) + 1).scalar() + + item = Voucher( + now, + guest_book.pax if guest_book is not None else data.pax, + bill_id, + kot_id, + data.table.id_, + data.customer.id_ if data.customer is not None else None, + voucher_type, + user.id_, + ) + db.add(item) + for k in data.kots: + code = db.query(func.coalesce(func.max(Kot.code), 0) + 1).scalar() + 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): + product = db.query(Product).filter(Product.id == i.product.id_).first() + tax_rate = get_tax(product.sale_category.tax.rate, voucher_type) + inv = Inventory( + kot.id, + product.id, + round(i.quantity, 2), + product.price, + round(i.discount, 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_, 0) + inv.modifiers.append(mod) + db.add(mod) + do_update_settlements(item, db) + if len(item.kots) == 0 or len(item.kots[0].inventories) == 0: + raise HTTPException( + status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail="Please add some products", ) - kot.inventories.append(inv) - request.dbsession.add(inv) - for m in i["modifiers"]: - mod = InventoryModifier(None, uuid.UUID(m["id"]), 0) - inv.modifiers.append(mod) - request.dbsession.add(mod) - do_update_settlements(item, request.dbsession) - if len(item.kots) == 0 or len(item.kots[0].inventories) == 0: - raise ValidationError("Please add some products!") - if update_table: - do_update_table(item, guest_book, request.dbsession) - transaction.commit() - return True + if update_table: + do_update_table(item, guest_book, db) + db.commit() + except SQLAlchemyError as e: + db.rollback() + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(e), + ) + except Exception: + db.rollback() + raise diff --git a/barker/routers/voucher/show.py b/barker/routers/voucher/show.py index b1e4f2b..389964a 100644 --- a/barker/routers/voucher/show.py +++ b/barker/routers/voucher/show.py @@ -1,65 +1,77 @@ import re import uuid +from typing import Optional -from pyramid.view import view_config +from fastapi import APIRouter, HTTPException, status, Depends, Security +from sqlalchemy.orm import Session -from barker.exceptions import ValidationFailure -from barker.models import Voucher, Overview, FoodTable, GuestBook, VoucherType +from ...schemas.auth import UserToken +from ...core.security import get_current_active_user as get_user +from ...db.session import SessionLocal +from ...models import Voucher, Overview, FoodTable, GuestBook, VoucherType + +router = APIRouter() -@view_config( - request_method="GET", route_name="v1_vouchers_id", renderer="json", permission="Authenticated", -) -def show_id(request): - id_ = uuid.UUID(request.matchdict["id"]) - item = request.dbsession.query(Voucher).filter(Voucher.id == id_).first() +# Dependency +def get_db(): + try: + db = SessionLocal() + yield db + finally: + db.close() + + +@router.get("/from-id/{id_}") +def from_id( + id_: str, db: Session = Depends(get_db), user: UserToken = Security(get_user), +): + item = db.query(Voucher).filter(Voucher.id == id_).first() return voucher_info(item) -@view_config( - request_method="GET", route_name="v1_vouchers_new", request_param="b", renderer="json", permission="Authenticated", -) -def show(request): - bill_id = request.GET["b"] - item = request.dbsession.query(Voucher) - if re.compile("^\d{2,}-\d{4}$").match(bill_id): - item = item.filter(Voucher.bill_id == int(bill_id.replace("-", "")), Voucher.voucher_type.in_([1, 3]),) - elif re.compile("^NC-\d+$").match(bill_id): - item = item.filter(Voucher.bill_id == int(bill_id.replace("NC-", "")), Voucher.voucher_type == 2,) - elif re.compile("^ST-\d+$").match(bill_id): - item = item.filter(Voucher.bill_id == int(bill_id.replace("ST-", "")), Voucher.voucher_type == 4,) +@router.get("/from-bill/{id_}") +def from_bill( + id_: str, db: Session = Depends(get_db), user: UserToken = Security(get_user), +): + item: Voucher = db.query(Voucher) + if re.compile(r"^\d{2,}-\d{4}$").match(id_): + item = item.filter(Voucher.bill_id == int(id_.replace("-", "")), Voucher.voucher_type.in_([1, 3]),) + elif re.compile(r"^NC-\d+$").match(id_): + item = item.filter(Voucher.bill_id == int(id_.replace("NC-", "")), Voucher.voucher_type == 2,) + elif re.compile(r"^ST-\d+$").match(id_): + item = item.filter(Voucher.bill_id == int(id_.replace("ST-", "")), Voucher.voucher_type == 4,) item = item.first() if item is None: return {} return voucher_info(item) -@view_config( - request_method="GET", route_name="v1_vouchers_new", request_param="t", renderer="json", permission="Authenticated", -) -def show_for_table(request): - table_id = uuid.UUID(request.GET["t"]) - voucher_id = request.GET.get("v", None) - guest_id = request.GET.get("g", None) - if voucher_id is not None: - item = ( - request.dbsession.query(Overview) - .filter(Overview.voucher_id == uuid.UUID(voucher_id), Overview.food_table_id == table_id,) - .first() - ) +@router.get("/from-table/{id_}") +def from_bill( + id_: str, # Table ID + v: Optional[uuid.UUID] = None, # Voucher ID + g: Optional[uuid.UUID] = None, # Guest ID + db: Session = Depends(get_db), + user: UserToken = Security(get_user), +): + if v is not None: + item = db.query(Overview).filter(Overview.voucher_id == v, Overview.food_table_id == id_,).first() if item is None: - raise ValidationFailure("Bill Not Found") + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, detail="Voucher not found", + ) else: return voucher_info(item.voucher) - table = request.dbsession.query(FoodTable).filter(FoodTable.id == table_id).first() - if guest_id is not None: - guest = request.dbsession.query(GuestBook).filter(GuestBook.id == guest_id).first() + table = db.query(FoodTable).filter(FoodTable.id == id_).first() + if g is not None: + guest = db.query(GuestBook).filter(GuestBook.id == g).first() else: guest = None return voucher_blank(table, guest) -def voucher_info(item): +def voucher_info(item: Voucher): return { "id": item.id, "date": item.date.strftime("%H:%M"), diff --git a/barker/routers/voucher/update.py b/barker/routers/voucher/update.py index f0e48d8..42e8d57 100644 --- a/barker/routers/voucher/update.py +++ b/barker/routers/voucher/update.py @@ -1,20 +1,19 @@ -import datetime import uuid +from datetime import datetime from decimal import Decimal +from typing import Optional -import transaction -from pyramid.view import view_config +from fastapi import APIRouter, HTTPException, status, Depends, Security from sqlalchemy import func +from sqlalchemy.exc import SQLAlchemyError +from sqlalchemy.orm import Session -from barker.models import ( - Voucher, - Kot, - Inventory, - InventoryModifier, - VoucherType, - Product, -) -from barker.views.voucher import ( +from ...schemas.auth import UserToken +import barker.schemas.voucher as schemas +from ...core.security import get_current_active_user as get_user +from ...db.session import SessionLocal +from ...models import Voucher, VoucherType, Kot, Product, Inventory, InventoryModifier +from ...routers.voucher import ( get_tax, do_update_settlements, get_bill_id, @@ -23,65 +22,89 @@ from barker.views.voucher import ( get_guest_book, ) +router = APIRouter() -@view_config(request_method="PUT", route_name="v1_vouchers_id", renderer="json", trans=True) -def update(request): - json = request.json_body - now = datetime.datetime.now() - update_table = request.GET["u"] == "true" - voucher_type = VoucherType[request.GET["p"]] - guest_book = get_guest_book(request.GET.get("g", None), request.dbsession) - item = request.dbsession.query(Voucher).filter(Voucher.id == uuid.UUID(request.matchdict["id"])).first() - check_permissions(item, voucher_type, request.effective_principals) +# Dependency +def get_db(): + try: + db = SessionLocal() + yield db + finally: + db.close() - if guest_book is not None: - item.pax = guest_book.pax - item.food_table_id = json["table"]["id"] - if "customer" in json and "id" in json["customer"]: - item.customer_id = json["customer"]["id"] - if item.voucher_type == VoucherType.KOT and voucher_type != VoucherType.KOT: - item.date = now - item.bill_id = get_bill_id(voucher_type, request.dbsession) - item.voucher_type = voucher_type - item.user_id = uuid.UUID(request.authenticated_userid) - item.last_edit_date = now - for k in item.kots: - for i in k.inventories: - i.tax_rate = get_tax(i.tax_rate, voucher_type) - i.discount = next( - round(Decimal(inv["discount"]), 5) - for ko in json["kots"] - for inv in ko["inventories"] - if uuid.UUID(inv["id"]) == i.id - ) - for k in (k for k in json["kots"] if "id" not in k and len(k["inventories"]) > 0): - code = request.dbsession.query(func.coalesce(func.max(Kot.code), 0) + 1).scalar() - kot = Kot(item.id, code, item.food_table_id, now, item.user_id) - item.kots.append(kot) - request.dbsession.add(kot) - for index, i in enumerate(k["inventories"]): - product = request.dbsession.query(Product).filter(Product.id == uuid.UUID(i["product"]["id"])).first() - tax_rate = get_tax(product.sale_category.tax.rate, voucher_type) - inv = Inventory( - kot.id, - product.id, - round(Decimal(i["quantity"]), 2), - product.price, - round(Decimal(i["discount"]), 5), - i["isHappyHour"], - product.sale_category.tax_id, - tax_rate, - index, - ) - kot.inventories.append(inv) - request.dbsession.add(inv) - for m in i["modifiers"]: - mod = InventoryModifier(None, uuid.UUID(m["id"]), 0) - inv.modifiers.append(mod) - request.dbsession.add(mod) - do_update_settlements(item, request.dbsession) - if update_table: - do_update_table(item, guest_book, request.dbsession) - transaction.commit() - return True + +@router.put("/update/{id_}") +def update( + id_: uuid.UUID, + data: schemas.VoucherIn, + u: bool, # Update table? + p: str, # Print type + g: Optional[uuid.UUID] = None, # Guest book id + db: Session = Depends(get_db), + user: UserToken = Security(get_user), +): + try: + now = datetime.now() + update_table = u + voucher_type = VoucherType[p] + guest_book = get_guest_book(g, db) + + item: Voucher = db.query(Voucher).filter(Voucher.id == id_).first() + + check_permissions(item, voucher_type, user.permissions) + + if guest_book is not None: + item.pax = guest_book.pax + item.food_table_id = data.table.id_ + if data.customer is not None: + item.customer_id = data.customer.id_ + if item.voucher_type == VoucherType.KOT and voucher_type != VoucherType.KOT: + item.date = now + item.bill_id = get_bill_id(voucher_type, db) + item.voucher_type = voucher_type + item.user_id = user.id_ + item.last_edit_date = now + for k in item.kots: + for i in k.inventories: + i.tax_rate = get_tax(i.tax_rate, voucher_type) + i.discount = next( + round(inv.discount, 5) for ko in data.kots for inv in ko.inventories if inv.id_ == i.id + ) + for k in (k for k in data.kots if k.id_ is None and len(k.inventories) > 0): + code = db.query(func.coalesce(func.max(Kot.code), 0) + 1).scalar() + kot = Kot(item.id, code, item.food_table_id, now, item.user_id) + item.kots.append(kot) + db.add(kot) + for index, i in enumerate(k.inventories): + product = db.query(Product).filter(Product.id == i.product.id_).first() + tax_rate = get_tax(product.sale_category.tax.rate, voucher_type) + inv = Inventory( + kot.id, + product.id, + round(i.quantity, 2), + product.price, + round(i.discount, 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_, 0) + inv.modifiers.append(mod) + db.add(mod) + do_update_settlements(item, db) + if update_table: + do_update_table(item, guest_book, db) + db.commit() + except SQLAlchemyError as e: + db.rollback() + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(e), + ) + except Exception: + db.rollback() + raise diff --git a/barker/schemas/customer.py b/barker/schemas/customer.py index ce15214..2dd35b7 100644 --- a/barker/schemas/customer.py +++ b/barker/schemas/customer.py @@ -27,3 +27,12 @@ class Customer(CustomerIn): fields = {"id_": "id"} anystr_strip_whitespace = True alias_generator = to_camel + + +class CustomerLink(BaseModel): + id_: uuid.UUID = Field(...) + name: Optional[str] + + class Config: + fields = {"id_": "id"} + alias_generator = to_camel diff --git a/barker/schemas/tax.py b/barker/schemas/tax.py index f225966..6490cde 100644 --- a/barker/schemas/tax.py +++ b/barker/schemas/tax.py @@ -9,7 +9,7 @@ from barker.schemas import to_camel class TaxIn(BaseModel): name: str = Field(..., min_length=1) - rate: Decimal = Field(ge=0, multiple_of=0.0001, default=0, le=1) + rate: Decimal = Field(ge=0, multiple_of=0.01, default=0) class Config: fields = {"id_": "id"} diff --git a/barker/schemas/voucher.py b/barker/schemas/voucher.py new file mode 100644 index 0000000..e37eb44 --- /dev/null +++ b/barker/schemas/voucher.py @@ -0,0 +1,58 @@ +import uuid +from typing import Optional, List +from decimal import Decimal + +from pydantic import BaseModel, Field + +from barker.schemas import to_camel +from barker.schemas.customer import CustomerLink +from barker.schemas.modifier import ModifierLink +from barker.schemas.product import ProductLink +from barker.schemas.table import TableLink +from barker.schemas.tax import TaxLink + + +class Inventory(BaseModel): + id_: Optional[uuid.UUID] + product: ProductLink + quantity: Decimal = Field(ge=0, multiple_of=0.01) + rate: Optional[Decimal] + tax: Optional[TaxLink] + taxRate: Optional[Decimal] + discount: Decimal = Field(ge=0, multiple_of=0.00001, le=1) + is_happy_hour: bool + modifiers: Optional[List[ModifierLink]] + amount: Optional[Decimal] + + class Config: + alias_generator = to_camel + + +class Kot(BaseModel): + id_: Optional[uuid.UUID] + inventories: List[Inventory] + + class Config: + anystr_strip_whitespace = True + alias_generator = to_camel + + +class VoucherIn(BaseModel): + pax: int + table: TableLink + customer: Optional[CustomerLink] + kots: List[Kot] + + class Config: + fields = {"id_": "id"} + anystr_strip_whitespace = True + alias_generator = to_camel + + +class Voucher(VoucherIn): + id_: uuid.UUID + + class Config: + fields = {"id_": "id"} + anystr_strip_whitespace = True + alias_generator = to_camel diff --git a/bookie/src/app/auth/auth.service.ts b/bookie/src/app/auth/auth.service.ts index 7a1b9f4..2f06431 100644 --- a/bookie/src/app/auth/auth.service.ts +++ b/bookie/src/app/auth/auth.service.ts @@ -16,22 +16,39 @@ export class AuthService { public currentUser: Observable; constructor(private http: HttpClient) { - this.currentUserSubject = new BehaviorSubject(JSON.parse(localStorage.getItem(JWT_USER))); + this.checkStorage(); this.currentUser = this.currentUserSubject.asObservable(); } + checkStorage(): User { + const existingToken: User = JSON.parse(localStorage.getItem(JWT_USER)); + if (existingToken === null || Date.now() > existingToken.exp * 1000) { + localStorage.removeItem(JWT_USER); + this.currentUserSubject = new BehaviorSubject(null); + return null; + } else { + this.currentUserSubject = new BehaviorSubject(existingToken); + return existingToken; + } + } + public get user(): User { - const val = this.currentUserSubject.value; + let val = this.currentUserSubject.value; if (val == null) { return val; } - const expired = Date.now() > val.exp * 1000; + let expired = Date.now() > val.exp * 1000; + if (expired) { + val = this.checkStorage(); + } + if (val == null) { + return null; + } + expired = Date.now() > val.exp * 1000; if (expired) { this.logout(); - return null; - } else { - return this.currentUserSubject.value; } + return this.currentUserSubject.value; } login(username: string, password: string, otp: string) { @@ -73,10 +90,6 @@ export class AuthService { return Date.now() > (this.user.exp - (environment.ACCESS_TOKEN_REFRESH_MINUTES * 60)) * 1000; } - expired(): boolean { - return Date.now() > this.user.exp * 1000; - } - logout() { // remove user from local storage to log user out localStorage.removeItem(JWT_USER); diff --git a/bookie/src/app/sales/bills/voucher.service.ts b/bookie/src/app/sales/bills/voucher.service.ts index 715d247..e23696b 100644 --- a/bookie/src/app/sales/bills/voucher.service.ts +++ b/bookie/src/app/sales/bills/voucher.service.ts @@ -10,9 +10,9 @@ const httpOptions = { headers: new HttpHeaders({'Content-Type': 'application/json'}) }; -const url = '/v1/vouchers'; -const urlMoveTable = '/v1/move-table'; -const urlMoveKot = '/v1/move-kot'; +const url = '/api/voucher'; +const urlMoveTable = '/api/move-table'; +const urlMoveKot = '/api/move-kot'; const serviceName = 'VoucherService'; @Injectable({providedIn: 'root'}) @@ -22,7 +22,7 @@ export class VoucherService { } get(id: string): Observable { - return >this.http.get(`${url}/${id}`) + return >this.http.get(`${url}/from-id/${id}`) .pipe( catchError(this.log.handleError(serviceName, `get id=${id}`)) ); @@ -30,9 +30,6 @@ export class VoucherService { getFromTable(tableId: string, voucherId: string, guestId: string): Observable { let params = new HttpParams(); - if (tableId !== null) { - params = params.set('t', tableId); - } if (voucherId !== null) { params = params.set('v', voucherId); } @@ -40,7 +37,7 @@ export class VoucherService { params = params.set('g', guestId); } - return >this.http.get(`${url}/new`, {params: params}) + return >this.http.get(`${url}/from-table/${tableId}`, {params: params}) .pipe( catchError(this.log.handleError( serviceName, @@ -54,7 +51,7 @@ export class VoucherService { if (guest_book_id !== null) { options.params = options.params.set('g', guest_book_id); } - return >this.http.post(`${url}/new`, voucher, options) + return >this.http.post(`${url}/save`, voucher, options) .pipe( catchError(this.log.handleError(serviceName, 'save')) ); @@ -65,7 +62,7 @@ export class VoucherService { if (guest_book_id !== null) { options.params = options.params.set('g', guest_book_id); } - return >this.http.put(`${url}/${voucher.id}`, voucher, options) + return >this.http.put(`${url}/update/${voucher.id}`, voucher, options) .pipe( catchError(this.log.handleError(serviceName, 'update')) );