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
This commit is contained in:
2020-09-24 07:39:46 +05:30
parent b19d8cc030
commit 6c06271315
12 changed files with 382 additions and 224 deletions

View File

@ -3,6 +3,7 @@ from fastapi import FastAPI
from starlette.middleware.sessions import SessionMiddleware from starlette.middleware.sessions import SessionMiddleware
from .routers import ( from .routers import (
guest_book,
menu_category, menu_category,
modifier, modifier,
modifier_category, modifier_category,
@ -25,6 +26,7 @@ from .routers.reports import (
sale_report, sale_report,
tax_report tax_report
) )
from .routers.voucher import show, save, update
from .db.base_class import Base from .db.base_class import Base
from .core.config import settings 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(sale_report.router, prefix="/api/sale-report", tags=["reports"])
app.include_router(tax_report.router, prefix="/api/tax-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(issue_grid.router, prefix="/api/issue-grid", tags=["vouchers"])
# app.include_router(batch.router, prefix="/api/batch", tags=["vouchers"]) # app.include_router(batch.router, prefix="/api/batch", tags=["vouchers"])
# app.include_router(journal.router, prefix="/api/journal", tags=["vouchers"]) # app.include_router(journal.router, prefix="/api/journal", tags=["vouchers"])

View File

@ -9,7 +9,7 @@ from ..schemas.auth import UserToken
import barker.schemas.master as schemas import barker.schemas.master as schemas
from ..core.security import get_current_active_user as get_user from ..core.security import get_current_active_user as get_user
from ..db.session import SessionLocal from ..db.session import SessionLocal
from ..models.master import SaleCategory, Printer from ..models.master import Printer
router = APIRouter() router = APIRouter()
@ -87,7 +87,7 @@ def delete(
@router.get("") @router.get("")
def show_blank( 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) return printer_info(None)

View File

@ -1,4 +1,5 @@
import uuid import uuid
from decimal import Decimal
from typing import Optional from typing import Optional
from fastapi import APIRouter, HTTPException, status, Depends, Security 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"]), data: schemas.TaxIn, db: Session = Depends(get_db), user: UserToken = Security(get_user, scopes=["taxes"]),
): ):
try: 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.add(item)
db.commit() db.commit()
return tax_info(item) 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.", status_code=status.HTTP_423_LOCKED, detail=f"{item.name} is a fixture and cannot be edited or deleted.",
) )
item.name = data.name item.name = data.name
item.rate = data.rate item.rate = round(data.rate / Decimal(100), 4)
db.commit() db.commit()
return tax_info(item) return tax_info(item)
except SQLAlchemyError as e: except SQLAlchemyError as e:

View File

@ -1,6 +1,9 @@
import uuid import uuid
from fastapi import HTTPException
from sqlalchemy import func from sqlalchemy import func
from sqlalchemy.orm import Session
from starlette import status
from barker.models import ( from barker.models import (
VoucherType, VoucherType,
@ -18,14 +21,16 @@ def get_tax(tax, voucher_type):
elif voucher_type in [VoucherType.KOT, VoucherType.REGULAR_BILL]: elif voucher_type in [VoucherType.KOT, VoucherType.REGULAR_BILL]:
return tax return tax
else: 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: if voucher_type == VoucherType.KOT:
return None return None
bill_id = ( 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) .filter(Voucher.voucher_type == voucher_type.value)
.scalar() .scalar()
) )
@ -34,46 +39,55 @@ def get_bill_id(voucher_type, dbsession):
return bill_id return bill_id
def do_update_table(item, guest_book, dbsession): def do_update_table(item, guest_book, db):
status = "running" if item.voucher_type == VoucherType.KOT else "printed" status_ = "running" if item.voucher_type == VoucherType.KOT else "printed"
if item.status is None: if item.status is None:
item.status = Overview( item.status = Overview(
voucher_id=item.id, voucher_id=item.id,
food_table_id=item.food_table_id, food_table_id=item.food_table_id,
guest_book_id=guest_book.id if guest_book is not None else None, 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: else:
item.status.status = status item.status.status = status_
def check_permissions(item, voucher_type, permissions): def check_permissions(item, voucher_type, permissions):
if voucher_type == VoucherType.KOT and "Print Kot" not in permissions: if voucher_type == VoucherType.KOT and "print-kot" not in permissions:
raise ValidationFailure("You are not allowed to print a kot") 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 ValidationFailure("You are not allowed to print bill") 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: if item is None:
return return
if item.voucher_type != VoucherType.KOT and "Edit Printed Bill" not in permissions: 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: 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: 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): def get_guest_book(id_: uuid.UUID, db: Session):
if guest_book_id is None: if id_ is None:
return guest_book_id return id_
return dbsession.query(GuestBook).filter(GuestBook.id == uuid.UUID(guest_book_id)).first() return db.query(GuestBook).filter(GuestBook.id == id_).first()
def do_update_settlements(voucher, dbsession): def do_update_settlements(voucher, db: Session):
settlements = [] settlements = []
total_amount = voucher.amount total_amount = voucher.amount
settlements.append({"id": SettleOption.AMOUNT(), "amount": -total_amount}) settlements.append({"id": SettleOption.AMOUNT(), "amount": -total_amount})
@ -91,8 +105,8 @@ def do_update_settlements(voucher, dbsession):
else: else:
s = Settlement(voucher.id, settlement_type_id, amount) s = Settlement(voucher.id, settlement_type_id, amount)
voucher.settlements.append(s) 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]): for i in (i for i in voucher.settlements if i.settled not in [x["id"] for x in settlements]):
voucher.settlements.remove(i) voucher.settlements.remove(i)
dbsession.delete(i) db.delete(i)

