diff --git a/barker/models/master.py b/barker/models/master.py index bd7059f..fb6a081 100644 --- a/barker/models/master.py +++ b/barker/models/master.py @@ -47,7 +47,8 @@ class FoodTable(Base): id = Column("id", GUID(), primary_key=True, default=uuid.uuid4) name = Column("name", Unicode(255), nullable=False, unique=True) - location = Column("location", Unicode(255), nullable=False) + seats = Column("seats", Numeric, nullable=False) + section = Column("section", Unicode(255), nullable=False) is_active = Column("is_active", Boolean, nullable=False) sort_order = Column("sort_order", Numeric, nullable=False) @@ -56,9 +57,12 @@ class FoodTable(Base): def __name__(self): return self.name - def __init__(self, name=None, location=None, is_active=None, sort_order=0, id=None): + def __init__( + self, name=None, seats=None, section=None, is_active=None, sort_order=0, id=None + ): self.name = name - self.location = location + self.seats = seats + self.section = section self.is_active = is_active self.sort_order = sort_order self.id = id diff --git a/barker/routes.py b/barker/routes.py index 52e9c67..b8e2303 100644 --- a/barker/routes.py +++ b/barker/routes.py @@ -55,7 +55,8 @@ def includeme(config): config.add_route("v1_product_groups_list", "/v1/product-groups") config.add_route("v1_product_group_types_list", "/v1/product-group-types") - config.add_route('product_group_type_list', '/ProductGroupTypes.json') + config.add_route("v1_bills_new", "/v1/bills/new") + config.add_route("v1_bills_id", "/v1/bills/{id}") config.add_route('quantity_sold', '/QuantitySold.json') diff --git a/barker/scripts/fixtures.py b/barker/scripts/fixtures.py index a9c9b2a..4cb1f45 100644 --- a/barker/scripts/fixtures.py +++ b/barker/scripts/fixtures.py @@ -109,8 +109,8 @@ def main(argv=sys.argv): admin.roles.append(roles[0]) dbsession.add(admin) - for name in range(1,20): - dbsession.add(FoodTable(str(name), "", True)) + for name in range(1, 20): + dbsession.add(FoodTable(str(name), 0, "", True)) options = [ SettleOption('Unsettled', False, 1, True, 1), diff --git a/barker/views/food_table.py b/barker/views/food_table.py index 411892f..e44d28c 100644 --- a/barker/views/food_table.py +++ b/barker/views/food_table.py @@ -5,6 +5,7 @@ import transaction from pyramid.view import view_config from barker.models import FoodTable, Overview +from barker.models.validation_exception import ValidationError @view_config( @@ -16,13 +17,22 @@ from barker.models import FoodTable, Overview ) def save(request): json = request.json_body - item = FoodTable( - json["name"], json["location"], json["isActive"], json["sortOrder"] - ) + + name = json.get("name", "").strip() + if name == "": + raise ValidationError("Name cannot be blank") + try: + seats = int(json.get("seats", 0)) + if seats < 0: + raise ValidationError("Seats must be an integer >= 0") + except ValueError: + raise ValidationError("Seats must be an integer >= 0") + section = json.get("section", "").strip() + is_active = json.get("isActive", True) + item = FoodTable(name, seats, section, is_active) request.dbsession.add(item) transaction.commit() - item = request.dbsession.query(FoodTable).filter(FoodTable.id == item.id).first() - return food_table_info(item) + return food_table_info(item.id, request.dbsession) @view_config( @@ -33,19 +43,25 @@ def save(request): trans=True, ) def update(request): - json = request.json_body item = ( request.dbsession.query(FoodTable) .filter(FoodTable.id == uuid.UUID(request.matchdict["id"])) .first() ) - item.name = json["name"] - item.location = json["location"] - item.is_active = json["isActive"] - item.sort_order = json["sortOrder"] + json = request.json_body + item.name = json["name"].strip() + if item.name == "": + raise ValidationError("Name cannot be blank") + try: + item.seats = int(json.get("seats", 0)) + if item.seats < 0: + raise ValidationError("Seats must be an integer >= 0") + except ValueError: + raise ValidationError("Seats must be an integer >= 0") + item.section = json.get("section", "").strip() + item.is_active = json.get("isActive", True) transaction.commit() - item = request.dbsession.query(FoodTable).filter(FoodTable.id == item.id).first() - return food_table_info(item) + return food_table_info(item.id, request.dbsession) @view_config( @@ -63,7 +79,7 @@ def delete(request): ) request.dbsession.delete(item) transaction.commit() - return {} + return {None, request.dbsession} @view_config( @@ -73,16 +89,8 @@ def delete(request): permission="Authenticated", ) def show_id(request): - id_ = request.matchdict["id"] - p = re.compile( - "^[A-Za-z0-9]{8}-[A-Za-z0-9]{4}-[A-Za-z0-9]{4}-[A-Za-z0-9]{4}-[A-Za-z0-9]{12}$" - ) - if p.match(id_): - id_ = uuid.UUID(id_) - item = request.dbsession.query(FoodTable).filter(FoodTable.id == id_).first() - else: - item = request.dbsession.query(FoodTable).filter(FoodTable.name == id_).first() - return food_table_info(item) + id_ = uuid.UUID(request.matchdict["id"]) + return food_table_info(id_, request.dbsession) @view_config( @@ -107,7 +115,7 @@ def show_voucher(request): permission="Tables", ) def show_blank(request): - return {"name": "", "isActive": True, "location": "", "sortOrder": 0} + return food_table_info(None, request.dbsession) @view_config( @@ -129,7 +137,8 @@ def show_list(request): { "id": item.id, "name": item.name, - "location": item.location, + "seats": item.seats, + "section": item.section, "isActive": item.is_active, "sortOrder": item.sort_order, "status": "" if item.status is None else item.status.status, @@ -154,11 +163,22 @@ def sort_order(request): return True -def food_table_info(item): +def food_table_info(item, dbsession): + if item is None: + return { + "name": "", + "seats": 0, + "section": "", + "isActive": True, + "sortOrder": 0 + } + if type(item) == uuid.UUID: + item = dbsession.query(FoodTable).filter(FoodTable.id == item).first() return { "id": item.id, "name": item.name, - "location": item.location, + "seats":item.seats, + "section": item.section, "isActive": item.is_active, "status": "" if item.status is None else item.status.status, "sortOrder": item.sort_order, diff --git a/barker/views/guest_book.py b/barker/views/guest_book.py index a1b8c87..3331c46 100644 --- a/barker/views/guest_book.py +++ b/barker/views/guest_book.py @@ -1,12 +1,10 @@ -import re import uuid from datetime import datetime, date, timedelta import transaction from pyramid.view import view_config -from sqlalchemy import desc -from barker.models import FoodTable, Overview, GuestBook, Customer +from barker.models import GuestBook, Customer @view_config(request_method='PUT', route_name='v1_guest_book_new', renderer='json', permission='Users', trans=True) @@ -73,7 +71,7 @@ def show_list(request): 'pax': item.pax, 'status': '' if item.status is None else item.status.status }) - return guest_book + return {"date": date_, "list": guest_book} def guest_book_info(item): diff --git a/barker/views/product.py b/barker/views/product.py index d7ba579..5e14ede 100644 --- a/barker/views/product.py +++ b/barker/views/product.py @@ -85,6 +85,8 @@ def update(request): ) json = request.json_body item.name = json["name"].strip() + if item.name == "": + raise ValidationError("Name cannot be blank") item.units = json["units"].strip() item.product_group_id = uuid.UUID(json["productGroup"]["id"]) item.tax_id = uuid.UUID(json["tax"]["id"]) @@ -148,8 +150,7 @@ def show_blank(request): ) def show_id(request): id_ = uuid.UUID(request.matchdict["id"]) - item = request.dbsession.query(Product).filter(Product.id == id_).first() - return product_info(item.id, request.dbsession) + return product_info(id_, request.dbsession) @view_config( diff --git a/barker/views/voucher.py b/barker/views/voucher.py index 8fd3023..564c09f 100644 --- a/barker/views/voucher.py +++ b/barker/views/voucher.py @@ -21,71 +21,77 @@ from barker.models import ( ) -@view_config(request_method='PUT', route_name='voucher', renderer='json', trans=True) +@view_config(request_method="PUT", route_name="voucher", renderer="json", trans=True) def save(request): - update_table = request.GET['u'] + update_table = request.GET["u"] json = request.json_body - if not json['Printed'] and 'Print Kot' not in request.effective_principals: + if not json["Printed"] and "Print Kot" not in request.effective_principals: raise HTTPForbidden("You are not allowed to print a kot") - if json['Printed'] and 'Print Bill' not in request.effective_principals: + if json["Printed"] and "Print Bill" not in request.effective_principals: raise HTTPForbidden("You are not allowed to print bill") item = save_voucher(json, request.dbsession) if update_table: status = "printed" if item.is_printed else "running" - item.status = Overview(voucher_id=None, food_table_id=item.food_table_id, status=status) + item.status = Overview( + voucher_id=None, food_table_id=item.food_table_id, status=status + ) request.dbsession.add(item.status) transaction.commit() item = request.dbsession.query(Voucher).filter(Voucher.id == item.id).first() return voucher_info(item) -@view_config(request_method='POST', route_name='voucher_id', renderer='json', trans=True) +@view_config( + request_method="POST", route_name="voucher_id", renderer="json", trans=True +) def update(request): now = datetime.now() - update_table = request.GET['u'] + update_table = request.GET["u"] json = request.json_body - id = uuid.UUID(request.matchdict['id']) + id = uuid.UUID(request.matchdict["id"]) item = request.dbsession.query(Voucher).filter(Voucher.id == id).first() - if not json['Printed'] and 'Print Kot' not in request.effective_principals: + if not json["Printed"] and "Print Kot" not in request.effective_principals: raise HTTPForbidden("You are not allowed to print a kot") - if json['Printed'] and 'Print Bill' not in request.effective_principals: + if json["Printed"] and "Print Bill" not in request.effective_principals: raise HTTPForbidden("You are not allowed to print bill") - if item.is_printed and 'Edit Printed Bill' not in request.effective_principals: + if item.is_printed and "Edit Printed Bill" not in request.effective_principals: raise HTTPForbidden("You are not allowed to edit a printed bill") - if item.is_printed and not json['Printed']: + if item.is_printed and not json["Printed"]: transaction.abort() raise ValidationFailure("This Bill is already printed\nCannot add a Kot to it.") if item.is_void: transaction.abort() - raise ValidationFailure("This Bill is already void.\nReason: {0}".format(item.void_reason)) + raise ValidationFailure( + "This Bill is already void.\nReason: {0}".format(item.void_reason) + ) - if item.is_printed and not json['Printed']: + if item.is_printed and not json["Printed"]: transaction.abort() raise ValidationFailure("This Bill is already printed\nCannot add a Kot to it.") - item.pax = json['Pax'] - item.food_table_id = json['Table']['FoodTableID'] - item.customer_id = json['Customer']['CustomerID'] - item.voucher_type = json['VoucherType'] - if not item.is_printed and json['Printed']: + item.pax = json["Pax"] + item.food_table_id = json["Table"]["FoodTableID"] + item.customer_id = json["Customer"]["CustomerID"] + item.voucher_type = json["VoucherType"] + if not item.is_printed and json["Printed"]: item.date = now type = [1, 3] if item.voucher_type in [1, 3] else [item.voucher_type] - item.bill_id = request.dbsession.query( - func.coalesce(func.max(Voucher.bill_id), 0) + 1 - ).filter( - Voucher.voucher_type.in_(type) - ).scalar() + item.bill_id = ( + request.dbsession.query(func.coalesce(func.max(Voucher.bill_id), 0) + 1) + .filter(Voucher.voucher_type.in_(type)) + .scalar() + ) - item.is_printed = item.is_printed or json['Printed'] - item.user_id = json['User']['UserID'] + item.is_printed = item.is_printed or json["Printed"] + item.user_id = json["User"]["UserID"] item.last_edit_date = now for k in item.kots: for i in k.inventories: @@ -93,29 +99,56 @@ def update(request): i.service_tax_rate, i.vat_rate, item.voucher_type ) i.discount = next( - Decimal(inv['Discount']) for ko in json['Kots'] for inv in ko['Inventories'] if - uuid.UUID(inv['InventoryID']) == i.id + Decimal(inv["Discount"]) + for ko in json["Kots"] + for inv in ko["Inventories"] + if uuid.UUID(inv["InventoryID"]) == i.id ) - for k in (k for k in json['Kots'] if k['KotID'] == '00000000-0000-0000-0000-000000000000'): - kot = Kot(item.id, item.food_table_id, item.date, item.user_id, dbsession=request.dbsession) + for k in ( + k for k in json["Kots"] if k["KotID"] == "00000000-0000-0000-0000-000000000000" + ): + kot = Kot( + item.id, + item.food_table_id, + item.date, + item.user_id, + dbsession=request.dbsession, + ) item.kots.append(kot) request.dbsession.add(kot) - for index, i in enumerate(k['Inventories']): - st, vat = get_st_vat(i['ServiceTaxRate'], i['VatRate'], json['VoucherType']) - inv = Inventory(kot.id, uuid.UUID(i['ProductID']), i['Quantity'], i['Price'], i['Discount'], - i['IsHappyHour'], i['ServiceTaxID'], st, i['VatID'], vat, index) + for index, i in enumerate(k["Inventories"]): + st, vat = get_st_vat(i["ServiceTaxRate"], i["VatRate"], json["VoucherType"]) + inv = Inventory( + kot.id, + uuid.UUID(i["ProductID"]), + i["Quantity"], + i["Price"], + i["Discount"], + i["IsHappyHour"], + i["ServiceTaxID"], + st, + i["VatID"], + vat, + index, + ) kot.inventories.append(inv) request.dbsession.add(inv) - for m in i['Modifiers']: - mod = InventoryModifier(None, uuid.UUID(m['ModifierID']), 0) + for m in i["Modifiers"]: + mod = InventoryModifier(None, uuid.UUID(m["ModifierID"]), 0) inv.modifiers.append(mod) request.dbsession.add(mod) get_settlements(item, request.dbsession) if update_table: - vft = request.dbsession.query(Overview).filter(Overview.voucher_id == item.id).first() + vft = ( + request.dbsession.query(Overview) + .filter(Overview.voucher_id == item.id) + .first() + ) status = "printed" if item.is_printed else "running" if vft is None: - item.status = Overview(voucher_id=None, food_table_id=item.food_table_id, status=status) + item.status = Overview( + voucher_id=None, food_table_id=item.food_table_id, status=status + ) request.dbsession.add(item.status) else: vft.status = status @@ -125,17 +158,27 @@ def update(request): return voucher_info(item) -@view_config(request_method='POST', route_name='voucher_settle', renderer='json', permission='Settle Bill', trans=False) +@view_config( + request_method="POST", + route_name="voucher_settle", + renderer="json", + permission="Settle Bill", + trans=False, +) def settle_voucher(request): - update_table = request.GET['u'] + update_table = request.GET["u"] json = request.json_body - id = uuid.UUID(request.matchdict['id']) - item = request.dbsession.query(Voucher).filter(Voucher.id == id).first() + id_ = uuid.UUID(request.matchdict["id"]) + item = request.dbsession.query(Voucher).filter(Voucher.id == id_).first() - allowed = [SettleOption.AMOUNT(), SettleOption.ROUND_OFF(), SettleOption.UNSETTLED()] - for i in (j for j in json if j['Amount'] != 0): - amount = i['Amount'] - so = i['Settled'] + allowed = [ + SettleOption.AMOUNT(), + SettleOption.ROUND_OFF(), + SettleOption.UNSETTLED(), + ] + for i in (j for j in json if j["Amount"] != 0): + amount = i["Amount"] + so = i["Settled"] so_settled = [s for s in item.settlements if s.settled == so] if len(so_settled) == 1: so_settled[0].amount = amount @@ -150,52 +193,72 @@ def settle_voucher(request): unsettled = get_settlements(item, request.dbsession) if unsettled == 0 and update_table: - request.dbsession.query(Overview).filter(Overview.voucher_id == item.id).delete() + request.dbsession.query(Overview).filter( + Overview.voucher_id == item.id + ).delete() transaction.commit() item = request.dbsession.query(Voucher).filter(Voucher.id == item.id).first() return voucher_info(item) -@view_config(request_method='POST', route_name='voucher_reprint', renderer='json', permission='Edit Printed Bill', - trans=True) # Permission error +@view_config( + request_method="POST", + route_name="voucher_reprint", + renderer="json", + permission="Edit Printed Bill", + trans=True, +) # Permission error def voucher_change(request): json = request.json_body - id = uuid.UUID(request.matchdict['id']) + id_ = uuid.UUID(request.matchdict["id"]) item = save_voucher(json, request.dbsession) - old = request.dbsession.query(Voucher).filter(Voucher.id == id).first() + old = request.dbsession.query(Voucher).filter(Voucher.id == id_).first() old.void = True - old.void_reason = "Bill Discounted / Changed. New Bill ID is {0}".format(item.full_bill_id) + old.void_reason = "Bill Discounted / Changed. New Bill ID is {0}".format( + item.full_bill_id + ) # TODO: Set the Void Settlement if old.status is None: - item.status = Overview(voucher_id=None, food_table_id=item.food_table_id, status="printed") + item.status = Overview( + voucher_id=None, food_table_id=item.food_table_id, status="printed" + ) request.dbsession.add(item.status) else: - request.dbsession.query( - Overview - ).filter( - Overview.voucher_id == old.id - ).update({Overview.voucher_id: item.id}) + request.dbsession.query(Overview).filter(Overview.voucher_id == old.id).update( + {Overview.voucher_id: item.id} + ) transaction.commit() item = request.dbsession.query(Voucher).filter(Voucher.id == item.id).first() return voucher_info(item) -@view_config(request_method='POST', route_name='voucher_void', renderer='json', permission='Void Bill', trans=True) +@view_config( + request_method="POST", + route_name="voucher_void", + renderer="json", + permission="Void Bill", + trans=True, +) def void_voucher(request): - update_table = request.GET['u'] + update_table = request.GET["u"] json = request.json_body - id = uuid.UUID(request.matchdict['id']) - item = request.dbsession.query(Voucher).filter(Voucher.id == id).first() + id_ = uuid.UUID(request.matchdict["id"]) + item = request.dbsession.query(Voucher).filter(Voucher.id == id_).first() item.void = True - item.void_reason = json['Reason'] + item.void_reason = json["Reason"] amount = round(-1 * sum(i.amount for k in item.kots for i in k.inventories), 5) * -1 s = Settlement(item.id, SettleOption.VOID(), amount) item.settlements.append(s) request.dbsession.add(s) - allowed = [SettleOption.AMOUNT(), SettleOption.ROUND_OFF(), SettleOption.UNSETTLED(), SettleOption.VOID()] + allowed = [ + SettleOption.AMOUNT(), + SettleOption.ROUND_OFF(), + SettleOption.UNSETTLED(), + SettleOption.VOID(), + ] for i in (s for s in item.settlements if s.settled not in allowed): item.settlements.remove(i) request.dbsession.delete(i) @@ -208,56 +271,73 @@ def void_voucher(request): return voucher_info(item) -@view_config(request_method='POST', route_name='voucher_split', renderer='json', permission='Split Bill', trans=True) +@view_config( + request_method="POST", + route_name="voucher_split", + renderer="json", + permission="Split Bill", + trans=True, +) def split_voucher(request): json = request.json_body - id = uuid.UUID(request.matchdict['id']) - item = request.dbsession.query(Voucher).filter(Voucher.id == id).first() + id_ = uuid.UUID(request.matchdict["id"]) + item = request.dbsession.query(Voucher).filter(Voucher.id == id_).first() item.void = True - item.void_reason = 'Bill Split' + item.void_reason = "Bill Split" # TODO: Set the Void Settlement - new_one = save_voucher(json['One'], request.dbsession) - new_two = save_voucher(json['Two'], request.dbsession) + new_one = save_voucher(json["One"], request.dbsession) + new_two = save_voucher(json["Two"], request.dbsession) status = "printed" if item.is_printed else "running" - new_one.status = Overview(voucher_id=None, food_table_id=new_one.food_table_id, status=status) + new_one.status = Overview( + voucher_id=None, food_table_id=new_one.food_table_id, status=status + ) request.dbsession.add(new_one.status) - request.dbsession.query( - Overview - ).filter( - Overview.voucher_id == item.id - ).update({Overview.voucher_id: new_two.id}) + request.dbsession.query(Overview).filter(Overview.voucher_id == item.id).update( + {Overview.voucher_id: new_two.id} + ) transaction.commit() -@view_config(request_method='GET', route_name='voucher_id', renderer='json', permission='Authenticated') +@view_config( + request_method="GET", + route_name="voucher_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() + id_ = uuid.UUID(request.matchdict["id"]) + item = request.dbsession.query(Voucher).filter(Voucher.id == id_).first() return voucher_info(item) -@view_config(request_method='GET', route_name='voucher', request_param='b', renderer='json', permission='Authenticated') +@view_config( + request_method="GET", + route_name="voucher", + request_param="b", + renderer="json", + permission="Authenticated", +) def show(request): - bill_id = request.GET['b'] + bill_id = request.GET["b"] item = request.dbsession.query(Voucher) - if re.compile('^\d{2,}-\d{4}$').match(bill_id): + 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]) + Voucher.bill_id == int(bill_id.replace("-", "")), + Voucher.voucher_type.in_([1, 3]), ) - elif re.compile('^NC-\d+$').match(bill_id): + elif re.compile("^NC-\d+$").match(bill_id): item = item.filter( - Voucher.bill_id == int(bill_id.replace('NC-', '')), - Voucher.voucher_type == 2 + Voucher.bill_id == int(bill_id.replace("NC-", "")), + Voucher.voucher_type == 2, ) - elif re.compile('^ST-\d+$').match(bill_id): + elif re.compile("^ST-\d+$").match(bill_id): item = item.filter( - Voucher.bill_id == int(bill_id.replace('ST-', '')), - Voucher.voucher_type == 4 + Voucher.bill_id == int(bill_id.replace("ST-", "")), + Voucher.voucher_type == 4, ) item = item.first() if item is None: @@ -267,63 +347,67 @@ def show(request): def voucher_info(item): return { - 'VoucherID': item.id, - 'Date': item.date.strftime('%d-%b-%Y %H:%M:%S'), - 'Pax': item.pax, - 'User': {'UserID': item.user_id, 'Name': item.user.name}, - 'CreationDate': item.creation_date.strftime('%d-%b-%Y %H:%M:%S'), - 'LastEditDate': item.last_edit_date.strftime('%d-%b-%Y %H:%M:%S'), - 'BillID': item.bill_id, - 'Table': {'FoodTableID': item.food_table_id, 'Name': item.food_table.name}, - 'Customer': {'CustomerID': item.customer_id, 'Name': item.customer.name}, - 'Settlements': [], - 'Narration': item.narration, - 'Void': item.is_void, - 'VoidReason': item.void_reason, - 'Printed': item.is_printed, - 'VoucherType': item.voucher_type, - 'KotID': item.kot_id, - 'Kots': [ + "id": item.id, + "date": item.date.strftime("%d-%b-%Y %H:%M:%S"), + "pax": item.pax, + "user": {"id": item.user_id, "name": item.user.name}, + "creationDate": item.creation_date.strftime("%d-%b-%Y %H:%M:%S"), + "lastEditDate": item.last_edit_date.strftime("%d-%b-%Y %H:%M:%S"), + "billId": item.bill_id, + "table": {"id": item.food_table_id, "name": item.food_table.name}, + "customer": {"id": item.customer_id, "name": item.customer.name}, + "settlements": [], + "narration": item.narration, + "void": item.is_void, + "voidReason": item.void_reason, + "printed": item.is_printed, + "voucherType": item.voucher_type, + "kotId": item.kot_id, + "kots": [ { - 'KotID': k.id, 'Code': k.code, 'Date': k.date.strftime('%d-%b-%Y %H:%M:%S'), - 'User': {'UserID': k.user_id, 'Name': k.user.name}, - 'Inventories': [ + "id": k.id, + "code": k.code, + "date": k.date.strftime("%d-%b-%Y %H:%M:%S"), + "user": {"id": k.user_id, "name": k.user.name}, + "inventories": [ { - 'InventoryID': i.id, - 'SortOrder': i.sort_order, - 'Product': - { - 'ProductID': i.product_id, - 'Name': i.product.name, - 'Units': i.product.units, - 'ProductGroup': - { - 'ProductGroupID': i.product.product_group_id, - 'Name': i.product.product_group.name, - 'GroupType': i.product.product_group.group_type, - 'DiscountLimit': i.product.product_group.discount_limit - } + "id": i.id, + "sortOrder": i.sort_order, + "product": { + "id": i.product_id, + "name": i.product.name, + "units": i.product.units, + "productGroup": { + "id": i.product.product_group_id, + "name": i.product.product_group.name, + "groupType": i.product.product_group.group_type, + "discountLimit": i.product.product_group.discount_limit, }, - 'Quantity': i.quantity, - 'Price': i.price, - 'IsHappyHour': i.is_happy_hour, - 'ServiceTaxRate': i.service_tax_rate, - 'VatRate': i.vat_rate, - 'ServiceTax': {'TaxID': i.service_tax_id, 'Name': i.service_tax.name}, - 'Vat': {'TaxID': i.vat_id, 'Name': i.vat.name}, - 'Discount': i.discount, - 'InventoryModifier': [ + }, + "quantity": i.quantity, + "price": i.price, + "isHappyHour": i.is_happy_hour, + "taxRate": i.tax_rate, + "tax": {"id": i.vat_id, "name": i.vat.name}, + "discount": i.discount, + "inventoryModifier": [ { - 'Modifier': { - 'ModifierID': m.modifier.id, - 'Name': m.modifier.name, - 'ShowInBill': m.modifier.show_in_bill + "modifier": { + "id": m.modifier.id, + "name": m.modifier.name, + "showInBill": m.modifier.show_in_bill, }, - 'Price': m.price - } for m in i.modifiers] - } for i in k.inventories] - } for k in item.kots], - 'Reprints': [] + "price": m.price, + } + for m in i.modifiers + ], + } + for i in k.inventories + ], + } + for k in item.kots + ], + "reprints": [], } @@ -337,7 +421,9 @@ def get_st_vat(st, vat, voucher_type): def get_settlements(voucher, dbsession): - amount = round(-1 * sum(sum(i.amount for i in k.inventories) for k in voucher.kots), 5) + amount = round( + -1 * sum(sum(i.amount for i in k.inventories) for k in voucher.kots), 5 + ) so_amount = [s for s in voucher.settlements if s.settled == SettleOption.AMOUNT()] if len(so_amount) == 1: so_amount[0].amount = amount @@ -347,7 +433,9 @@ def get_settlements(voucher, dbsession): dbsession.add(s) round_off = round(amount) - amount - so_round_off = [s for s in voucher.settlements if s.settled == SettleOption.ROUND_OFF()] + so_round_off = [ + s for s in voucher.settlements if s.settled == SettleOption.ROUND_OFF() + ] if len(so_round_off) == 1 and round_off != 0: so_round_off[0].amount = round_off elif len(so_round_off) == 1 and round_off == 0: @@ -358,8 +446,12 @@ def get_settlements(voucher, dbsession): voucher.settlements.append(s) dbsession.add(s) - unsettled = sum(s.amount for s in voucher.settlements if s.settled != SettleOption.UNSETTLED()) - so_unsettled = [s for s in voucher.settlements if s.settled == SettleOption.UNSETTLED()] + unsettled = sum( + s.amount for s in voucher.settlements if s.settled != SettleOption.UNSETTLED() + ) + so_unsettled = [ + s for s in voucher.settlements if s.settled == SettleOption.UNSETTLED() + ] if len(so_unsettled) == 1 and unsettled != 0: so_unsettled[0].amount = unsettled elif len(so_unsettled) == 1 and unsettled == 0: @@ -373,21 +465,41 @@ def get_settlements(voucher, dbsession): def save_voucher(json, dbsession): - item = Voucher(json['Pax'], json['Table']['FoodTableID'], json['Customer']['CustomerID'], json['Printed'], - json['VoucherType'], json['User']['UserID'], dbsession) + item = Voucher( + json["Pax"], + json["Table"]["FoodTableID"], + json["Customer"]["CustomerID"], + json["Printed"], + json["VoucherType"], + json["User"]["UserID"], + dbsession, + ) dbsession.add(item) - for k in json['Kots']: - kot = Kot(item.id, item.food_table_id, item.date, item.user_id, dbsession=dbsession) + for k in json["Kots"]: + kot = Kot( + item.id, item.food_table_id, item.date, item.user_id, dbsession=dbsession + ) item.kots.append(kot) dbsession.add(kot) - for index, i in enumerate(k['Inventories']): - st, vat = get_st_vat(i['ServiceTaxRate'], i['VatRate'], json['VoucherType']) - inv = Inventory(kot.id, uuid.UUID(i['ProductID']), i['Quantity'], i['Price'], i['Discount'], - i['IsHappyHour'], i['ServiceTaxID'], st, i['VatID'], vat, index) + for index, i in enumerate(k["Inventories"]): + st, vat = get_st_vat(i["ServiceTaxRate"], i["VatRate"], json["VoucherType"]) + inv = Inventory( + kot.id, + uuid.UUID(i["ProductID"]), + i["Quantity"], + i["Price"], + i["Discount"], + i["IsHappyHour"], + i["ServiceTaxID"], + st, + i["VatID"], + vat, + index, + ) kot.inventories.append(inv) dbsession.add(inv) - for m in i['Modifiers']: - mod = InventoryModifier(None, uuid.UUID(m['ModifierID']), 0) + for m in i["Modifiers"]: + mod = InventoryModifier(None, uuid.UUID(m["ModifierID"]), 0) inv.modifiers.append(mod) dbsession.add(mod) get_settlements(item, dbsession) diff --git a/bookie/src/app/app-routing.module.ts b/bookie/src/app/app-routing.module.ts index f3291a7..8733fe8 100644 --- a/bookie/src/app/app-routing.module.ts +++ b/bookie/src/app/app-routing.module.ts @@ -5,6 +5,10 @@ import {LogoutComponent} from "./auth/logout/logout.component"; import {HomeComponent} from "./home/home.component"; const routes: Routes = [ + { + path: 'bills', + loadChildren: () => import('./bills/bills.module').then(mod => mod.BillsModule) + }, { path: 'guest-book', loadChildren: () => import('./guest-book/guest-book.module').then(mod => mod.GuestBookModule) diff --git a/bookie/src/app/core/table.ts b/bookie/src/app/core/table.ts index e743881..a8e3836 100644 --- a/bookie/src/app/core/table.ts +++ b/bookie/src/app/core/table.ts @@ -1,6 +1,7 @@ export class Table { id: string; name: string; - location: string; + seats: number; + section: string; isActive: boolean; } diff --git a/bookie/src/app/guest-book/guest-book-detail/guest-book-detail.component.css b/bookie/src/app/guest-book/guest-book-detail/guest-book-detail.component.css index 194f9ec..e69de29 100644 --- a/bookie/src/app/guest-book/guest-book-detail/guest-book-detail.component.css +++ b/bookie/src/app/guest-book/guest-book-detail/guest-book-detail.component.css @@ -1,27 +0,0 @@ -.full-width { - width: 100%; -} - -.shipping-card { - min-width: 120px; - margin: 20px auto; -} - -.mat-radio-button { - display: block; - margin: 5px 0; -} - -.row { - display: flex; - flex-direction: row; -} - -.col { - flex: 1; - margin-right: 20px; -} - -.col:last-child { - margin-right: 0; -} diff --git a/bookie/src/app/guest-book/guest-book-detail/guest-book-detail.component.html b/bookie/src/app/guest-book/guest-book-detail/guest-book-detail.component.html index ba77ba0..1e1fb70 100644 --- a/bookie/src/app/guest-book/guest-book-detail/guest-book-detail.component.html +++ b/bookie/src/app/guest-book/guest-book-detail/guest-book-detail.component.html @@ -1,51 +1,52 @@ -
- - - Shipping Information - +
+ + + Guest Details + -
-
- - - -
-
-
-
- - + +
+ + Name + Name is required
-
-
-
- - +
+ + Phone +
-
-
-
- - - {{phone.value.length}} / 10 - -
-
-
-
- +
+ + Pax
-
+
+ + Company + + +
+
+ + Address + + +
+ - + - +
diff --git a/bookie/src/app/guest-book/guest-book-detail/guest-book-detail.component.ts b/bookie/src/app/guest-book/guest-book-detail/guest-book-detail.component.ts index be4b520..16bdec8 100644 --- a/bookie/src/app/guest-book/guest-book-detail/guest-book-detail.component.ts +++ b/bookie/src/app/guest-book/guest-book-detail/guest-book-detail.component.ts @@ -1,19 +1,17 @@ -import {Component, OnInit} from '@angular/core'; -import {FormArray, FormBuilder, FormGroup, Validators} from '@angular/forms'; -import {RoleService} from "../../role/role.service"; -import {GuestBookService} from "../guest-book.service"; -import {ToasterService} from "../../core/toaster.service"; -import {Role} from "../../role/role"; -import {GuestBook} from "../guest-book"; -import {ActivatedRoute, Router} from "@angular/router"; -import {User} from "../../user/user"; +import { AfterViewInit, Component, ElementRef, OnInit, ViewChild } from '@angular/core'; +import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { GuestBookService } from "../guest-book.service"; +import { ToasterService } from "../../core/toaster.service"; +import { GuestBook } from "../guest-book"; +import { ActivatedRoute, Router } from "@angular/router"; @Component({ selector: 'app-guest-book-detail', templateUrl: './guest-book-detail.component.html', styleUrls: ['./guest-book-detail.component.css'] }) -export class GuestBookDetailComponent implements OnInit { +export class GuestBookDetailComponent implements OnInit, AfterViewInit { + @ViewChild('name', { static: true }) nameElement: ElementRef; form: FormGroup; item: GuestBook; @@ -44,6 +42,12 @@ export class GuestBookDetailComponent implements OnInit { }); } + ngAfterViewInit() { + setTimeout(() => { + this.nameElement.nativeElement.focus(); + }, 0); + } + showItem(item: GuestBook) { this.item = item; this.form.get('company').setValue(item.company); @@ -53,12 +57,12 @@ export class GuestBookDetailComponent implements OnInit { this.form.get('address').setValue(item.address); } - onSubmit() { + save() { this.ser.saveOrUpdate(this.getItem()) .subscribe( (result) => { this.toaster.show('Success', ''); - this.router.navigateByUrl('/guest-book/list'); + this.router.navigateByUrl('/guest-book'); }, (error) => { this.toaster.show('Danger', error.error); diff --git a/bookie/src/app/guest-book/guest-book-list-resolver.service.ts b/bookie/src/app/guest-book/guest-book-list-resolver.service.ts index cdbbf95..fc8ac6f 100644 --- a/bookie/src/app/guest-book/guest-book-list-resolver.service.ts +++ b/bookie/src/app/guest-book/guest-book-list-resolver.service.ts @@ -1,18 +1,18 @@ -import {Injectable} from '@angular/core'; -import {ActivatedRouteSnapshot, Resolve, RouterStateSnapshot} from '@angular/router'; -import {GuestBook} from "./guest-book"; -import {Observable} from 'rxjs/internal/Observable'; -import {GuestBookService} from './guest-book.service'; +import { Injectable } from '@angular/core'; +import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot } from '@angular/router'; +import { Observable } from 'rxjs/internal/Observable'; +import { GuestBookList } from "./guest-book"; +import { GuestBookService } from './guest-book.service'; @Injectable({ providedIn: 'root' }) -export class GuestBookListResolver implements Resolve { +export class GuestBookListResolver implements Resolve { constructor(private ser: GuestBookService) { } - resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable { + resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable { return this.ser.list(null); } } diff --git a/bookie/src/app/guest-book/guest-book-list/guest-book-list-datasource.ts b/bookie/src/app/guest-book/guest-book-list/guest-book-list-datasource.ts index 4aeb8d3..f1d942e 100644 --- a/bookie/src/app/guest-book/guest-book-list/guest-book-list-datasource.ts +++ b/bookie/src/app/guest-book/guest-book-list/guest-book-list-datasource.ts @@ -1,9 +1,6 @@ -import {DataSource} from '@angular/cdk/collections'; -import { MatPaginator } from '@angular/material/paginator'; -import { MatSort } from '@angular/material/sort'; -import {map, tap} from 'rxjs/operators'; -import {Observable, of as observableOf, merge} from 'rxjs'; -import {GuestBook} from "../guest-book"; +import { DataSource } from '@angular/cdk/collections'; +import { Observable } from 'rxjs'; +import { GuestBook } from "../guest-book"; /** * Data source for the GuestBookList view. This class should @@ -11,31 +8,14 @@ import {GuestBook} from "../guest-book"; * (including sorting, pagination, and filtering). */ export class GuestBookListDataSource extends DataSource { - private dataObservable: Observable; - constructor( - private paginator: MatPaginator, - private sort: MatSort, - public data: GuestBook[] + constructor(private readonly dataObs: Observable ) { super(); } connect(): Observable { - this.dataObservable = observableOf(this.data); - const dataMutations = [ - this.dataObservable, - this.paginator.page, - this.sort.sortChange - ]; - - return merge(...dataMutations).pipe( - map((x: any) => { - return this.getPagedData(this.getSortedData([...this.data])); - }), - tap((x: GuestBook[]) => this.paginator.length = x.length) - ); - + return this.dataObs; } /** @@ -44,31 +24,4 @@ export class GuestBookListDataSource extends DataSource { */ disconnect() { } - - private getPagedData(data: GuestBook[]) { - const startIndex = this.paginator.pageIndex * this.paginator.pageSize; - return data.splice(startIndex, this.paginator.pageSize); - } - - private getSortedData(data: GuestBook[]) { - if (!this.sort.active || this.sort.direction === '') { - return data; - } - - return data.sort((a, b) => { - const isAsc = this.sort.direction === 'asc'; - switch (this.sort.active) { - case 'name': - return compare(a.name, b.name, isAsc); - case 'id': - return compare(+a.id, +b.id, isAsc); - default: - return 0; - } - }); - } -} - -function compare(a, b, isAsc) { - return (a < b ? -1 : 1) * (isAsc ? 1 : -1); } diff --git a/bookie/src/app/guest-book/guest-book-list/guest-book-list.component.html b/bookie/src/app/guest-book/guest-book-list/guest-book-list.component.html index 8313222..bc48781 100644 --- a/bookie/src/app/guest-book/guest-book-list/guest-book-list.component.html +++ b/bookie/src/app/guest-book/guest-book-list/guest-book-list.component.html @@ -1,70 +1,66 @@ -
-
-
+ + + Guest List + + add_box + Add + + + + + - +
+ + + + + S. No + {{row.serial}} + - - - - - - + + + Name + {{row.name}} + - - - - - + + + Phone + {{row.phone}} + - - - - - + + + Pax + {{row.pax}} + - - - - - + + + Action + + + + + + - - - Action - - - - - - - - - -
S. No{{row.serial}}Name{{row.name}}Phone{{row.phone}}Pax{{row.pax}}
- - - -
+ + + + + diff --git a/bookie/src/app/guest-book/guest-book-list/guest-book-list.component.ts b/bookie/src/app/guest-book/guest-book-list/guest-book-list.component.ts index 720af3a..de13bcf 100644 --- a/bookie/src/app/guest-book/guest-book-list/guest-book-list.component.ts +++ b/bookie/src/app/guest-book/guest-book-list/guest-book-list.component.ts @@ -1,14 +1,12 @@ -import {AfterViewInit, Component, ElementRef, OnInit, ViewChild} from '@angular/core'; -import { MatPaginator } from '@angular/material/paginator'; -import { MatSort } from '@angular/material/sort'; -import {GuestBookListDataSource} from './guest-book-list-datasource'; -import {ActivatedRoute} from "@angular/router"; -import {FormBuilder, FormGroup} from "@angular/forms"; -import {debounceTime, distinctUntilChanged, map} from "rxjs/operators"; -import {GuestBook} from "../guest-book"; -import {Observable} from "rxjs"; +import { Component, OnInit } from '@angular/core'; +import { ActivatedRoute } from "@angular/router"; +import { FormBuilder, FormGroup } from "@angular/forms"; +import { BehaviorSubject } from "rxjs"; +import { map } from "rxjs/operators"; import * as moment from 'moment'; -import {GuestBookService} from "../guest-book.service"; +import {GuestBook, GuestBookList} from "../guest-book"; +import { GuestBookService } from "../guest-book.service"; +import { GuestBookListDataSource } from './guest-book-list-datasource'; @Component({ selector: 'app-guest-book-list', @@ -16,17 +14,15 @@ import {GuestBookService} from "../guest-book.service"; styleUrls: ['./guest-book-list.component.css'] }) export class GuestBookListComponent implements OnInit { - @ViewChild(MatPaginator, { static: true }) paginator: MatPaginator; - @ViewChild(MatSort, { static: true }) sort: MatSort; dataSource: GuestBookListDataSource; - filter: Observable; form: FormGroup; - list: GuestBook[]; + data: BehaviorSubject; /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */ displayedColumns = ['sno', 'name', 'phone', 'pax', 'action']; constructor(private route: ActivatedRoute, private fb: FormBuilder, private ser: GuestBookService) { this.createForm(); + this.data = new BehaviorSubject([]); this.listenToDateChange(); } @@ -41,18 +37,19 @@ export class GuestBookListComponent implements OnInit { map(x => moment(x).format('DD-MMM-YYYY')) ).subscribe(x => { return this.ser.list(x) - .subscribe((list: GuestBook[]) => { - this.list = list; - this.dataSource = new GuestBookListDataSource(this.paginator, this.sort, this.list); + .subscribe((list: GuestBookList) => { + console.log("date changed"); + this.data.next(list.list); }); }); } ngOnInit() { this.route.data - .subscribe((data: { list: GuestBook[] }) => { - this.list = data.list; + .subscribe((data: { list: GuestBookList }) => { + this.data.next(data.list.list); + this.form.setValue({"date": moment(data.list.date, 'DD-MMM-YYYY').toDate()}); }); - this.dataSource = new GuestBookListDataSource(this.paginator, this.sort, this.list); + this.dataSource = new GuestBookListDataSource(this.data); } } diff --git a/bookie/src/app/guest-book/guest-book.module.ts b/bookie/src/app/guest-book/guest-book.module.ts index 507e5b1..9bd8096 100644 --- a/bookie/src/app/guest-book/guest-book.module.ts +++ b/bookie/src/app/guest-book/guest-book.module.ts @@ -11,9 +11,10 @@ import { MatRadioModule } from '@angular/material/radio'; import { MatSelectModule } from '@angular/material/select'; import { MatSortModule } from '@angular/material/sort'; import { MatTableModule } from '@angular/material/table'; -import {MomentDateAdapter} from '@angular/material-moment-adapter'; -import { GuestBookDetailComponent } from './guest-book-detail/guest-book-detail.component'; +import { MomentDateAdapter } from '@angular/material-moment-adapter'; import { ReactiveFormsModule } from '@angular/forms'; +import { FlexLayoutModule } from '@angular/flex-layout'; +import { GuestBookDetailComponent } from './guest-book-detail/guest-book-detail.component'; import { GuestBookListComponent } from './guest-book-list/guest-book-list.component'; import { GuestBookRoutingModule } from './guest-book-routing.module'; @@ -45,6 +46,7 @@ export const MY_FORMATS = { MatDatepickerModule, MatNativeDateModule, ReactiveFormsModule, + FlexLayoutModule, GuestBookRoutingModule ], providers: [ diff --git a/bookie/src/app/guest-book/guest-book.service.ts b/bookie/src/app/guest-book/guest-book.service.ts index e5114be..b6e6c89 100644 --- a/bookie/src/app/guest-book/guest-book.service.ts +++ b/bookie/src/app/guest-book/guest-book.service.ts @@ -1,9 +1,9 @@ -import {Injectable} from '@angular/core'; -import {Observable} from 'rxjs/internal/Observable'; -import {catchError} from 'rxjs/operators'; -import {HttpClient, HttpHeaders, HttpParams} from '@angular/common/http'; -import {GuestBook} from './guest-book'; -import {ErrorLoggerService} from '../core/error-logger.service'; +import { Injectable } from '@angular/core'; +import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http'; +import { Observable } from 'rxjs/internal/Observable'; +import { catchError } from 'rxjs/operators'; +import { GuestBook, GuestBookList } from './guest-book'; +import { ErrorLoggerService } from '../core/error-logger.service'; const httpOptions = { headers: new HttpHeaders({'Content-Type': 'application/json'}) @@ -26,10 +26,10 @@ export class GuestBookService { ); } - list(date: string): Observable { + list(date: string): Observable { const options = {params: new HttpParams().set('q', (date === null) ? '' : date)}; const listUrl: string = `${url}/list`; - return >this.http.get(listUrl, options) + return >this.http.get(listUrl, options) .pipe( catchError(this.log.handleError(serviceName, 'list')) ); diff --git a/bookie/src/app/guest-book/guest-book.ts b/bookie/src/app/guest-book/guest-book.ts index 7d1a8e8..ca816b6 100644 --- a/bookie/src/app/guest-book/guest-book.ts +++ b/bookie/src/app/guest-book/guest-book.ts @@ -11,3 +11,8 @@ export class GuestBook { Object.assign(this, init); } } + +export class GuestBookList { + date: string; + list: GuestBook[]; +} diff --git a/bookie/src/app/home/home.component.html b/bookie/src/app/home/home.component.html index ddd5dba..5b387c5 100644 --- a/bookie/src/app/home/home.component.html +++ b/bookie/src/app/home/home.component.html @@ -1,7 +1,7 @@ account_box Login - + Guest Book diff --git a/bookie/src/app/product/product-detail/product-detail.component.ts b/bookie/src/app/product/product-detail/product-detail.component.ts index 21f3689..1c98191 100644 --- a/bookie/src/app/product/product-detail/product-detail.component.ts +++ b/bookie/src/app/product/product-detail/product-detail.component.ts @@ -15,7 +15,7 @@ import { Tax } from "../../core/tax"; styleUrls: ['./product-detail.component.css'] }) export class ProductDetailComponent implements OnInit, AfterViewInit { - @ViewChild('nameElement', { static: true }) nameElement: ElementRef; + @ViewChild('name', { static: true }) nameElement: ElementRef; form: FormGroup; productGroups: ProductGroup[]; taxes: Tax[]; diff --git a/bookie/src/app/running-tables/running-tables.component.html b/bookie/src/app/running-tables/running-tables.component.html index e704dfc..8e9b478 100644 --- a/bookie/src/app/running-tables/running-tables.component.html +++ b/bookie/src/app/running-tables/running-tables.component.html @@ -4,6 +4,6 @@ + *ngFor="let table of list" [routerLink]="['/bills', 'new']" [queryParams]="{table: table.id}">{{table.name}} diff --git a/bookie/src/app/tables/table-detail/table-detail.component.html b/bookie/src/app/tables/table-detail/table-detail.component.html index 8add151..abd523d 100644 --- a/bookie/src/app/tables/table-detail/table-detail.component.html +++ b/bookie/src/app/tables/table-detail/table-detail.component.html @@ -15,8 +15,15 @@
- Location - + Seats + + +
+
+ + Section +
{{row.name}} - - - Location - {{row.location}} + + + Seats + {{row.seats}} + + + + + Section + {{row.section}} diff --git a/bookie/src/app/tables/table-list/table-list.component.ts b/bookie/src/app/tables/table-list/table-list.component.ts index fa44d18..54806d6 100644 --- a/bookie/src/app/tables/table-list/table-list.component.ts +++ b/bookie/src/app/tables/table-list/table-list.component.ts @@ -20,7 +20,7 @@ export class TableListComponent implements OnInit { list: Table[]; data: BehaviorSubject; /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */ - displayedColumns = ['name', 'location', 'isActive']; + displayedColumns = ['name', 'seats', 'section', 'isActive']; constructor( private route: ActivatedRoute,