View File

@ -1,22 +1,19 @@
import datetime
import uuid import uuid
from datetime import datetime
from decimal import Decimal from decimal import Decimal
from typing import Optional
import transaction from fastapi import APIRouter, HTTPException, status, Depends, Security
from pyramid.view import view_config
from sqlalchemy import func from sqlalchemy import func
from sqlalchemy.exc import SQLAlchemyError
from sqlalchemy.orm import Session
from barker.models import ( from ...schemas.auth import UserToken
Voucher, import barker.schemas.voucher as schemas
Kot, from ...core.security import get_current_active_user as get_user
Inventory, from ...db.session import SessionLocal
InventoryModifier, from ...models import Voucher, VoucherType, Kot, Product, Inventory, InventoryModifier
VoucherType, from ...routers.voucher import (
Product,
FoodTable,
)
from barker.models.validation_exception import ValidationError
from barker.views.voucher import (
get_tax, get_tax,
do_update_settlements, do_update_settlements,
get_bill_id, get_bill_id,
@ -25,61 +22,88 @@ from barker.views.voucher import (
get_guest_book, 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( @router.post("/save")
now, def save(
guest_book.pax if guest_book is not None else json["pax"], data: schemas.VoucherIn,
bill_id, u: bool, # Update table?
kot_id, p: str, # Print type
json["table"]["id"], g: Optional[uuid.UUID] = None, # Guest book id
json["customer"]["id"] if "id" in json["customer"] else None, db: Session = Depends(get_db),
voucher_type, user: UserToken = Security(get_user),
uuid.UUID(request.authenticated_userid), ):
) try:
request.dbsession.add(item) now = datetime.now()
for k in json["kots"]: update_table = u
code = request.dbsession.query(func.coalesce(func.max(Kot.code), 0) + 1).scalar() voucher_type = VoucherType[p]
kot = Kot(item.id, code, item.food_table_id, item.date, item.user_id) guest_book = get_guest_book(g, db)
item.kots.append(kot)
request.dbsession.add(kot) check_permissions(None, voucher_type, user.permissions)
for index, i in enumerate(k["inventories"]):
product = request.dbsession.query(Product).filter(Product.id == uuid.UUID(i["product"]["id"])).first() bill_id = get_bill_id(voucher_type, db)
tax_rate = get_tax(product.sale_category.tax.rate, voucher_type) kot_id = db.query(func.coalesce(func.max(Voucher.kot_id), 0) + 1).scalar()
inv = Inventory(
kot.id, item = Voucher(
product.id, now,
round(Decimal(i["quantity"]), 2), guest_book.pax if guest_book is not None else data.pax,
product.price, bill_id,
round(Decimal(i["discount"]), 5), kot_id,
i["isHappyHour"], data.table.id_,
product.sale_category.tax_id, data.customer.id_ if data.customer is not None else None,
tax_rate, voucher_type,
index, 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: if update_table:
do_update_table(item, guest_book, request.dbsession) do_update_table(item, guest_book, db)
transaction.commit() db.commit()
return True except SQLAlchemyError as e:
db.rollback()
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(e),
)
except Exception:
db.rollback()
raise

View File

@ -1,65 +1,77 @@
import re import re
import uuid 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 ...schemas.auth import UserToken
from barker.models import Voucher, Overview, FoodTable, GuestBook, VoucherType 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( # Dependency
request_method="GET", route_name="v1_vouchers_id", renderer="json", permission="Authenticated", def get_db():
) try:
def show_id(request): db = SessionLocal()
id_ = uuid.UUID(request.matchdict["id"]) yield db
item = request.dbsession.query(Voucher).filter(Voucher.id == id_).first() 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) return voucher_info(item)
@view_config( @router.get("/from-bill/{id_}")
request_method="GET", route_name="v1_vouchers_new", request_param="b", renderer="json", permission="Authenticated", def from_bill(
) id_: str, db: Session = Depends(get_db), user: UserToken = Security(get_user),
def show(request): ):
bill_id = request.GET["b"] item: Voucher = db.query(Voucher)
item = request.dbsession.query(Voucher) if re.compile(r"^\d{2,}-\d{4}$").match(id_):
if re.compile("^\d{2,}-\d{4}$").match(bill_id): item = item.filter(Voucher.bill_id == int(id_.replace("-", "")), Voucher.voucher_type.in_([1, 3]),)
item = item.filter(Voucher.bill_id == int(bill_id.replace("-", "")), Voucher.voucher_type.in_([1, 3]),) elif re.compile(r"^NC-\d+$").match(id_):
elif re.compile("^NC-\d+$").match(bill_id): item = item.filter(Voucher.bill_id == int(id_.replace("NC-", "")), Voucher.voucher_type == 2,)
item = item.filter(Voucher.bill_id == int(bill_id.replace("NC-", "")), Voucher.voucher_type == 2,) elif re.compile(r"^ST-\d+$").match(id_):
elif re.compile("^ST-\d+$").match(bill_id): item = item.filter(Voucher.bill_id == int(id_.replace("ST-", "")), Voucher.voucher_type == 4,)
item = item.filter(Voucher.bill_id == int(bill_id.replace("ST-", "")), Voucher.voucher_type == 4,)
item = item.first() item = item.first()
if item is None: if item is None:
return {} return {}
return voucher_info(item) return voucher_info(item)
@view_config( @router.get("/from-table/{id_}")
request_method="GET", route_name="v1_vouchers_new", request_param="t", renderer="json", permission="Authenticated", def from_bill(
) id_: str, # Table ID
def show_for_table(request): v: Optional[uuid.UUID] = None, # Voucher ID
table_id = uuid.UUID(request.GET["t"]) g: Optional[uuid.UUID] = None, # Guest ID
voucher_id = request.GET.get("v", None) db: Session = Depends(get_db),
guest_id = request.GET.get("g", None) user: UserToken = Security(get_user),
if voucher_id is not None: ):
item = ( if v is not None:
request.dbsession.query(Overview) item = db.query(Overview).filter(Overview.voucher_id == v, Overview.food_table_id == id_,).first()
.filter(Overview.voucher_id == uuid.UUID(voucher_id), Overview.food_table_id == table_id,)
.first()
)
if item is None: if item is None:
raise ValidationFailure("Bill Not Found") raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND, detail="Voucher not found",
)
else: else:
return voucher_info(item.voucher) return voucher_info(item.voucher)
table = request.dbsession.query(FoodTable).filter(FoodTable.id == table_id).first() table = db.query(FoodTable).filter(FoodTable.id == id_).first()
if guest_id is not None: if g is not None:
guest = request.dbsession.query(GuestBook).filter(GuestBook.id == guest_id).first() guest = db.query(GuestBook).filter(GuestBook.id == g).first()
else: else:
guest = None guest = None
return voucher_blank(table, guest) return voucher_blank(table, guest)
def voucher_info(item): def voucher_info(item: Voucher):
return { return {
"id": item.id, "id": item.id,
"date": item.date.strftime("%H:%M"), "date": item.date.strftime("%H:%M"),

View File

@ -1,20 +1,19 @@
import datetime
import uuid import uuid
from datetime import datetime
from decimal import Decimal from decimal import Decimal
from typing import Optional
import transaction from fastapi import APIRouter, HTTPException, status, Depends, Security
from pyramid.view import view_config
from sqlalchemy import func from sqlalchemy import func
from sqlalchemy.exc import SQLAlchemyError
from sqlalchemy.orm import Session
from barker.models import ( from ...schemas.auth import UserToken
Voucher, import barker.schemas.voucher as schemas
Kot, from ...core.security import get_current_active_user as get_user
Inventory, from ...db.session import SessionLocal
InventoryModifier, from ...models import Voucher, VoucherType, Kot, Product, Inventory, InventoryModifier
VoucherType, from ...routers.voucher import (
Product,
)
from barker.views.voucher import (
get_tax, get_tax,
do_update_settlements, do_update_settlements,
get_bill_id, get_bill_id,
@ -23,65 +22,89 @@ from barker.views.voucher import (
get_guest_book, 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 @router.put("/update/{id_}")
item.food_table_id = json["table"]["id"] def update(
if "customer" in json and "id" in json["customer"]: id_: uuid.UUID,
item.customer_id = json["customer"]["id"] data: schemas.VoucherIn,
if item.voucher_type == VoucherType.KOT and voucher_type != VoucherType.KOT: u: bool, # Update table?
item.date = now p: str, # Print type
item.bill_id = get_bill_id(voucher_type, request.dbsession) g: Optional[uuid.UUID] = None, # Guest book id
item.voucher_type = voucher_type db: Session = Depends(get_db),
item.user_id = uuid.UUID(request.authenticated_userid) user: UserToken = Security(get_user),
item.last_edit_date = now ):
for k in item.kots: try:
for i in k.inventories: now = datetime.now()
i.tax_rate = get_tax(i.tax_rate, voucher_type) update_table = u
i.discount = next( voucher_type = VoucherType[p]
round(Decimal(inv["discount"]), 5) guest_book = get_guest_book(g, db)
for ko in json["kots"]
for inv in ko["inventories"] item: Voucher = db.query(Voucher).filter(Voucher.id == id_).first()
if uuid.UUID(inv["id"]) == i.id
) check_permissions(item, voucher_type, user.permissions)
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() if guest_book is not None:
kot = Kot(item.id, code, item.food_table_id, now, item.user_id) item.pax = guest_book.pax
item.kots.append(kot) item.food_table_id = data.table.id_
request.dbsession.add(kot) if data.customer is not None:
for index, i in enumerate(k["inventories"]): item.customer_id = data.customer.id_
product = request.dbsession.query(Product).filter(Product.id == uuid.UUID(i["product"]["id"])).first() if item.voucher_type == VoucherType.KOT and voucher_type != VoucherType.KOT:
tax_rate = get_tax(product.sale_category.tax.rate, voucher_type) item.date = now
inv = Inventory( item.bill_id = get_bill_id(voucher_type, db)
kot.id, item.voucher_type = voucher_type
product.id, item.user_id = user.id_
round(Decimal(i["quantity"]), 2), item.last_edit_date = now
product.price, for k in item.kots:
round(Decimal(i["discount"]), 5), for i in k.inventories:
i["isHappyHour"], i.tax_rate = get_tax(i.tax_rate, voucher_type)
product.sale_category.tax_id, i.discount = next(
tax_rate, round(inv.discount, 5) for ko in data.kots for inv in ko.inventories if inv.id_ == i.id
index, )
) for k in (k for k in data.kots if k.id_ is None and len(k.inventories) > 0):
kot.inventories.append(inv) code = db.query(func.coalesce(func.max(Kot.code), 0) + 1).scalar()
request.dbsession.add(inv) kot = Kot(item.id, code, item.food_table_id, now, item.user_id)
for m in i["modifiers"]: item.kots.append(kot)
mod = InventoryModifier(None, uuid.UUID(m["id"]), 0) db.add(kot)
inv.modifiers.append(mod) for index, i in enumerate(k.inventories):
request.dbsession.add(mod) product = db.query(Product).filter(Product.id == i.product.id_).first()
do_update_settlements(item, request.dbsession) tax_rate = get_tax(product.sale_category.tax.rate, voucher_type)
if update_table: inv = Inventory(
do_update_table(item, guest_book, request.dbsession) kot.id,
transaction.commit() product.id,
return True 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

View File

@ -27,3 +27,12 @@ class Customer(CustomerIn):
fields = {"id_": "id"} fields = {"id_": "id"}
anystr_strip_whitespace = True anystr_strip_whitespace = True
alias_generator = to_camel alias_generator = to_camel
class CustomerLink(BaseModel):
id_: uuid.UUID = Field(...)
name: Optional[str]
class Config:
fields = {"id_": "id"}
alias_generator = to_camel

View File

@ -9,7 +9,7 @@ from barker.schemas import to_camel
class TaxIn(BaseModel): class TaxIn(BaseModel):
name: str = Field(..., min_length=1) 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: class Config:
fields = {"id_": "id"} fields = {"id_": "id"}

58
barker/schemas/voucher.py Normal file
View File

@ -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

View File

@ -16,22 +16,39 @@ export class AuthService {
public currentUser: Observable<User>; public currentUser: Observable<User>;
constructor(private http: HttpClient) { constructor(private http: HttpClient) {
this.currentUserSubject = new BehaviorSubject<User>(JSON.parse(localStorage.getItem(JWT_USER))); this.checkStorage();
this.currentUser = this.currentUserSubject.asObservable(); 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<User>(null);
return null;
} else {
this.currentUserSubject = new BehaviorSubject<User>(existingToken);
return existingToken;
}
}
public get user(): User { public get user(): User {
const val = this.currentUserSubject.value; let val = this.currentUserSubject.value;
if (val == null) { if (val == null) {
return val; 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) { if (expired) {
this.logout(); this.logout();
return null;
} else {
return this.currentUserSubject.value;
} }
return this.currentUserSubject.value;
} }
login(username: string, password: string, otp: string) { 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; return Date.now() > (this.user.exp - (environment.ACCESS_TOKEN_REFRESH_MINUTES * 60)) * 1000;
} }
expired(): boolean {
return Date.now() > this.user.exp * 1000;
}
logout() { logout() {
// remove user from local storage to log user out // remove user from local storage to log user out
localStorage.removeItem(JWT_USER); localStorage.removeItem(JWT_USER);

View File

@ -10,9 +10,9 @@ const httpOptions = {
headers: new HttpHeaders({'Content-Type': 'application/json'}) headers: new HttpHeaders({'Content-Type': 'application/json'})
}; };
const url = '/v1/vouchers'; const url = '/api/voucher';
const urlMoveTable = '/v1/move-table'; const urlMoveTable = '/api/move-table';
const urlMoveKot = '/v1/move-kot'; const urlMoveKot = '/api/move-kot';
const serviceName = 'VoucherService'; const serviceName = 'VoucherService';
@Injectable({providedIn: 'root'}) @Injectable({providedIn: 'root'})
@ -22,7 +22,7 @@ export class VoucherService {
} }
get(id: string): Observable<Bill> { get(id: string): Observable<Bill> {
return <Observable<Bill>>this.http.get<Bill>(`${url}/${id}`) return <Observable<Bill>>this.http.get<Bill>(`${url}/from-id/${id}`)
.pipe( .pipe(
catchError(this.log.handleError(serviceName, `get id=${id}`)) catchError(this.log.handleError(serviceName, `get id=${id}`))
); );
@ -30,9 +30,6 @@ export class VoucherService {
getFromTable(tableId: string, voucherId: string, guestId: string): Observable<Bill> { getFromTable(tableId: string, voucherId: string, guestId: string): Observable<Bill> {
let params = new HttpParams(); let params = new HttpParams();
if (tableId !== null) {
params = params.set('t', tableId);
}
if (voucherId !== null) { if (voucherId !== null) {
params = params.set('v', voucherId); params = params.set('v', voucherId);
} }
@ -40,7 +37,7 @@ export class VoucherService {
params = params.set('g', guestId); params = params.set('g', guestId);
} }
return <Observable<Bill>>this.http.get<Bill>(`${url}/new`, {params: params}) return <Observable<Bill>>this.http.get<Bill>(`${url}/from-table/${tableId}`, {params: params})
.pipe( .pipe(
catchError(this.log.handleError( catchError(this.log.handleError(
serviceName, serviceName,
@ -54,7 +51,7 @@ export class VoucherService {
if (guest_book_id !== null) { if (guest_book_id !== null) {
options.params = options.params.set('g', guest_book_id); options.params = options.params.set('g', guest_book_id);
} }
return <Observable<boolean>>this.http.post<boolean>(`${url}/new`, voucher, options) return <Observable<boolean>>this.http.post<boolean>(`${url}/save`, voucher, options)
.pipe( .pipe(
catchError(this.log.handleError(serviceName, 'save')) catchError(this.log.handleError(serviceName, 'save'))
); );
@ -65,7 +62,7 @@ export class VoucherService {
if (guest_book_id !== null) { if (guest_book_id !== null) {
options.params = options.params.set('g', guest_book_id); options.params = options.params.set('g', guest_book_id);
} }
return <Observable<boolean>>this.http.put<boolean>(`${url}/${voucher.id}`, voucher, options) return <Observable<boolean>>this.http.put<boolean>(`${url}/update/${voucher.id}`, voucher, options)
.pipe( .pipe(
catchError(this.log.handleError(serviceName, 'update')) catchError(this.log.handleError(serviceName, 'update'))
); );