diff --git a/barker/models/__init__.py b/barker/models/__init__.py index b349963..313e9dd 100644 --- a/barker/models/__init__.py +++ b/barker/models/__init__.py @@ -26,8 +26,9 @@ from .master import ( Printer, PrintLocation, Product, - ProductGroup, - ProductGroupModifier, + MenuCategory, + MenuCategoryModifier, + SaleCategory, SettleOption, Tax ) diff --git a/barker/models/master.py b/barker/models/master.py index cd68dd1..b784047 100644 --- a/barker/models/master.py +++ b/barker/models/master.py @@ -83,14 +83,13 @@ class Tax(Base): self.id = id -class ProductGroup(Base): - __tablename__ = "product_groups" - # Peoduct/menu category +class MenuCategory(Base): + __tablename__ = "menu_categories" + id = Column("id", GUID(), primary_key=True, default=uuid.uuid4) name = Column("name", Unicode(255), nullable=False, unique=True) discount_limit = Column("discount_limit", Numeric, nullable=False) is_modifier_compulsory = Column("is_modifier_compulsory", Boolean, nullable=False) - group_type = Column("group_type", Unicode(255), nullable=False) is_active = Column("is_active", Boolean, nullable=False) is_fixture = Column("is_fixture", Boolean, nullable=False) @@ -101,7 +100,6 @@ class ProductGroup(Base): name, discount_limit, is_modifier_compulsory, - group_type, is_active, sort_order, is_fixture=False, @@ -110,24 +108,40 @@ class ProductGroup(Base): self.name = name self.discount_limit = discount_limit self.is_modifier_compulsory = is_modifier_compulsory - self.group_type = group_type self.is_active = is_active self.sort_order = sort_order self.is_fixture = is_fixture self.id = id +class SaleCategory(Base): + __tablename__ = "sale_categories" + + id = Column("id", GUID(), primary_key=True, default=uuid.uuid4) + name = Column("name", Unicode(255), nullable=False, unique=True) + tax_id = Column("tax_id", GUID(), ForeignKey("taxes.id"), nullable=False) + + tax = relationship("Tax", foreign_keys=tax_id) + + def __init__(self, name, tax_id=False, id=None): + self.name = name + self.tax_id = tax_id + self.id = id + + class Product(Base): __tablename__ = "products" __table_args__ = (UniqueConstraint("name", "units"),) - # add sales category instead of group_type in productgroups + id = Column("id", GUID(), primary_key=True, default=uuid.uuid4) name = Column("name", Unicode(255), nullable=False) units = Column("units", Unicode(255), nullable=False) - product_group_id = Column( - "product_group_id", GUID(), ForeignKey("product_groups.id"), nullable=False + menu_category_id = Column( + "menu_category_id", GUID(), ForeignKey("menu_categories.id"), nullable=False + ) + sale_category_id = Column( + "sale_category_id", GUID(), ForeignKey("sale_categories.id"), nullable=False ) - tax_id = Column("tax_id", GUID(), ForeignKey("taxes.id"), nullable=False) price = Column("price", Numeric, nullable=False) has_happy_hour = Column("has_happy_hour", Boolean, nullable=False) is_not_available = Column("is_not_available", Boolean, nullable=False) @@ -136,15 +150,15 @@ class Product(Base): is_active = Column("is_active", Boolean, nullable=False) sort_order = Column("sort_order", Numeric, nullable=False) - product_group = relationship("ProductGroup", backref="products") - tax = relationship("Tax", foreign_keys=tax_id) + menu_category = relationship("MenuCategory", backref="products") + sale_category = relationship("SaleCategory", backref="products") def __init__( self, name=None, units=None, - product_group_id=None, - tax_id=None, + menu_category_id=None, + sale_category_id=None, price=None, has_happy_hour=None, is_not_available=None, @@ -155,8 +169,8 @@ class Product(Base): ): self.name = name self.units = units - self.product_group_id = product_group_id - self.tax_id = tax_id + self.menu_category_id = menu_category_id + self.sale_category_id = sale_category_id self.price = price self.has_happy_hour = has_happy_hour self.is_not_available = is_not_available @@ -201,26 +215,26 @@ class Modifier(Base): self.price = price -class ProductGroupModifier(Base): - __tablename__ = "product_group_modifiers" +class MenuCategoryModifier(Base): + __tablename__ = "menu_category_modifiers" id = Column("id", GUID(), primary_key=True, default=uuid.uuid4) - product_group_id = Column( - "product_group_id", GUID(), ForeignKey("product_groups.id") + menu_category_id = Column( + "menu_cateory_id", GUID(), ForeignKey("menu_categories.id") ) modifier_id = Column( "modifier_id", GUID(), ForeignKey("modifiers.id"), nullable=False ) show_automatically = Column("show_automatically", Boolean, nullable=False) - product_group = relationship("ProductGroup", backref="modifiers") - modifier = relationship("Modifier", backref="product_groups") + menu_category = relationship("MenuCategory", backref="modifiers") + modifier = relationship("Modifier", backref="menu_categories") def __init__( - self, product_group_id=None, modifier_id=None, show_automatically=None, id=None + self, menu_category_id=None, modifier_id=None, show_automatically=None, id=None ): self.id = id - self.product_group_id = product_group_id + self.menu_category_id = menu_category_id self.modifier_id = modifier_id self.show_automatically = show_automatically @@ -283,11 +297,11 @@ class Printer(Base): class PrintLocation(Base): __tablename__ = "print_locations" - __table_args__ = (UniqueConstraint("product_group_id", "location_id"),) + __table_args__ = (UniqueConstraint("menu_category_id", "location_id"),) id = Column("id", GUID(), primary_key=True, default=uuid.uuid4) - product_group_id = Column( - "product_group_id", GUID(), ForeignKey("product_groups.id") + menu_category_id = Column( + "menu_category_id", GUID(), ForeignKey("menu_categories.id") ) location_id = Column( "location_id", GUID(), ForeignKey("locations.id"), nullable=False @@ -295,12 +309,12 @@ class PrintLocation(Base): printer_id = Column("printer_id", GUID(), ForeignKey("printers.id"), nullable=False) copies = Column("copies", Numeric, nullable=False) - product_group = relationship("ProductGroup", backref="print_locations") + menu_category = relationship("MenuCategory", backref="print_locations") location = relationship("Location", backref="print_locations") printer = relationship("Printer", backref="print_locations") - def __init__(self, product_group_id, location_id, printer_id, copies): - self.product_group_id = product_group_id + def __init__(self, menu_category_id, location_id, printer_id, copies): + self.menu_category_id = menu_category_id self.location_id = location_id self.printer_id = printer_id self.copies = copies diff --git a/barker/models/voucher.py b/barker/models/voucher.py index 3c5ee3c..85c98d3 100644 --- a/barker/models/voucher.py +++ b/barker/models/voucher.py @@ -209,19 +209,16 @@ class Inventory(Base): quantity = Column('quantity', Numeric) price = Column('price', Numeric) is_happy_hour = Column('is_happy_hour', Boolean, nullable=False) - service_tax_rate = Column('service_tax_rate', Numeric) - service_tax_id = Column('service_tax_id', GUID(), ForeignKey('taxes.id'), nullable=False) - vat_rate = Column('vat_rate', Numeric) - vat_id = Column('vat_id', GUID(), ForeignKey('taxes.id'), nullable=False) + tax_rate = Column('tax_rate', Numeric) + tax_id = Column('tax_id', GUID(), ForeignKey('taxes.id'), nullable=False) discount = Column('discount', Numeric) sort_order = Column('sort_order', Numeric, nullable=False) kot = relationship('Kot', backref='inventories') - vat = relationship('Tax', foreign_keys=vat_id) - service_tax = relationship('Tax', foreign_keys=service_tax_id) + tax = relationship('Tax', foreign_keys=tax_id) product = relationship('Product', backref='inventories') - def __init__(self, kot_id, product_id, quantity, price, discount, is_hh, st_id, st_rate, vat_id, vat_rate, + def __init__(self, kot_id, product_id, quantity, price, discount, is_hh, tax_id, tax_rate, sort_order): self.kot_id = kot_id self.product_id = product_id @@ -229,10 +226,8 @@ class Inventory(Base): self.price = price self.discount = discount self.is_happy_hour = is_hh - self.service_tax_id = st_id - self.service_tax_rate = st_rate - self.vat_id = vat_id - self.vat_rate = vat_rate + self.tax_id = tax_id + self.tax_rate = tax_rate self.sort_order = sort_order @hybrid_property diff --git a/barker/routes.py b/barker/routes.py index 8ae5ee1..ef63b77 100644 --- a/barker/routes.py +++ b/barker/routes.py @@ -47,13 +47,21 @@ def includeme(config): config.add_route("v1_products_id", "/v1/products/{id}") config.add_route("v1_products_list", "/v1/products") - config.add_route("product_groups_new", "/product-groups/new") - config.add_route("product_groups_id", "/product-groups/{id}") - config.add_route("product_groups_list", "/product-groups") - config.add_route("v1_product_groups_new", "/v1/product-groups/new") - config.add_route("v1_product_groups_id", "/v1/product-groups/{id}") - 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("menu_categories_new", "/menu-categories/new") + config.add_route("menu_categories_id", "/menu-categories/{id}") + config.add_route("menu_categories_list", "/menu-categories") + config.add_route("v1_menu_categories_new", "/v1/menu-categories/new") + config.add_route("v1_menu_categories_id", "/v1/menu-categories/{id}") + config.add_route("v1_menu_categories_list", "/v1/menu-categories") + config.add_route("v1_menu_category_types_list", "/v1/menu-category-types") + + config.add_route("sale_categories_new", "/sale-categories/new") + config.add_route("sale_categories_id", "/sale-categories/{id}") + config.add_route("sale_categories_list", "/sale-categories") + config.add_route("v1_sale_categories_new", "/v1/sale-categories/new") + config.add_route("v1_sale_categories_id", "/v1/sale-categories/{id}") + config.add_route("v1_sale_categories_list", "/v1/sale-categories") + config.add_route("v1_sale_category_types_list", "/v1/sale-category-types") config.add_route("v1_bills_new", "/v1/bills/new") config.add_route("v1_bills_id", "/v1/bills/{id}") diff --git a/barker/scripts/initializedb.py b/barker/scripts/initializedb.py index 9077650..3a6d8fe 100644 --- a/barker/scripts/initializedb.py +++ b/barker/scripts/initializedb.py @@ -31,8 +31,8 @@ from barker.models import ( PrintLocation, Printer, Product, - ProductGroup, - ProductGroupModifier, + MenuCategory, + MenuCategoryModifier, Reprint, Role, role_permissions, diff --git a/barker/views/menu_category.py b/barker/views/menu_category.py new file mode 100644 index 0000000..cf3e6a7 --- /dev/null +++ b/barker/views/menu_category.py @@ -0,0 +1,220 @@ +import uuid +from decimal import Decimal, InvalidOperation + +import transaction +from pyramid.response import Response +from pyramid.view import view_config + +from barker.exceptions import ValidationFailure +from barker.models import Product, MenuCategory +from barker.models.validation_exception import ValidationError + + +@view_config( + request_method="POST", + route_name="v1_menu_categories_new", + renderer="json", + permission="Products", + trans=True, +) +def save(request): + json = request.json_body + name = json.get("name", "").strip() + if name == "": + raise ValidationError("Name cannot be blank") + try: + discount_limit = Decimal(json["discountLimit"]) / 100 + if discount_limit < 0 or discount_limit > 1: + raise ValidationError("Tax Rate must be a decimal >= 0 and <= 100") + except (ValueError, InvalidOperation): + raise ValidationError("Tax Rate must be a decimal >= 0 and <= 100") + is_modifier_compulsory = json.get("isModifierCompulsory", True) + is_active = json.get("isActive", True) + item = MenuCategory(name, discount_limit, is_modifier_compulsory, is_active, 0) + request.dbsession.add(item) + transaction.commit() + return menu_category_info(item.id, request.dbsession) + + +@view_config( + request_method="PUT", + route_name="v1_menu_categories_id", + renderer="json", + permission="Products", + trans=True, +) +def update(request): + json = request.json_body + item = ( + request.dbsession.query(MenuCategory) + .filter(MenuCategory.id == uuid.UUID(request.matchdict["id"])) + .first() + ) + if item.is_fixture: + raise ValidationError( + "{0} is a fixture and cannot be edited or deleted.".format(item.full_name) + ) + item.name = json["name"].strip() + try: + item.discount_limit = Decimal(json["discountLimit"]) / 100 + if item.discount_limit < 0 or item.discount_limit > 1: + raise ValidationError("Tax Rate must be a decimal >= 0 and <= 100") + except (ValueError, InvalidOperation): + raise ValidationError("Tax Rate must be a decimal >= 0 and <= 100") + item.is_modifier_compulsory = json.get("isModifierCompulsory", True) + item.is_active = json.get("isActive", True) + transaction.commit() + return menu_category_info(item.id, request.dbsession) + + +@view_config( + request_method="DELETE", + route_name="v1_menu_categories_id", + renderer="json", + permission="Products", + trans=True, +) +def delete(request): + item = ( + request.dbsession.query(MenuCategory) + .filter(MenuCategory.id == uuid.UUID(request.matchdict["id"])) + .first() + ) + if item is None: + response = Response("Menu Category not Found") + response.status_int = 500 + return response + elif item.is_fixture: + transaction.abort() + raise ValidationFailure( + "{0} is a fixture and cannot be edited or deleted.".format(item.name) + ) + else: + response = Response("Menu Category deletion not implemented") + response.status_int = 500 + return response + + +@view_config( + request_method="GET", + route_name="v1_menu_categories_new", + renderer="json", + permission="Authenticated", +) +def show_blank(request): + return menu_category_info(None, request.dbsession) + + +@view_config( + request_method="GET", + route_name="v1_menu_categories_id", + renderer="json", + permission="Authenticated", +) +def show_id(request): + return menu_category_info(uuid.UUID(request.matchdict["id"]), request.dbsession) + + +@view_config( + request_method="GET", + route_name="v1_menu_categories_list", + renderer="json", + permission="Authenticated", +) +def show_list(request): + list_ = ( + request.dbsession.query(MenuCategory) + .order_by(MenuCategory.sort_order) + .order_by(MenuCategory.name) + .all() + ) + menu_categories = [] + for item in list_: + menu_categories.append(menu_category_info(item, request.dbsession)) + return menu_categories + + +@view_config( + request_method="GET", + route_name="v1_menu_categories_list", + renderer="json", + request_param="s", + permission="Authenticated", +) +def sale_list(request): + list_ = ( + request.dbsession.query(MenuCategory) + .filter(MenuCategory.is_active == True) + .order_by(MenuCategory.sort_order) + .order_by(MenuCategory.name) + .all() + ) + menu_categories = [] + for item in list_: + products = ( + request.dbsession.query(Product) + .filter(Product.menu_category_id == item.id) + .filter(Product.is_active == True) + .order_by(Product.sort_order) + .order_by(Product.name) + .all() + ) + if len(products) > 0: + pg = menu_category_info(item) + pg["products"] = [] + for p in products: + pg["products"].append( + { + "id": p.id, + "name": p.name, + "units": p.units, + "tat": {"id": p.vat.id, "name": p.vat.name, "rate": p.vat.rate}, + "price": p.price, + "hasHappyHour": p.has_happy_hour, + "isActive": p.is_active, + "isNotAvailable": p.is_not_available, + "sortOrder": p.sort_order, + "quantity": p.quantity, + } + ) + menu_categories.append(pg) + return menu_categories + + +@view_config( + request_method="POST", + route_name="v1_menu_categories_list", + renderer="json", + permission="Products", + trans=True, +) +def sort_order(request): + json = request.json_body + for index, item in enumerate(json): + request.dbsession.query(MenuCategory).filter( + MenuCategory.id == uuid.UUID(item["id"]) + ).update({MenuCategory.sort_order: index}) + return True + + +def menu_category_info(item, dbsession): + if item is None: + return { + "name": "", + "discountLimit": 0, + "isModifierCompulsory": False, + "isActive": True, + "isFixture": False, + "sortOrder": 0, + } + if type(item) is uuid.UUID: + item = dbsession.query(MenuCategory).filter(MenuCategory.id == item).first() + return { + "id": item.id, + "name": item.name, + "discountLimit": item.discount_limit, + "isModifierCompulsory": item.is_modifier_compulsory, + "isActive": item.is_active, + "isFixture": item.is_fixture, + "sortOrder": item.sort_order, + } diff --git a/barker/views/modifier.py b/barker/views/modifier.py index 063d51b..763bb14 100644 --- a/barker/views/modifier.py +++ b/barker/views/modifier.py @@ -5,7 +5,7 @@ import transaction from pyramid.view import view_config from sqlalchemy import or_ -from barker.models import Modifier, ProductGroupModifier +from barker.models import Modifier, MenuCategoryModifier @view_config(request_method='PUT', route_name='modifier', renderer='json', permission='Modifiers', trans=True) @@ -13,7 +13,7 @@ def save(request): json = request.json_body item = Modifier(json['Name'], json['ShowInBill'], json['Price']) request.dbsession.add(item) - add_groups(item, json['ProductGroupModifiers'], request.dbsession) + add_groups(item, json['MenuCategoryModifiers'], request.dbsession) transaction.commit() item = request.dbsession.query(Modifier).filter(Modifier.id == item.id).first() return modifier_info(item) @@ -26,7 +26,7 @@ def update(request): item.name = json['Name'] item.show_in_bill = json['ShowInBill'] item.price = json['Price'] - add_groups(item, json['ProductGroupModifiers'], request.dbsession) + add_groups(item, json['MenuCategoryModifiers'], request.dbsession) transaction.commit() item = request.dbsession.query(Modifier).filter(Modifier.id == item.id).first() return modifier_info(item) @@ -64,11 +64,11 @@ def show_list(request): @view_config(request_method='GET', route_name='modifier_list', renderer='json', request_param='pg', permission='Authenticated') def show_for_pg(request): - product_group_id = uuid.UUID(request.GET['pg']) + menu_category_id = uuid.UUID(request.GET['pg']) pgm_list = request.dbsession.query( - ProductGroupModifier + MenuCategoryModifier ).filter( - or_(ProductGroupModifier.product_group == None, ProductGroupModifier.product_group_id == product_group_id) + or_(MenuCategoryModifier.menu_category == None, MenuCategoryModifier.menu_category_id == menu_category_id) ).all() pg_modifiers = [] @@ -84,34 +84,34 @@ def show_for_pg(request): def modifier_info(modifier): return { - 'ModifierID': modifier.id, - 'Name': modifier.name, - 'ShowInBill': modifier.show_in_bill, - 'Price': modifier.price, - 'ProductGroupModifiers': [ + 'id': modifier.id, + 'name': modifier.name, + 'showInBill': modifier.show_in_bill, + 'price': modifier.price, + 'menuCategoryModifiers': [ { - 'ProductGroupModifierID': i.id, - 'ProductGroup': {'ProductGroupID': i.product_group_id} if i.product_group_id is not None else None, - 'ShowAutomatically': i.show_automatically - } for i in modifier.product_groups] + 'id': i.id, + 'menuCategory': {'id': i.menu_category_id} if i.menu_category_id is not None else None, + 'showAutomatically': i.show_automatically + } for i in modifier.menu_categories] } def add_groups(modifier, groups, dbsession): - all = [p for p in groups if p['ProductGroup'] is None] + all = [p for p in groups if p['MenuCategory'] is None] if len(all) > 0: - old = [p for p in modifier.product_groups if p.product_group_id is None] + old = [p for p in modifier.menu_categories if p.menu_category_id is None] if len(old) != 1: - for item in modifier.product_groups: + for item in modifier.menu_categories: dbsession.delete(item) - modifier.product_groups.clear() - modifier.product_groups.append(ProductGroupModifier(None, None, False)) + modifier.menu_categories.clear() + modifier.menu_categories.append(MenuCategoryModifier(None, None, False)) else: - new = {uuid.UUID(p['ProductGroup']['ProductGroupID']) for p in groups} - old = {p.product_group_id for p in modifier.product_groups} + new = {uuid.UUID(p['menuCategory']['id']) for p in groups} + old = {p.menu_category_id for p in modifier.menu_categories} for pg_id in new - old: - modifier.product_groups.append(ProductGroupModifier(pg_id, None, False)) + modifier.menu_categories.append(MenuCategoryModifier(pg_id, None, False)) - gp = [p for p in modifier.product_groups if p.product_group_id in (old - new)] + gp = [p for p in modifier.menu_categories if p.menu_category_id in (old - new)] for item in gp: dbsession.delete(item) diff --git a/barker/views/print_location.py b/barker/views/print_location.py index e42fe32..789f323 100644 --- a/barker/views/print_location.py +++ b/barker/views/print_location.py @@ -10,7 +10,7 @@ def show(request): id = request.matchdict['id'] item = request.dbsession.query(PrintLocation).join(PrintLocation.location).filter( Location.name == id, - PrintLocation.product_group_id == None + PrintLocation.menu_category_id == None ).first() return print_location_info(item) @@ -22,14 +22,14 @@ def show_pg(request): pg = uuid.UUID(request.GET['pg']) item = request.dbsession.query(PrintLocation).join(PrintLocation.location).filter( Location.name == id, - PrintLocation.product_group_id == pg + PrintLocation.menu_category_id == pg ).first() if item is None: item = request.dbsession.query( PrintLocation ).join(PrintLocation.location).filter( Location.name == id, - PrintLocation.product_group_id == None + PrintLocation.menu_category_id == None ).first() return print_location_info(item) @@ -37,10 +37,10 @@ def show_pg(request): def print_location_info(item): return { - 'PrintLocationID': item.id, - 'ProductGroup': None if item.product_group is None else {'ProductGroupID': item.product_group_id}, - 'Location': item.location.name, - 'Printer': item.printer.name, - 'Copies': item.copies, - 'CutCode': item.printer.cut_code + 'id': item.id, + 'menuCategory': None if item.menu_category is None else {'id': item.menu_category_id}, + 'location': item.location.name, + 'printer': item.printer.name, + 'copies': item.copies, + 'cutCode': item.printer.cut_code } diff --git a/barker/views/product.py b/barker/views/product.py index 5e14ede..11e04e8 100644 --- a/barker/views/product.py +++ b/barker/views/product.py @@ -25,15 +25,15 @@ def save(request): units = json.get("units", "").strip() - product_group = json.get("productGroup", None) - if product_group is None: - raise ValidationError("please choose a product group") - product_group_id = uuid.UUID(product_group["id"]) + menu_category = json.get("menuCategory", None) + if menu_category is None: + raise ValidationError("please choose a menu category") + menu_category_id = uuid.UUID(menu_category["id"]) - tax = json.get("tax", None) - if product_group is None: - raise ValidationError("please choose a product group") - tax_id = uuid.UUID(tax["id"]) + sale_category = json.get("saleCategory", None) + if menu_category is None: + raise ValidationError("please choose a sale category") + sale_category_id = uuid.UUID(sale_category["id"]) try: price = Decimal(json.get("price", 0)) @@ -57,8 +57,8 @@ def save(request): item = Product( name, units, - product_group_id, - tax_id, + menu_category_id, + sale_category_id, price, has_happy_hour, is_not_available, @@ -88,8 +88,8 @@ def update(request): 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"]) + item.menu_category_id = uuid.UUID(json["menuCategory"]["id"]) + item.sale_category_id = uuid.UUID(json["saleCategory"]["id"]) try: item.price = Decimal(json["price"]) if item.price < 0: @@ -165,7 +165,7 @@ def show_list(request): if active is not None: list_ = list_.filter(Product.is_active == active) list_ = ( - list_.order_by(Product.product_group_id, Product.sort_order) + list_.order_by(Product.menu_category_id, Product.sort_order) .order_by(Product.name) .all() ) @@ -187,13 +187,13 @@ def sort_order(request): indexes = {} for item in json: product_id = uuid.UUID(item["id"]) - product_group_id = uuid.UUID(item["productGroup"]["id"]) - if product_group_id in indexes: - indexes[product_group_id] += 1 + menu_category_id = uuid.UUID(item["menuCategory"]["id"]) + if menu_category_id in indexes: + indexes[menu_category_id] += 1 else: - indexes[product_group_id] = 0 + indexes[menu_category_id] = 0 request.dbsession.query(Product).filter(Product.id == product_id).update( - {Product.sort_order: indexes[product_group_id]} + {Product.sort_order: indexes[menu_category_id]} ) return True @@ -203,8 +203,8 @@ def product_info(item, dbsession): return { "name": "", "units": "", - "productGroup": {}, - "tax": {}, + "menuCategory": {}, + "saleCategory": {}, "price": 0, "hasHappyHour": False, "isNotAvailable": False, @@ -217,8 +217,8 @@ def product_info(item, dbsession): "id": item.id, "name": item.name, "units": item.units, - "productGroup": {"id": item.product_group_id, "name": item.product_group.name}, - "tax": {"id": item.tax_id, "name": item.tax.name, "rate": item.tax.rate}, + "menuCategory": {"id": item.menu_category_id, "name": item.menu_category.name}, + "saleCategory": {"id": item.sale_category_id, "name": item.sale_category.name}, "price": item.price, "hasHappyHour": item.has_happy_hour, "isNotAvailable": item.is_not_available, diff --git a/barker/views/product_group.py b/barker/views/product_group.py deleted file mode 100644 index dc000e1..0000000 --- a/barker/views/product_group.py +++ /dev/null @@ -1,180 +0,0 @@ -import uuid -from decimal import Decimal, InvalidOperation - -import transaction -from pyramid.response import Response -from pyramid.view import view_config - -from barker.exceptions import ValidationFailure -from barker.models import Product, ProductGroup -from barker.models.validation_exception import ValidationError - - -@view_config(request_method='POST', route_name='v1_product_groups_new', renderer='json', permission='Products', trans=True) -def save(request): - json = request.json_body - name = json.get("name", "").strip() - if name == "": - raise ValidationError("Name cannot be blank") - try: - discount_limit = Decimal(json["discountLimit"]) / 100 - if discount_limit < 0 or discount_limit > 1: - raise ValidationError("Tax Rate must be a decimal >= 0 and <= 100") - except (ValueError, InvalidOperation): - raise ValidationError("Tax Rate must be a decimal >= 0 and <= 100") - is_modifier_compulsory = json.get("isModifierCompulsory", True) - group_type = json.get("group_type", "").strip() - is_active = json.get("isActive", True) - item = ProductGroup(name, discount_limit, is_modifier_compulsory, group_type, is_active, 0) - request.dbsession.add(item) - transaction.commit() - return product_group_info(item.id, request.dbsession) - - -@view_config(request_method='PUT', route_name='v1_product_groups_id', renderer='json', permission='Products', trans=True) -def update(request): - json = request.json_body - item = ( - request.dbsession.query(ProductGroup) - .filter(ProductGroup.id == uuid.UUID(request.matchdict["id"])) - .first() - ) - if item.is_fixture: - raise ValidationError( - "{0} is a fixture and cannot be edited or deleted.".format(item.full_name) - ) - item.name = json['name'].strip() - try: - item.discount_limit = Decimal(json["discountLimit"]) / 100 - if item.discount_limit < 0 or item.discount_limit > 1: - raise ValidationError("Tax Rate must be a decimal >= 0 and <= 100") - except (ValueError, InvalidOperation): - raise ValidationError("Tax Rate must be a decimal >= 0 and <= 100") - item.is_modifier_compulsory = json.get("isModifierCompulsory", True) - item.group_type = json.get("group_type", "").strip() - item.is_active = json.get("isActive", True) - transaction.commit() - return product_group_info(item.id, request.dbsession) - - -@view_config(request_method='DELETE', route_name='v1_product_groups_id', renderer='json', permission='Products', trans=True) -def delete(request): - item = ( - request.dbsession.query(ProductGroup) - .filter(ProductGroup.id == uuid.UUID(request.matchdict["id"])) - .first() - ) - if item is None: - response = Response("Product Group not Found") - response.status_int = 500 - return response - elif item.is_fixture: - transaction.abort() - raise ValidationFailure("{0} is a fixture and cannot be edited or deleted.".format(item.name)) - else: - response = Response("Product Group deletion not implemented") - response.status_int = 500 - return response - - -@view_config(request_method='GET', route_name='v1_product_groups_new', renderer='json', permission='Authenticated') -def show_blank(request): - return product_group_info(None, request.dbsession) - - -@view_config(request_method='GET', route_name='v1_product_groups_id', renderer='json', permission='Authenticated') -def show_id(request): - return product_group_info(uuid.UUID(request.matchdict["id"]), request.dbsession) - - -@view_config(request_method='GET', route_name='v1_product_groups_list', renderer='json', permission='Authenticated') -def show_list(request): - list_ = request.dbsession.query(ProductGroup).order_by(ProductGroup.sort_order).order_by(ProductGroup.name).all() - product_groups = [] - for item in list_: - product_groups.append(product_group_info(item, request.dbsession)) - return product_groups - - -@view_config(request_method='GET', route_name='v1_product_groups_list', renderer='json', request_param='s', - permission='Authenticated') -def sale_list(request): - list_ = request.dbsession.query( - ProductGroup - ).filter(ProductGroup.is_active == True).order_by(ProductGroup.sort_order).order_by(ProductGroup.name).all() - product_groups = [] - for item in list_: - products = request.dbsession.query( - Product - ).filter( - Product.product_group_id == item.id - ).filter(Product.is_active == True).order_by(Product.sort_order).order_by(Product.name).all() - if len(products) > 0: - pg = product_group_info(item) - pg['Products'] = [] - for p in products: - pg['Products'].append({ - 'ProductID': p.id, - 'Name': p.name, - 'Units': p.units, - 'Vat': {'TaxID': p.vat.id, 'Name': p.vat.name, 'Rate': p.vat.rate}, - 'ServiceTax': {'TaxID': p.service_tax.id, 'Name': p.service_tax.name, 'Rate': p.service_tax.rate}, - 'Price': p.price, - 'HasHappyHour': p.has_happy_hour, - 'IsActive': p.is_active, - 'IsNotAvailable': p.is_not_available, - 'SortOrder': p.sort_order, - 'Quantity': p.quantity}) - product_groups.append(pg) - return product_groups - - -@view_config(request_method='POST', route_name='v1_product_groups_list', renderer='json', permission='Products', trans=True) -def sort_order(request): - json = request.json_body - for index, item in enumerate(json): - request.dbsession.query( - ProductGroup - ).filter( - ProductGroup.id == uuid.UUID(item['id']) - ).update( - {ProductGroup.sort_order: index} - ) - return True - - -@view_config(request_method='GET', route_name='v1_product_group_types_list', renderer='json', permission='Authenticated') -def product_group_type_list(request): - list_ = request.dbsession.query( - ProductGroup.group_type - ).group_by( - ProductGroup.group_type - ).order_by( - ProductGroup.group_type - ).all() - return [item.group_type for item in list_] - - -def product_group_info(item, dbsession): - if item is None: - return { - 'name': "", - 'discountLimit': 0, - 'isModifierCompulsory': False, - 'groupType': "", - 'isActive': True, - 'isFixture': False, - 'sortOrder': 0 - } - if type(item) is uuid.UUID: - item = dbsession.query(ProductGroup).filter(ProductGroup.id == item).first() - return { - 'id': item.id, - 'name': item.name, - 'discountLimit': item.discount_limit, - 'isModifierCompulsory': item.is_modifier_compulsory, - 'groupType': item.group_type, - 'isActive': item.is_active, - 'isFixture': item.is_fixture, - 'sortOrder': item.sort_order - } diff --git a/barker/views/reports/discount_report.py b/barker/views/reports/discount_report.py index 496dd61..a48fc4b 100644 --- a/barker/views/reports/discount_report.py +++ b/barker/views/reports/discount_report.py @@ -4,7 +4,7 @@ from pyramid.httpexceptions import HTTPForbidden from pyramid.view import view_config from sqlalchemy import func -from barker.models import Inventory, Kot, Product, ProductGroup, Settlement, SettleOption, Voucher +from barker.models import Inventory, Kot, Product, MenuCategory, Settlement, SettleOption, Voucher @view_config(request_method='GET', route_name='discount_report', renderer='json', permission='Discount Report', @@ -18,8 +18,8 @@ def discount_report(request): amount = func.sum(Inventory.quantity * Inventory.effective_price * Inventory.discount).label('Amount') list = request.dbsession.query( - ProductGroup.group_type, amount - ).join(Voucher.kots).join(Kot.inventories).join(Inventory.product).join(Product.product_group).filter( + MenuCategory.group_type, amount + ).join(Voucher.kots).join(Kot.inventories).join(Inventory.product).join(Product.menu_category).filter( Voucher.date >= start_date, Voucher.date <= finish_date, Voucher.is_void == False, @@ -28,9 +28,9 @@ def discount_report(request): [SettleOption.CASH(), SettleOption.CREDIT_CARD(), SettleOption.BILL_TO_COMPANY(), SettleOption.UNSETTLED()])) ).group_by( - ProductGroup.group_type + MenuCategory.group_type ).order_by( - ProductGroup.group_type + MenuCategory.group_type ).all() return [{'GroupType': pg, 'Amount': amt} for pg, amt in list] diff --git a/barker/views/reports/quantity_sold.py b/barker/views/reports/quantity_sold.py index 3d98e1b..911d740 100644 --- a/barker/views/reports/quantity_sold.py +++ b/barker/views/reports/quantity_sold.py @@ -4,7 +4,7 @@ from pyramid.httpexceptions import HTTPForbidden from pyramid.view import view_config from sqlalchemy import func -from barker.models import Inventory, Kot, Product, ProductGroup, Settlement, SettleOption, Voucher +from barker.models import Inventory, Kot, Product, MenuCategory, Settlement, SettleOption, Voucher @view_config(request_method='GET', route_name='quantity_sold', renderer='json', permission='Sales Detail', @@ -45,13 +45,13 @@ def quantity_sold(request): def q(start_date, finish_date, options, dbsession): return dbsession.query( Product.id, Product.full_name, Inventory.is_happy_hour, func.sum(Inventory.quantity) - ).join(Voucher.kots).join(Kot.inventories).join(Inventory.product).join(Product.product_group).filter( + ).join(Voucher.kots).join(Kot.inventories).join(Inventory.product).join(Product.menu_category).filter( Voucher.date >= start_date, Voucher.date <= finish_date, Voucher.is_void == False, Voucher.settlements.any(Settlement.settled.in_(options)) ).group_by( - Product.id, Product.full_name, Inventory.is_happy_hour, ProductGroup.name, ProductGroup.group_type + Product.id, Product.full_name, Inventory.is_happy_hour, MenuCategory.name, MenuCategory.group_type ).order_by( - ProductGroup.group_type, ProductGroup.name, Product.full_name, Inventory.is_happy_hour + MenuCategory.group_type, MenuCategory.name, Product.full_name, Inventory.is_happy_hour ).all() diff --git a/barker/views/reports/sale_analysis.py b/barker/views/reports/sale_analysis.py index 8658dbc..e8cab32 100644 --- a/barker/views/reports/sale_analysis.py +++ b/barker/views/reports/sale_analysis.py @@ -4,14 +4,14 @@ from pyramid.httpexceptions import HTTPForbidden from pyramid.view import view_config from sqlalchemy import func -from barker.models import Inventory, Kot, Product, ProductGroup, Settlement, SettleOption, Tax, Voucher +from barker.models import Inventory, Kot, Product, MenuCategory, Settlement, SettleOption, Tax, Voucher import datetime from pyramid.httpexceptions import HTTPForbidden from pyramid.view import view_config from sqlalchemy import func -from barker.models import Inventory, Kot, Product, ProductGroup, Settlement, SettleOption, Tax, Voucher +from barker.models import Inventory, Kot, Product, MenuCategory, Settlement, SettleOption, Tax, Voucher @view_config(request_method='GET', route_name='sa_sale', renderer='json', permission='Sales Analysis', @@ -25,16 +25,16 @@ def get_sale(request): amount = func.sum(Inventory.quantity * Inventory.effective_price * (1 - Inventory.discount)).label('Amount') list = request.dbsession.query( - ProductGroup.group_type, amount - ).join(Voucher.kots).join(Kot.inventories).join(Inventory.product).join(Product.product_group).filter( + MenuCategory.group_type, amount + ).join(Voucher.kots).join(Kot.inventories).join(Inventory.product).join(Product.menu_category).filter( Voucher.date >= start_date, Voucher.date <= finish_date, Voucher.is_void == False, Voucher.settlements.any(~Settlement.settled.in_([1, 4, 7, 8, 9, 10])) ).group_by( - ProductGroup.group_type + MenuCategory.group_type ).order_by( - ProductGroup.group_type + MenuCategory.group_type ).all() total = 0 info = [] diff --git a/barker/views/sale_category.py b/barker/views/sale_category.py new file mode 100644 index 0000000..80acdcc --- /dev/null +++ b/barker/views/sale_category.py @@ -0,0 +1,130 @@ +import uuid + +import transaction +from pyramid.response import Response +from pyramid.view import view_config + +from barker.models import SaleCategory +from barker.models.validation_exception import ValidationError + + +@view_config( + request_method="POST", + route_name="v1_sale_categories_new", + renderer="json", + permission="Products", + trans=True, +) +def save(request): + json = request.json_body + name = json.get("name", "").strip() + if name == "": + raise ValidationError("Name cannot be blank") + tax = json.get("tax", None) + if tax is None: + raise ValidationError("please choose a tax") + tax_id = uuid.UUID(tax["id"]) + item = SaleCategory(name, tax_id) + request.dbsession.add(item) + transaction.commit() + return sale_category_info(item.id, request.dbsession) + + +@view_config( + request_method="PUT", + route_name="v1_sale_categories_id", + renderer="json", + permission="Products", + trans=True, +) +def update(request): + json = request.json_body + item = ( + request.dbsession.query(SaleCategory) + .filter(SaleCategory.id == uuid.UUID(request.matchdict["id"])) + .first() + ) + if item.is_fixture: + raise ValidationError( + "{0} is a fixture and cannot be edited or deleted.".format(item.full_name) + ) + item.name = json["name"].strip() + item.tax_id = uuid.UUID(json["tax"]["id"]) + transaction.commit() + return sale_category_info(item.id, request.dbsession) + + +@view_config( + request_method="DELETE", + route_name="v1_sale_categories_id", + renderer="json", + permission="Products", + trans=True, +) +def delete(request): + item = ( + request.dbsession.query(SaleCategory) + .filter(SaleCategory.id == uuid.UUID(request.matchdict["id"])) + .first() + ) + if item is None: + response = Response("Sale Category not Found") + response.status_int = 500 + return response + else: + response = Response("Sale Category deletion not implemented") + response.status_int = 500 + return response + + +@view_config( + request_method="GET", + route_name="v1_sale_categories_new", + renderer="json", + permission="Authenticated", +) +def show_blank(request): + return sale_category_info(None, request.dbsession) + + +@view_config( + request_method="GET", + route_name="v1_sale_categories_id", + renderer="json", + permission="Authenticated", +) +def show_id(request): + return sale_category_info(uuid.UUID(request.matchdict["id"]), request.dbsession) + + +@view_config( + request_method="GET", + route_name="v1_sale_categories_list", + renderer="json", + permission="Authenticated", +) +def show_list(request): + list_ = ( + request.dbsession.query(SaleCategory) + .order_by(SaleCategory.name) + .all() + ) + sale_categories = [] + for item in list_: + sale_categories.append(sale_category_info(item, request.dbsession)) + return sale_categories + + +def sale_category_info(item, dbsession): + if item is None: + return { + "name": "", + "tax": {} + } + if type(item) is uuid.UUID: + item = dbsession.query(SaleCategory).filter(SaleCategory.id == item).first() + return { + "id": item.id, + "name": item.name, + "tax": {"id": item.tax_id, "name": item.tax.name, "rate": item.tax.rate} + } diff --git a/barker/views/voucher.py b/barker/views/voucher.py index 564c09f..ffbde5a 100644 --- a/barker/views/voucher.py +++ b/barker/views/voucher.py @@ -377,11 +377,14 @@ def voucher_info(item): "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, + "menuCategory": { + "id": i.product.menu_category_id, + "name": i.product.menu_category.name, + "discountLimit": i.product.menu_category.discount_limit, + }, + "saleCategory": { + "id": i.product.sale_category_id, + "name": i.product.sale_category.name }, }, "quantity": i.quantity, diff --git a/bookie/src/app/app-routing.module.ts b/bookie/src/app/app-routing.module.ts index 701896d..c72766c 100644 --- a/bookie/src/app/app-routing.module.ts +++ b/bookie/src/app/app-routing.module.ts @@ -22,8 +22,8 @@ const routes: Routes = [ loadChildren: () => import('./product/products.module').then(mod => mod.ProductsModule) }, { - path: 'product-groups', - loadChildren: () => import('./product-group/product-groups.module').then(mod => mod.ProductGroupsModule) + path: 'menu-categories', + loadChildren: () => import('./menu-category/menu-categories.module').then(mod => mod.MenuCategoriesModule) }, { path: 'roles', @@ -33,6 +33,10 @@ const routes: Routes = [ path: 'running-tables', loadChildren: () => import('./running-tables/running-tables.module').then(mod => mod.RunningTablesModule) }, + { + path: 'sale-categories', + loadChildren: () => import('./sale-category/sale-categories.module').then(mod => mod.SaleCategoriesModule) + }, { path: 'tables', loadChildren: () => import('./tables/tables.module').then(mod => mod.TableModule) diff --git a/bookie/src/app/auth/auth-guard.service.ts b/bookie/src/app/auth/auth-guard.service.ts index 505276e..ed3088b 100644 --- a/bookie/src/app/auth/auth-guard.service.ts +++ b/bookie/src/app/auth/auth-guard.service.ts @@ -1,8 +1,8 @@ import { Injectable } from '@angular/core'; import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot } from '@angular/router'; -import { AuthService } from './auth.service'; import { Observable } from 'rxjs/internal/Observable'; import { map } from 'rxjs/operators'; +import { AuthService } from './auth.service'; import { ToasterService } from '../core/toaster.service'; import { User } from '../core/user'; @@ -14,28 +14,28 @@ export class AuthGuard implements CanActivate { constructor(private auth: AuthService, private router: Router, private toaster: ToasterService) { } - static checkUser(permission: string, user: User, router: Router, state: RouterStateSnapshot, toaster: ToasterService): boolean { + checkUser(permission: string, user: User, state: RouterStateSnapshot): boolean { if (!user.isAuthenticated) { - router.navigate(['login'], {queryParams: {returnUrl: state.url}}); - toaster.show('Danger', 'User is not authenticated'); + this.router.navigate(['login'], {queryParams: {returnUrl: state.url}}); + this.toaster.show('Danger', 'User is not authenticated'); return false; } const hasPermission = permission === undefined || user.perms.indexOf(permission) !== -1; if (!hasPermission) { - toaster.show('Danger', 'You do not have the permission to access this area.'); + this.toaster.show('Danger', 'You do not have the permission to access this area.'); } return hasPermission; } - canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable | boolean { + canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable | boolean { if (this.auth.user === undefined) { return this.auth.userObservable .pipe( - map((value: User) => AuthGuard.checkUser( - route.data['permission'], value, this.router, state, this.toaster + map((value: User) => this.checkUser( + next.data['permission'], value, state )) ); } - return AuthGuard.checkUser(route.data['permission'], this.auth.user, this.router, state, this.toaster); + return this.checkUser(next.data['permission'], this.auth.user, state); } } diff --git a/bookie/src/app/core/product-group.ts b/bookie/src/app/core/menu-category.ts similarity index 75% rename from bookie/src/app/core/product-group.ts rename to bookie/src/app/core/menu-category.ts index fcca995..838eae3 100644 --- a/bookie/src/app/core/product-group.ts +++ b/bookie/src/app/core/menu-category.ts @@ -1,9 +1,8 @@ -export class ProductGroup { +export class MenuCategory { id: string; name: string; discountLimit: number; isModifierCompulsory: boolean; - groupType: string; isActive: boolean; isFixture: boolean; sortOrder: number; diff --git a/bookie/src/app/core/product.ts b/bookie/src/app/core/product.ts index 9db6b69..898fe55 100644 --- a/bookie/src/app/core/product.ts +++ b/bookie/src/app/core/product.ts @@ -1,13 +1,13 @@ -import {ProductGroup} from './product-group'; -import {Tax} from "./tax"; +import {MenuCategory} from './menu-category'; +import {SaleCategory} from "./sale-category"; export class Product { id: string; code: number; name: string; units: string; - productGroup: ProductGroup; - tax: Tax; + menuCategory: MenuCategory; + saleCategory: SaleCategory; price: number; hasHappyHour: boolean; isNotAvailable: boolean; diff --git a/bookie/src/app/core/sale-category.ts b/bookie/src/app/core/sale-category.ts new file mode 100644 index 0000000..51cd361 --- /dev/null +++ b/bookie/src/app/core/sale-category.ts @@ -0,0 +1,7 @@ +import {Tax} from "./tax"; + +export class SaleCategory { + id: string; + name: string; + tax: Tax; +} diff --git a/bookie/src/app/home/home.component.html b/bookie/src/app/home/home.component.html index 674efd4..3dfed08 100644 --- a/bookie/src/app/home/home.component.html +++ b/bookie/src/app/home/home.component.html @@ -10,8 +10,11 @@ Tables - - Product Groups + + Menu Categories + + + Sale Categories Products diff --git a/bookie/src/app/menu-category/menu-categories-routing.module.spec.ts b/bookie/src/app/menu-category/menu-categories-routing.module.spec.ts new file mode 100644 index 0000000..45eddd7 --- /dev/null +++ b/bookie/src/app/menu-category/menu-categories-routing.module.spec.ts @@ -0,0 +1,13 @@ +import {MenuCategoriesRoutingModule} from './menu-categories-routing.module'; + +describe('MenuCategoriesRoutingModule', () => { + let menuCategoriesRoutingModule: MenuCategoriesRoutingModule; + + beforeEach(() => { + menuCategoriesRoutingModule = new MenuCategoriesRoutingModule(); + }); + + it('should create an instance', () => { + expect(menuCategoriesRoutingModule).toBeTruthy(); + }); +}); diff --git a/bookie/src/app/menu-category/menu-categories-routing.module.ts b/bookie/src/app/menu-category/menu-categories-routing.module.ts new file mode 100644 index 0000000..7637fbb --- /dev/null +++ b/bookie/src/app/menu-category/menu-categories-routing.module.ts @@ -0,0 +1,61 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { RouterModule, Routes } from '@angular/router'; +import { MenuCategoryListResolver } from './menu-category-list-resolver.service'; +import { MenuCategoryResolver } from './menu-category-resolver.service'; +import { MenuCategoryListComponent } from './menu-category-list/menu-category-list.component'; +import { MenuCategoryDetailComponent } from './menu-category-detail/menu-category-detail.component'; +import { AuthGuard } from '../auth/auth-guard.service'; + +const menuCategoriesRoutes: Routes = [ + { + path: '', + component: MenuCategoryListComponent, + canActivate: [AuthGuard], + data: { + permission: 'Products' + }, + resolve: { + list: MenuCategoryListResolver + } + }, + { + path: 'new', + component: MenuCategoryDetailComponent, + canActivate: [AuthGuard], + data: { + permission: 'Products' + }, + resolve: { + item: MenuCategoryResolver + } + }, + { + path: ':id', + component: MenuCategoryDetailComponent, + canActivate: [AuthGuard], + data: { + permission: 'Products' + }, + resolve: { + item: MenuCategoryResolver + } + } +]; + +@NgModule({ + imports: [ + CommonModule, + RouterModule.forChild(menuCategoriesRoutes) + + ], + exports: [ + RouterModule + ], + providers: [ + MenuCategoryListResolver, + MenuCategoryResolver + ] +}) +export class MenuCategoriesRoutingModule { +} diff --git a/bookie/src/app/menu-category/menu-categories.module.spec.ts b/bookie/src/app/menu-category/menu-categories.module.spec.ts new file mode 100644 index 0000000..f2f3c17 --- /dev/null +++ b/bookie/src/app/menu-category/menu-categories.module.spec.ts @@ -0,0 +1,13 @@ +import {MenuCategoriesModule} from './menu-categories.module'; + +describe('MenuCategoriesModule', () => { + let menuCategoriesModule: MenuCategoriesModule; + + beforeEach(() => { + menuCategoriesModule = new MenuCategoriesModule(); + }); + + it('should create an instance', () => { + expect(menuCategoriesModule).toBeTruthy(); + }); +}); diff --git a/bookie/src/app/product-group/product-groups.module.ts b/bookie/src/app/menu-category/menu-categories.module.ts similarity index 58% rename from bookie/src/app/product-group/product-groups.module.ts rename to bookie/src/app/menu-category/menu-categories.module.ts index 415afad..3ac7e47 100644 --- a/bookie/src/app/product-group/product-groups.module.ts +++ b/bookie/src/app/menu-category/menu-categories.module.ts @@ -1,9 +1,9 @@ -import {NgModule} from '@angular/core'; -import {CommonModule} from '@angular/common'; +import { NgModule} from '@angular/core'; +import { CommonModule } from '@angular/common'; -import {ProductGroupListComponent} from './product-group-list/product-group-list.component'; -import {ProductGroupDetailComponent} from './product-group-detail/product-group-detail.component'; -import {ProductGroupsRoutingModule} from './product-groups-routing.module'; +import { MenuCategoryListComponent} from './menu-category-list/menu-category-list.component'; +import { MenuCategoryDetailComponent } from './menu-category-detail/menu-category-detail.component'; +import { MenuCategoriesRoutingModule } from './menu-categories-routing.module'; import { MatButtonModule } from '@angular/material/button'; import { MatCardModule } from '@angular/material/card'; import { MatCheckboxModule } from '@angular/material/checkbox'; @@ -13,8 +13,8 @@ import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; import { MatTableModule } from '@angular/material/table'; import { CdkTableModule } from '@angular/cdk/table'; import { DragDropModule } from '@angular/cdk/drag-drop'; -import {FlexLayoutModule} from '@angular/flex-layout'; -import {ReactiveFormsModule} from '@angular/forms'; +import { FlexLayoutModule } from '@angular/flex-layout'; +import { ReactiveFormsModule } from '@angular/forms'; @NgModule({ imports: [ @@ -30,12 +30,12 @@ import {ReactiveFormsModule} from '@angular/forms'; MatButtonModule, MatIconModule, ReactiveFormsModule, - ProductGroupsRoutingModule + MenuCategoriesRoutingModule ], declarations: [ - ProductGroupListComponent, - ProductGroupDetailComponent + MenuCategoryListComponent, + MenuCategoryDetailComponent ] }) -export class ProductGroupsModule { +export class MenuCategoriesModule { } diff --git a/bookie/src/app/product-group/product-group-detail/product-group-detail.component.css b/bookie/src/app/menu-category/menu-category-detail/menu-category-detail.component.css similarity index 100% rename from bookie/src/app/product-group/product-group-detail/product-group-detail.component.css rename to bookie/src/app/menu-category/menu-category-detail/menu-category-detail.component.css diff --git a/bookie/src/app/product-group/product-group-detail/product-group-detail.component.html b/bookie/src/app/menu-category/menu-category-detail/menu-category-detail.component.html similarity index 80% rename from bookie/src/app/product-group/product-group-detail/product-group-detail.component.html rename to bookie/src/app/menu-category/menu-category-detail/menu-category-detail.component.html index 3423ade..ea29386 100644 --- a/bookie/src/app/product-group/product-group-detail/product-group-detail.component.html +++ b/bookie/src/app/menu-category/menu-category-detail/menu-category-detail.component.html @@ -1,7 +1,7 @@
- Product Group + Menu Category
@@ -20,13 +20,6 @@ %
-
- - Group Type - - -
Is Modifier Compulsory? diff --git a/bookie/src/app/product-group/product-group-detail/product-group-detail.component.spec.ts b/bookie/src/app/menu-category/menu-category-detail/menu-category-detail.component.spec.ts similarity index 52% rename from bookie/src/app/product-group/product-group-detail/product-group-detail.component.spec.ts rename to bookie/src/app/menu-category/menu-category-detail/menu-category-detail.component.spec.ts index 5060015..fe09d89 100644 --- a/bookie/src/app/product-group/product-group-detail/product-group-detail.component.spec.ts +++ b/bookie/src/app/menu-category/menu-category-detail/menu-category-detail.component.spec.ts @@ -1,20 +1,20 @@ import {async, ComponentFixture, TestBed} from '@angular/core/testing'; -import {ProductGroupDetailComponent} from './product-group-detail.component'; +import {MenuCategoryDetailComponent} from './menu-category-detail.component'; -describe('ProductGroupDetailComponent', () => { - let component: ProductGroupDetailComponent; - let fixture: ComponentFixture; +describe('MenuCategoryDetailComponent', () => { + let component: MenuCategoryDetailComponent; + let fixture: ComponentFixture; beforeEach(async(() => { TestBed.configureTestingModule({ - declarations: [ProductGroupDetailComponent] + declarations: [MenuCategoryDetailComponent] }) .compileComponents(); })); beforeEach(() => { - fixture = TestBed.createComponent(ProductGroupDetailComponent); + fixture = TestBed.createComponent(MenuCategoryDetailComponent); component = fixture.componentInstance; fixture.detectChanges(); }); diff --git a/bookie/src/app/product-group/product-group-detail/product-group-detail.component.ts b/bookie/src/app/menu-category/menu-category-detail/menu-category-detail.component.ts similarity index 74% rename from bookie/src/app/product-group/product-group-detail/product-group-detail.component.ts rename to bookie/src/app/menu-category/menu-category-detail/menu-category-detail.component.ts index 8134b5d..7c9c309 100644 --- a/bookie/src/app/product-group/product-group-detail/product-group-detail.component.ts +++ b/bookie/src/app/menu-category/menu-category-detail/menu-category-detail.component.ts @@ -3,20 +3,20 @@ import { FormBuilder, FormGroup } from '@angular/forms'; import { ActivatedRoute, Router } from '@angular/router'; import { MatDialog } from "@angular/material"; -import { ProductGroupService } from '../product-group.service'; -import { ProductGroup } from '../../core/product-group'; +import { MenuCategoryService } from '../menu-category.service'; +import { MenuCategory } from '../../core/menu-category'; import { ToasterService } from '../../core/toaster.service'; import { ConfirmDialogComponent } from "../../shared/confirm-dialog/confirm-dialog.component"; @Component({ - selector: 'app-product-group-detail', - templateUrl: './product-group-detail.component.html', - styleUrls: ['./product-group-detail.component.css'] + selector: 'app-menu-category-detail', + templateUrl: './menu-category-detail.component.html', + styleUrls: ['./menu-category-detail.component.css'] }) -export class ProductGroupDetailComponent implements OnInit, AfterViewInit { +export class MenuCategoryDetailComponent implements OnInit, AfterViewInit { @ViewChild('nameElement', { static: true }) nameElement: ElementRef; form: FormGroup; - item: ProductGroup; + item: MenuCategory; constructor( private route: ActivatedRoute, @@ -24,7 +24,7 @@ export class ProductGroupDetailComponent implements OnInit, AfterViewInit { private dialog: MatDialog, private fb: FormBuilder, private toaster: ToasterService, - private ser: ProductGroupService + private ser: MenuCategoryService ) { this.createForm(); } @@ -34,25 +34,23 @@ export class ProductGroupDetailComponent implements OnInit, AfterViewInit { name: '', discountLimit: '', isModifierCompulsory: '', - groupType: '', isActive: '' }); } ngOnInit() { this.route.data - .subscribe((data: { item: ProductGroup }) => { + .subscribe((data: { item: MenuCategory }) => { this.showItem(data.item); }); } - showItem(item: ProductGroup) { + showItem(item: MenuCategory) { this.item = item; this.form.setValue({ name: this.item.name, discountLimit: this.item.discountLimit, isModifierCompulsory: this.item.isModifierCompulsory, - groupType: this.item.groupType, isActive: this.item.isActive }); } @@ -68,7 +66,7 @@ export class ProductGroupDetailComponent implements OnInit, AfterViewInit { .subscribe( (result) => { this.toaster.show('Success', ''); - this.router.navigateByUrl('/product-groups'); + this.router.navigateByUrl('/menu-categories'); }, (error) => { this.toaster.show('Danger', error.error); @@ -81,7 +79,7 @@ export class ProductGroupDetailComponent implements OnInit, AfterViewInit { .subscribe( (result) => { this.toaster.show('Success', ''); - this.router.navigateByUrl('/product-groups'); + this.router.navigateByUrl('/menu-categories'); }, (error) => { this.toaster.show('Danger', error.error); @@ -92,7 +90,7 @@ export class ProductGroupDetailComponent implements OnInit, AfterViewInit { confirmDelete(): void { const dialogRef = this.dialog.open(ConfirmDialogComponent, { width: '250px', - data: {title: 'Delete Product Group?', content: 'Are you sure? This cannot be undone.'} + data: {title: 'Delete Menu Category?', content: 'Are you sure? This cannot be undone.'} }); dialogRef.afterClosed().subscribe((result: boolean) => { @@ -102,12 +100,11 @@ export class ProductGroupDetailComponent implements OnInit, AfterViewInit { }); } - getItem(): ProductGroup { + getItem(): MenuCategory { const formModel = this.form.value; this.item.name = formModel.name; this.item.discountLimit = +formModel.discountLimit; this.item.isModifierCompulsory = formModel.isModifierCompulsory; - this.item.groupType = formModel.groupType; this.item.isActive = formModel.isActive; return this.item; } diff --git a/bookie/src/app/menu-category/menu-category-list-resolver.service.spec.ts b/bookie/src/app/menu-category/menu-category-list-resolver.service.spec.ts new file mode 100644 index 0000000..3afa2c4 --- /dev/null +++ b/bookie/src/app/menu-category/menu-category-list-resolver.service.spec.ts @@ -0,0 +1,14 @@ +import {inject, TestBed} from '@angular/core/testing'; +import {MenuCategoryListResolver} from './menu-category-list-resolver.service'; + +describe('MenuCategoryListResolver', () => { + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [MenuCategoryListResolver] + }); + }); + + it('should be created', inject([MenuCategoryListResolver], (service: MenuCategoryListResolver) => { + expect(service).toBeTruthy(); + })); +}); diff --git a/bookie/src/app/menu-category/menu-category-list-resolver.service.ts b/bookie/src/app/menu-category/menu-category-list-resolver.service.ts new file mode 100644 index 0000000..c0387d4 --- /dev/null +++ b/bookie/src/app/menu-category/menu-category-list-resolver.service.ts @@ -0,0 +1,18 @@ +import { Injectable } from '@angular/core'; +import { ActivatedRouteSnapshot, Resolve, Router, RouterStateSnapshot } from '@angular/router'; +import { MenuCategory } from '../core/menu-category'; +import { Observable } from 'rxjs/internal/Observable'; +import { MenuCategoryService } from './menu-category.service'; + +@Injectable({ + providedIn: 'root' +}) +export class MenuCategoryListResolver implements Resolve { + + constructor(private ser: MenuCategoryService, private router: Router) { + } + + resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable { + return this.ser.list(); + } +} diff --git a/bookie/src/app/product-group/product-group-list/product-group-list-datasource.ts b/bookie/src/app/menu-category/menu-category-list/menu-category-list-datasource.ts similarity index 50% rename from bookie/src/app/product-group/product-group-list/product-group-list-datasource.ts rename to bookie/src/app/menu-category/menu-category-list/menu-category-list-datasource.ts index a7bea3b..e0acc91 100644 --- a/bookie/src/app/product-group/product-group-list/product-group-list-datasource.ts +++ b/bookie/src/app/menu-category/menu-category-list/menu-category-list-datasource.ts @@ -1,19 +1,19 @@ import { DataSource } from '@angular/cdk/collections'; import { Observable } from 'rxjs'; -import { ProductGroup } from '../../core/product-group'; +import { MenuCategory } from '../../core/menu-category'; import { tap } from "rxjs/operators"; -export class ProductGroupListDataSource extends DataSource { - private data: ProductGroup[]; +export class MenuCategoryListDatasource extends DataSource { + private data: MenuCategory[]; - constructor(private readonly dataObs: Observable) { + constructor(private readonly dataObs: Observable) { super(); this.dataObs = dataObs.pipe( tap(x => this.data = x) ); } - connect(): Observable { + connect(): Observable { return this.dataObs; } diff --git a/bookie/src/app/product-group/product-group-list/product-group-list.component.css b/bookie/src/app/menu-category/menu-category-list/menu-category-list.component.css similarity index 100% rename from bookie/src/app/product-group/product-group-list/product-group-list.component.css rename to bookie/src/app/menu-category/menu-category-list/menu-category-list.component.css diff --git a/bookie/src/app/product-group/product-group-list/product-group-list.component.html b/bookie/src/app/menu-category/menu-category-list/menu-category-list.component.html similarity index 79% rename from bookie/src/app/product-group/product-group-list/product-group-list.component.html rename to bookie/src/app/menu-category/menu-category-list/menu-category-list.component.html index ee0c251..7f8a2f3 100644 --- a/bookie/src/app/product-group/product-group-list/product-group-list.component.html +++ b/bookie/src/app/menu-category/menu-category-list/menu-category-list.component.html @@ -1,10 +1,10 @@ - Product Groups + Menu Categories - + add_box Add @@ -15,7 +15,7 @@ Name - {{row.name}} + {{row.name}} @@ -30,12 +30,6 @@ {{row.isModifierCompulsory}} - - - Group Type - {{row.groupType}} - - Active? diff --git a/bookie/src/app/product-group/product-group-list/product-group-list.component.spec.ts b/bookie/src/app/menu-category/menu-category-list/menu-category-list.component.spec.ts similarity index 51% rename from bookie/src/app/product-group/product-group-list/product-group-list.component.spec.ts rename to bookie/src/app/menu-category/menu-category-list/menu-category-list.component.spec.ts index 939ebec..475399d 100644 --- a/bookie/src/app/product-group/product-group-list/product-group-list.component.spec.ts +++ b/bookie/src/app/menu-category/menu-category-list/menu-category-list.component.spec.ts @@ -1,18 +1,18 @@ import {ComponentFixture, fakeAsync, TestBed} from '@angular/core/testing'; -import {ProductGroupListComponent} from './product-group-list.component'; +import {MenuCategoryListComponent} from './menu-category-list.component'; -describe('ProductGroupListComponent', () => { - let component: ProductGroupListComponent; - let fixture: ComponentFixture; +describe('MenuCategoryListComponent', () => { + let component: MenuCategoryListComponent; + let fixture: ComponentFixture; beforeEach(fakeAsync(() => { TestBed.configureTestingModule({ - declarations: [ProductGroupListComponent] + declarations: [MenuCategoryListComponent] }) .compileComponents(); - fixture = TestBed.createComponent(ProductGroupListComponent); + fixture = TestBed.createComponent(MenuCategoryListComponent); component = fixture.componentInstance; fixture.detectChanges(); })); diff --git a/bookie/src/app/product-group/product-group-list/product-group-list.component.ts b/bookie/src/app/menu-category/menu-category-list/menu-category-list.component.ts similarity index 58% rename from bookie/src/app/product-group/product-group-list/product-group-list.component.ts rename to bookie/src/app/menu-category/menu-category-list/menu-category-list.component.ts index 47737a4..a2fe925 100644 --- a/bookie/src/app/product-group/product-group-list/product-group-list.component.ts +++ b/bookie/src/app/menu-category/menu-category-list/menu-category-list.component.ts @@ -1,44 +1,44 @@ import { Component, OnInit, ViewChild } from '@angular/core'; -import { ProductGroupListDataSource } from './product-group-list-datasource'; -import { ProductGroup } from '../../core/product-group'; +import { MenuCategoryListDatasource } from './menu-category-list-datasource'; +import { MenuCategory } from '../../core/menu-category'; import { ActivatedRoute, Router } from '@angular/router'; import { CdkDragDrop, moveItemInArray } from "@angular/cdk/drag-drop"; import { MatTable } from "@angular/material"; import { ToasterService } from "../../core/toaster.service"; -import { ProductGroupService } from "../product-group.service"; +import { MenuCategoryService } from "../menu-category.service"; import { BehaviorSubject } from "rxjs"; @Component({ - selector: 'app-product-group-list', - templateUrl: './product-group-list.component.html', - styleUrls: ['./product-group-list.component.css'] + selector: 'app-menu-category-list', + templateUrl: './menu-category-list.component.html', + styleUrls: ['./menu-category-list.component.css'] }) -export class ProductGroupListComponent implements OnInit { - @ViewChild('table', { static: true }) table: MatTable; - dataSource: ProductGroupListDataSource; - list: ProductGroup[]; - data: BehaviorSubject; +export class MenuCategoryListComponent implements OnInit { + @ViewChild('table', { static: true }) table: MatTable; + dataSource: MenuCategoryListDatasource; + list: MenuCategory[]; + data: BehaviorSubject; /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */ - displayedColumns = ['name', 'discountLimit', 'isModifierCompulsory', 'groupType', 'isActive', 'isFixture']; + displayedColumns = ['name', 'discountLimit', 'isModifierCompulsory', 'isActive', 'isFixture']; constructor( private route: ActivatedRoute, private router: Router, private toaster: ToasterService, - private ser: ProductGroupService + private ser: MenuCategoryService ) { this.data = new BehaviorSubject([]); - this.data.subscribe((data: ProductGroup[]) => { + this.data.subscribe((data: MenuCategory[]) => { this.list = data; }) } ngOnInit() { this.route.data - .subscribe((data: { list: ProductGroup[] }) => { + .subscribe((data: { list: MenuCategory[] }) => { this.data.next(data.list); }); - this.dataSource = new ProductGroupListDataSource(this.data); + this.dataSource = new MenuCategoryListDatasource(this.data); } updateSortOrder() { @@ -53,7 +53,7 @@ export class ProductGroupListComponent implements OnInit { ); } - dropTable(event: CdkDragDrop) { + dropTable(event: CdkDragDrop) { const prevIndex = this.list.indexOf(event.item.data); moveItemInArray(this.list, prevIndex, event.currentIndex); this.data.next(this.list); diff --git a/bookie/src/app/menu-category/menu-category-resolver.service.spec.ts b/bookie/src/app/menu-category/menu-category-resolver.service.spec.ts new file mode 100644 index 0000000..1fe7ae1 --- /dev/null +++ b/bookie/src/app/menu-category/menu-category-resolver.service.spec.ts @@ -0,0 +1,14 @@ +import { inject, TestBed } from '@angular/core/testing'; +import { MenuCategoryResolver } from './menu-category-resolver.service'; + +describe('MenuCategoryResolver', () => { + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [MenuCategoryResolver] + }); + }); + + it('should be created', inject([MenuCategoryResolver], (service: MenuCategoryResolver) => { + expect(service).toBeTruthy(); + })); +}); diff --git a/bookie/src/app/menu-category/menu-category-resolver.service.ts b/bookie/src/app/menu-category/menu-category-resolver.service.ts new file mode 100644 index 0000000..599b8b2 --- /dev/null +++ b/bookie/src/app/menu-category/menu-category-resolver.service.ts @@ -0,0 +1,19 @@ +import { Injectable } from '@angular/core'; +import { ActivatedRouteSnapshot, Resolve, Router, RouterStateSnapshot } from '@angular/router'; +import { MenuCategoryService } from './menu-category.service'; +import { MenuCategory } from '../core/menu-category'; +import { Observable } from 'rxjs/internal/Observable'; + +@Injectable({ + providedIn: 'root' +}) +export class MenuCategoryResolver implements Resolve { + + constructor(private ser: MenuCategoryService, private router: Router) { + } + + resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable { + const id = route.paramMap.get('id'); + return this.ser.get(id); + } +} diff --git a/bookie/src/app/menu-category/menu-category.service.spec.ts b/bookie/src/app/menu-category/menu-category.service.spec.ts new file mode 100644 index 0000000..2f9dfd6 --- /dev/null +++ b/bookie/src/app/menu-category/menu-category.service.spec.ts @@ -0,0 +1,15 @@ +import {inject, TestBed} from '@angular/core/testing'; + +import {MenuCategoryService} from './menu-category.service'; + +describe('MenuCategoryService', () => { + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [MenuCategoryService] + }); + }); + + it('should be created', inject([MenuCategoryService], (service: MenuCategoryService) => { + expect(service).toBeTruthy(); + })); +}); diff --git a/bookie/src/app/product-group/product-group.service.ts b/bookie/src/app/menu-category/menu-category.service.ts similarity index 50% rename from bookie/src/app/product-group/product-group.service.ts rename to bookie/src/app/menu-category/menu-category.service.ts index ac5f589..3c15e52 100644 --- a/bookie/src/app/product-group/product-group.service.ts +++ b/bookie/src/app/menu-category/menu-category.service.ts @@ -3,68 +3,68 @@ import {HttpClient, HttpHeaders, HttpParams} from '@angular/common/http'; import {ErrorLoggerService} from '../core/error-logger.service'; import {catchError} from 'rxjs/operators'; import {Observable} from 'rxjs/internal/Observable'; -import {ProductGroup} from '../core/product-group'; +import {MenuCategory} from '../core/menu-category'; const httpOptions = { headers: new HttpHeaders({'Content-Type': 'application/json'}) }; -const url = '/v1/product-groups'; -const serviceName = 'ProductGroupService'; +const url = '/v1/menu-categories'; +const serviceName = 'MenuCategoryService'; @Injectable({ providedIn: 'root' }) -export class ProductGroupService { +export class MenuCategoryService { constructor(private http: HttpClient, private log: ErrorLoggerService) { } - get(id: string): Observable { + get(id: string): Observable { const getUrl: string = (id === null) ? `${url}/new` : `${url}/${id}`; - return >this.http.get(getUrl) + return >this.http.get(getUrl) .pipe( catchError(this.log.handleError(serviceName, `get id=${id}`)) ); } - list(): Observable { + list(): Observable { const options = {params: new HttpParams().set('l', '')}; - return >this.http.get(url, options) + return >this.http.get(url, options) .pipe( catchError(this.log.handleError(serviceName, 'list')) ); } - save(productGroup: ProductGroup): Observable { - return >this.http.post(`${url}/new`, productGroup, httpOptions) + save(menuCategory: MenuCategory): Observable { + return >this.http.post(`${url}/new`, menuCategory, httpOptions) .pipe( catchError(this.log.handleError(serviceName, 'save')) ); } - update(productGroup: ProductGroup): Observable { - return >this.http.put(`${url}/${productGroup.id}`, productGroup, httpOptions) + update(menuCategory: MenuCategory): Observable { + return >this.http.put(`${url}/${menuCategory.id}`, menuCategory, httpOptions) .pipe( catchError(this.log.handleError(serviceName, 'update')) ); } - updateSortOrder(list: ProductGroup[]): Observable { - return >this.http.post(url, list, httpOptions) + updateSortOrder(list: MenuCategory[]): Observable { + return >this.http.post(url, list, httpOptions) .pipe( catchError(this.log.handleError(serviceName, 'updateSortOrder')) ); } - saveOrUpdate(productGroup: ProductGroup): Observable { - if (!productGroup.id) { - return this.save(productGroup); + saveOrUpdate(menuCategory: MenuCategory): Observable { + if (!menuCategory.id) { + return this.save(menuCategory); } else { - return this.update(productGroup); + return this.update(menuCategory); } } - delete(id: string): Observable { - return >this.http.delete(`${url}/${id}`, httpOptions) + delete(id: string): Observable { + return >this.http.delete(`${url}/${id}`, httpOptions) .pipe( catchError(this.log.handleError(serviceName, 'delete')) ); diff --git a/bookie/src/app/product-group/product-group-list-resolver.service.spec.ts b/bookie/src/app/product-group/product-group-list-resolver.service.spec.ts deleted file mode 100644 index 864d865..0000000 --- a/bookie/src/app/product-group/product-group-list-resolver.service.spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import {inject, TestBed} from '@angular/core/testing'; - -import {ProductGroupListResolverService} from './product-group-list-resolver.service'; - -describe('ProductGroupListResolverService', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [ProductGroupListResolverService] - }); - }); - - it('should be created', inject([ProductGroupListResolverService], (service: ProductGroupListResolverService) => { - expect(service).toBeTruthy(); - })); -}); diff --git a/bookie/src/app/product-group/product-group-list-resolver.service.ts b/bookie/src/app/product-group/product-group-list-resolver.service.ts deleted file mode 100644 index e27be64..0000000 --- a/bookie/src/app/product-group/product-group-list-resolver.service.ts +++ /dev/null @@ -1,18 +0,0 @@ -import {Injectable} from '@angular/core'; -import {ActivatedRouteSnapshot, Resolve, Router, RouterStateSnapshot} from '@angular/router'; -import {ProductGroup} from '../core/product-group'; -import {Observable} from 'rxjs/internal/Observable'; -import {ProductGroupService} from './product-group.service'; - -@Injectable({ - providedIn: 'root' -}) -export class ProductGroupListResolver implements Resolve { - - constructor(private ser: ProductGroupService, private router: Router) { - } - - resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable { - return this.ser.list(); - } -} diff --git a/bookie/src/app/product-group/product-group-resolver.service.spec.ts b/bookie/src/app/product-group/product-group-resolver.service.spec.ts deleted file mode 100644 index 0200b56..0000000 --- a/bookie/src/app/product-group/product-group-resolver.service.spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import {inject, TestBed} from '@angular/core/testing'; - -import {ProductGroupResolver} from './product-group-resolver.service'; - -describe('ProductGroupResolver', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [ProductGroupResolver] - }); - }); - - it('should be created', inject([ProductGroupResolver], (service: ProductGroupResolver) => { - expect(service).toBeTruthy(); - })); -}); diff --git a/bookie/src/app/product-group/product-group-resolver.service.ts b/bookie/src/app/product-group/product-group-resolver.service.ts deleted file mode 100644 index 85e2ff8..0000000 --- a/bookie/src/app/product-group/product-group-resolver.service.ts +++ /dev/null @@ -1,19 +0,0 @@ -import {Injectable} from '@angular/core'; -import {ActivatedRouteSnapshot, Resolve, Router, RouterStateSnapshot} from '@angular/router'; -import {ProductGroupService} from './product-group.service'; -import {ProductGroup} from '../core/product-group'; -import {Observable} from 'rxjs/internal/Observable'; - -@Injectable({ - providedIn: 'root' -}) -export class ProductGroupResolver implements Resolve { - - constructor(private ser: ProductGroupService, private router: Router) { - } - - resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable { - const id = route.paramMap.get('id'); - return this.ser.get(id); - } -} diff --git a/bookie/src/app/product-group/product-group.service.spec.ts b/bookie/src/app/product-group/product-group.service.spec.ts deleted file mode 100644 index 9f9dd7d..0000000 --- a/bookie/src/app/product-group/product-group.service.spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import {inject, TestBed} from '@angular/core/testing'; - -import {ProductGroupService} from './product-group.service'; - -describe('ProductGroupService', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [ProductGroupService] - }); - }); - - it('should be created', inject([ProductGroupService], (service: ProductGroupService) => { - expect(service).toBeTruthy(); - })); -}); diff --git a/bookie/src/app/product-group/product-groups-routing.module.spec.ts b/bookie/src/app/product-group/product-groups-routing.module.spec.ts deleted file mode 100644 index 56bfefe..0000000 --- a/bookie/src/app/product-group/product-groups-routing.module.spec.ts +++ /dev/null @@ -1,13 +0,0 @@ -import {ProductGroupsRoutingModule} from './product-groups-routing.module'; - -describe('ProductGroupsRoutingModule', () => { - let productGroupsRoutingModule: ProductGroupsRoutingModule; - - beforeEach(() => { - productGroupsRoutingModule = new ProductGroupsRoutingModule(); - }); - - it('should create an instance', () => { - expect(productGroupsRoutingModule).toBeTruthy(); - }); -}); diff --git a/bookie/src/app/product-group/product-groups-routing.module.ts b/bookie/src/app/product-group/product-groups-routing.module.ts deleted file mode 100644 index 189e65c..0000000 --- a/bookie/src/app/product-group/product-groups-routing.module.ts +++ /dev/null @@ -1,61 +0,0 @@ -import {NgModule} from '@angular/core'; -import {CommonModule} from '@angular/common'; -import {RouterModule, Routes} from '@angular/router'; -import {ProductGroupListResolver} from './product-group-list-resolver.service'; -import {ProductGroupResolver} from './product-group-resolver.service'; -import {ProductGroupListComponent} from './product-group-list/product-group-list.component'; -import {ProductGroupDetailComponent} from './product-group-detail/product-group-detail.component'; -import {AuthGuard} from '../auth/auth-guard.service'; - -const productGroupRoutes: Routes = [ - { - path: '', - component: ProductGroupListComponent, - canActivate: [AuthGuard], - data: { - permission: 'Products' - }, - resolve: { - list: ProductGroupListResolver - } - }, - { - path: 'new', - component: ProductGroupDetailComponent, - canActivate: [AuthGuard], - data: { - permission: 'Products' - }, - resolve: { - item: ProductGroupResolver - } - }, - { - path: ':id', - component: ProductGroupDetailComponent, - canActivate: [AuthGuard], - data: { - permission: 'Products' - }, - resolve: { - item: ProductGroupResolver - } - } -]; - -@NgModule({ - imports: [ - CommonModule, - RouterModule.forChild(productGroupRoutes) - - ], - exports: [ - RouterModule - ], - providers: [ - ProductGroupListResolver, - ProductGroupResolver - ] -}) -export class ProductGroupsRoutingModule { -} diff --git a/bookie/src/app/product-group/product-groups.module.spec.ts b/bookie/src/app/product-group/product-groups.module.spec.ts deleted file mode 100644 index 566075a..0000000 --- a/bookie/src/app/product-group/product-groups.module.spec.ts +++ /dev/null @@ -1,13 +0,0 @@ -import {ProductGroupsModule} from './product-groups.module'; - -describe('ProductGroupsModule', () => { - let productGroupsModule: ProductGroupsModule; - - beforeEach(() => { - productGroupsModule = new ProductGroupsModule(); - }); - - it('should create an instance', () => { - expect(productGroupsModule).toBeTruthy(); - }); -}); diff --git a/bookie/src/app/product/product-detail/product-detail.component.html b/bookie/src/app/product/product-detail/product-detail.component.html index 824c5a2..06b2f97 100644 --- a/bookie/src/app/product/product-detail/product-detail.component.html +++ b/bookie/src/app/product/product-detail/product-detail.component.html @@ -16,7 +16,7 @@ fxLayoutGap.lt-md="0px"> Name - + Units @@ -43,18 +43,18 @@
- Product Type - - - {{ pg.name }} + Menu Category + + + {{ mc.name }} - Tax - - - {{ t.name }} + Sale Category + + + {{ sc.name }} 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 1c98191..a5f7d67 100644 --- a/bookie/src/app/product/product-detail/product-detail.component.ts +++ b/bookie/src/app/product/product-detail/product-detail.component.ts @@ -3,11 +3,11 @@ import { ToasterService } from '../../core/toaster.service'; import { ActivatedRoute, Router } from '@angular/router'; import { ProductService } from '../product.service'; import { Product } from '../../core/product'; -import { ProductGroup } from '../../core/product-group'; +import { MenuCategory } from '../../core/menu-category'; import { ConfirmDialogComponent } from '../../shared/confirm-dialog/confirm-dialog.component'; import { MatDialog } from '@angular/material/dialog'; import { FormBuilder, FormGroup } from '@angular/forms'; -import { Tax } from "../../core/tax"; +import { SaleCategory } from "../../core/sale-category"; @Component({ selector: 'app-product-detail', @@ -17,8 +17,8 @@ import { Tax } from "../../core/tax"; export class ProductDetailComponent implements OnInit, AfterViewInit { @ViewChild('name', { static: true }) nameElement: ElementRef; form: FormGroup; - productGroups: ProductGroup[]; - taxes: Tax[]; + menuCategories: MenuCategory[]; + saleCategories: SaleCategory[]; item: Product; constructor( @@ -37,8 +37,8 @@ export class ProductDetailComponent implements OnInit, AfterViewInit { code: {value: '', disabled: true}, name: '', units: '', - productGroup: '', - tax: '', + menuCategory: '', + saleCategory: '', price: '', hasHappyHour: '', isNotAvailable: '', @@ -49,9 +49,10 @@ export class ProductDetailComponent implements OnInit, AfterViewInit { ngOnInit() { this.route.data - .subscribe((data: { item: Product, productGroups: ProductGroup[], taxes: Tax[] }) => { - this.productGroups = data.productGroups; - this.taxes = data.taxes; + .subscribe((data: { item: Product, menuCategories: MenuCategory[], saleCategories: SaleCategory[] }) => { + this.menuCategories = data.menuCategories; + this.saleCategories = data.saleCategories; + console.log(this.saleCategories); this.showItem(data.item); }); } @@ -62,8 +63,8 @@ export class ProductDetailComponent implements OnInit, AfterViewInit { code: this.item.code || '(Auto)', name: this.item.name || '', units: this.item.units || '', - productGroup: this.item.tax.id ? this.item.tax.id : '', - tax: this.item.productGroup.id ? this.item.productGroup.id : '', + menuCategory: this.item.menuCategory.id ? this.item.menuCategory.id : '', + saleCategory: this.item.saleCategory.id ? this.item.saleCategory.id : '', price: this.item.price || '', hasHappyHour: this.item.hasHappyHour, isNotAvailable: this.item.isNotAvailable, @@ -121,8 +122,8 @@ export class ProductDetailComponent implements OnInit, AfterViewInit { const formModel = this.form.value; this.item.name = formModel.name; this.item.units = formModel.units; - this.item.productGroup.id = formModel.productGroup; - this.item.tax.id = formModel.tax; + this.item.menuCategory.id = formModel.menuCategory; + this.item.saleCategory.id = formModel.saleCategory; this.item.price = +formModel.price; this.item.hasHappyHour = formModel.hasHappyHour; this.item.isNotAvailable = formModel.isNotAvailable; diff --git a/bookie/src/app/product/product-list/product-list-datasource.ts b/bookie/src/app/product/product-list/product-list-datasource.ts index 74561d5..ba95436 100644 --- a/bookie/src/app/product/product-list/product-list-datasource.ts +++ b/bookie/src/app/product/product-list/product-list-datasource.ts @@ -41,7 +41,7 @@ export class ProductListDataSource extends DataSource { private getFilteredData(data: Product[]): Product[] { const filter = (this.filterValue === undefined) ? "" : this.filterValue; return data.filter(x => { - return x.productGroup.id === filter || filter === ""; + return x.menuCategory.id === filter || filter === ""; } ); } diff --git a/bookie/src/app/product/product-list/product-list.component.html b/bookie/src/app/product/product-list/product-list.component.html index b5976ab..e50fd92 100644 --- a/bookie/src/app/product/product-list/product-list.component.html +++ b/bookie/src/app/product/product-list/product-list.component.html @@ -18,10 +18,10 @@ fxLayoutGap.lt-md="0px"> Product Type - + -- All Products -- - - {{ pg.name }} + + {{ mc.name }} @@ -41,16 +41,16 @@ {{row.price | currency:'INR'}} - - - Product Group - {{row.productGroup.name}} + + + Menu Category + {{row.menuCategory.name}} - - - Tax - {{row.tax.rate | percent:'1.2-2'}} {{row.tax.name}} + + + Sale Category + {{row.saleCategory.name}} diff --git a/bookie/src/app/product/product-list/product-list.component.ts b/bookie/src/app/product/product-list/product-list.component.ts index 3194173..176cc4c 100644 --- a/bookie/src/app/product/product-list/product-list.component.ts +++ b/bookie/src/app/product/product-list/product-list.component.ts @@ -8,7 +8,7 @@ import { Product } from '../../core/product'; import { ToCsvService } from "../../shared/to-csv.service"; import { ToasterService } from "../../core/toaster.service"; import { ProductService } from "../product.service"; -import { ProductGroup } from "../../core/product-group"; +import { MenuCategory } from "../../core/menu-category"; import { BehaviorSubject } from "rxjs"; @Component({ @@ -23,9 +23,9 @@ export class ProductListComponent implements OnInit { form: FormGroup; list: Product[]; data: BehaviorSubject; - productGroups: ProductGroup[]; + menuCategories: MenuCategory[]; /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */ - displayedColumns: string[] = ['name', 'price', 'productGroup', 'tax', 'info', 'quantity']; + displayedColumns: string[] = ['name', 'price', 'menuCategory', 'saleCategory', 'info', 'quantity']; constructor( private route: ActivatedRoute, @@ -36,7 +36,7 @@ export class ProductListComponent implements OnInit { private ser: ProductService ) { this.form = this.fb.group({ - productGroup: '' + menuCategory: '' }); this.filter = new BehaviorSubject(""); this.data = new BehaviorSubject([]); @@ -51,9 +51,9 @@ export class ProductListComponent implements OnInit { ngOnInit() { this.route.data - .subscribe((data: { list: Product[], productGroups: ProductGroup[] }) => { + .subscribe((data: { list: Product[], menuCategories: MenuCategory[] }) => { this.data.next(data.list); - this.productGroups = data.productGroups; + this.menuCategories = data.menuCategories; }); this.dataSource = new ProductListDataSource(this.filter, this.data); } @@ -83,8 +83,8 @@ export class ProductListComponent implements OnInit { Name: 'name', Units: 'units', Price: 'price', - ProductGroup: 'productGroup', - Tax: 'tax' + MenuCategory: 'menuCategory', + SaleCategory: 'saleCategory' }; const csvData = new Blob([this.toCsv.toCsv(headers, this.dataSource.viewData)], {type: 'text/csv;charset=utf-8;'}); diff --git a/bookie/src/app/product/products-routing.module.ts b/bookie/src/app/product/products-routing.module.ts index 8ace696..057c16f 100644 --- a/bookie/src/app/product/products-routing.module.ts +++ b/bookie/src/app/product/products-routing.module.ts @@ -8,8 +8,8 @@ import { ProductDetailComponent } from './product-detail/product-detail.componen import { ProductListComponent } from './product-list/product-list.component'; import { AuthGuard } from '../auth/auth-guard.service'; -import { ProductGroupListResolver } from '../product-group/product-group-list-resolver.service'; -import { TaxListResolver } from "../taxes/tax-list-resolver.service"; +import { MenuCategoryListResolver } from '../menu-category/menu-category-list-resolver.service'; +import { SaleCategoryListResolver } from "../sale-category/sale-category-list-resolver.service"; const productRoutes: Routes = [ { @@ -21,7 +21,7 @@ const productRoutes: Routes = [ }, resolve: { list: ProductListResolver, - productGroups: ProductGroupListResolver + menuCategories: MenuCategoryListResolver } }, { @@ -33,8 +33,8 @@ const productRoutes: Routes = [ }, resolve: { item: ProductResolver, - productGroups: ProductGroupListResolver, - taxes: TaxListResolver + menuCategories: MenuCategoryListResolver, + saleCategories: SaleCategoryListResolver } }, { @@ -46,8 +46,8 @@ const productRoutes: Routes = [ }, resolve: { item: ProductResolver, - productGroups: ProductGroupListResolver, - taxes: TaxListResolver + menuCategories: MenuCategoryListResolver, + saleCategories: SaleCategoryListResolver } } ]; diff --git a/bookie/src/app/sale-category/sale-categories-routing.module.spec.ts b/bookie/src/app/sale-category/sale-categories-routing.module.spec.ts new file mode 100644 index 0000000..7dcf3a6 --- /dev/null +++ b/bookie/src/app/sale-category/sale-categories-routing.module.spec.ts @@ -0,0 +1,13 @@ +import {SaleCategoriesRoutingModule} from './sale-categories-routing.module'; + +describe('SaleCategoriesRoutingModule', () => { + let saleCategoriesRoutingModule: SaleCategoriesRoutingModule; + + beforeEach(() => { + saleCategoriesRoutingModule = new SaleCategoriesRoutingModule(); + }); + + it('should create an instance', () => { + expect(saleCategoriesRoutingModule).toBeTruthy(); + }); +}); diff --git a/bookie/src/app/sale-category/sale-categories-routing.module.ts b/bookie/src/app/sale-category/sale-categories-routing.module.ts new file mode 100644 index 0000000..851a619 --- /dev/null +++ b/bookie/src/app/sale-category/sale-categories-routing.module.ts @@ -0,0 +1,64 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { RouterModule, Routes } from '@angular/router'; +import { SaleCategoryListResolver } from './sale-category-list-resolver.service'; +import { SaleCategoryResolver } from './sale-category-resolver.service'; +import { SaleCategoryListComponent } from './sale-category-list/sale-category-list.component'; +import { SaleCategoryDetailComponent } from './sale-category-detail/sale-category-detail.component'; +import { AuthGuard } from '../auth/auth-guard.service'; +import { TaxListResolver } from "../taxes/tax-list-resolver.service"; + +const saleCategoriesRoutes: Routes = [ + { + path: '', + component: SaleCategoryListComponent, + canActivate: [AuthGuard], + data: { + permission: 'Products' + }, + resolve: { + list: SaleCategoryListResolver + } + }, + { + path: 'new', + component: SaleCategoryDetailComponent, + canActivate: [AuthGuard], + data: { + permission: 'Products' + }, + resolve: { + item: SaleCategoryResolver, + taxes: TaxListResolver + } + }, + { + path: ':id', + component: SaleCategoryDetailComponent, + canActivate: [AuthGuard], + data: { + permission: 'Products' + }, + resolve: { + item: SaleCategoryResolver, + taxes: TaxListResolver + } + } +]; + +@NgModule({ + imports: [ + CommonModule, + RouterModule.forChild(saleCategoriesRoutes) + + ], + exports: [ + RouterModule + ], + providers: [ + SaleCategoryListResolver, + SaleCategoryResolver + ] +}) +export class SaleCategoriesRoutingModule { +} diff --git a/bookie/src/app/sale-category/sale-categories.module.spec.ts b/bookie/src/app/sale-category/sale-categories.module.spec.ts new file mode 100644 index 0000000..ba7c469 --- /dev/null +++ b/bookie/src/app/sale-category/sale-categories.module.spec.ts @@ -0,0 +1,13 @@ +import {SaleCategoriesModule} from './sale-categories.module'; + +describe('SaleCategoriesModule', () => { + let saleCategoriesModule: SaleCategoriesModule; + + beforeEach(() => { + saleCategoriesModule = new SaleCategoriesModule(); + }); + + it('should create an instance', () => { + expect(saleCategoriesModule).toBeTruthy(); + }); +}); diff --git a/bookie/src/app/sale-category/sale-categories.module.ts b/bookie/src/app/sale-category/sale-categories.module.ts new file mode 100644 index 0000000..6464ce6 --- /dev/null +++ b/bookie/src/app/sale-category/sale-categories.module.ts @@ -0,0 +1,41 @@ +import { NgModule} from '@angular/core'; +import { CommonModule } from '@angular/common'; + +import { SaleCategoryListComponent} from './sale-category-list/sale-category-list.component'; +import { SaleCategoryDetailComponent } from './sale-category-detail/sale-category-detail.component'; +import { SaleCategoriesRoutingModule } from './sale-categories-routing.module'; +import { MatButtonModule } from '@angular/material/button'; +import { MatCardModule } from '@angular/material/card'; +import { MatCheckboxModule } from '@angular/material/checkbox'; +import { MatIconModule } from '@angular/material/icon'; +import { MatInputModule } from '@angular/material/input'; +import { MatOptionModule } from '@angular/material/core'; +import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; +import { MatSelectModule } from '@angular/material/select'; +import { MatTableModule } from '@angular/material/table'; +import { FlexLayoutModule } from '@angular/flex-layout'; +import { ReactiveFormsModule } from '@angular/forms'; + +@NgModule({ + imports: [ + CommonModule, + FlexLayoutModule, + MatButtonModule, + MatCardModule, + MatCheckboxModule, + MatIconModule, + MatInputModule, + MatOptionModule, + MatProgressSpinnerModule, + MatSelectModule, + MatTableModule, + ReactiveFormsModule, + SaleCategoriesRoutingModule + ], + declarations: [ + SaleCategoryListComponent, + SaleCategoryDetailComponent + ] +}) +export class SaleCategoriesModule { +} diff --git a/bookie/src/app/sale-category/sale-category-detail/sale-category-detail.component.css b/bookie/src/app/sale-category/sale-category-detail/sale-category-detail.component.css new file mode 100644 index 0000000..82c7afd --- /dev/null +++ b/bookie/src/app/sale-category/sale-category-detail/sale-category-detail.component.css @@ -0,0 +1,3 @@ +.example-card { + max-width: 400px; +} diff --git a/bookie/src/app/sale-category/sale-category-detail/sale-category-detail.component.html b/bookie/src/app/sale-category/sale-category-detail/sale-category-detail.component.html new file mode 100644 index 0000000..9ac015d --- /dev/null +++ b/bookie/src/app/sale-category/sale-category-detail/sale-category-detail.component.html @@ -0,0 +1,33 @@ +
+ + + Sale Category + + + +
+ + Name + + +
+
+ + Tax + + + {{ t.name }} + + + +
+ +
+ + + + +
+
diff --git a/bookie/src/app/sale-category/sale-category-detail/sale-category-detail.component.spec.ts b/bookie/src/app/sale-category/sale-category-detail/sale-category-detail.component.spec.ts new file mode 100644 index 0000000..c9b6537 --- /dev/null +++ b/bookie/src/app/sale-category/sale-category-detail/sale-category-detail.component.spec.ts @@ -0,0 +1,25 @@ +import {async, ComponentFixture, TestBed} from '@angular/core/testing'; + +import {SaleCategoryDetailComponent} from './sale-category-detail.component'; + +describe('SaleCategoryDetailComponent', () => { + let component: SaleCategoryDetailComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [SaleCategoryDetailComponent] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(SaleCategoryDetailComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/bookie/src/app/sale-category/sale-category-detail/sale-category-detail.component.ts b/bookie/src/app/sale-category/sale-category-detail/sale-category-detail.component.ts new file mode 100644 index 0000000..2c41cb0 --- /dev/null +++ b/bookie/src/app/sale-category/sale-category-detail/sale-category-detail.component.ts @@ -0,0 +1,108 @@ +import { AfterViewInit, Component, ElementRef, OnInit, ViewChild } from '@angular/core'; +import { FormBuilder, FormGroup } from '@angular/forms'; +import { ActivatedRoute, Router } from '@angular/router'; +import { MatDialog } from "@angular/material"; + +import { SaleCategoryService } from '../sale-category.service'; +import { SaleCategory } from '../../core/sale-category'; +import { ToasterService } from '../../core/toaster.service'; +import { ConfirmDialogComponent } from "../../shared/confirm-dialog/confirm-dialog.component"; +import { Tax } from "../../core/tax"; + +@Component({ + selector: 'app-sale-category-detail', + templateUrl: './sale-category-detail.component.html', + styleUrls: ['./sale-category-detail.component.css'] +}) +export class SaleCategoryDetailComponent implements OnInit, AfterViewInit { + @ViewChild('nameElement', { static: true }) nameElement: ElementRef; + form: FormGroup; + taxes: Tax[]; + item: SaleCategory; + + constructor( + private route: ActivatedRoute, + private router: Router, + private dialog: MatDialog, + private fb: FormBuilder, + private toaster: ToasterService, + private ser: SaleCategoryService + ) { + this.createForm(); + } + + createForm() { + this.form = this.fb.group({ + name: '', + tax: '' + }); + } + + ngOnInit() { + this.route.data + .subscribe((data: { item: SaleCategory, taxes: Tax[] }) => { + this.showItem(data.item); + this.taxes = data.taxes; + }); + } + + showItem(item: SaleCategory) { + this.item = item; + this.form.setValue({ + name: this.item.name, + tax: this.item.tax.id ? this.item.tax.id : '' + }); + } + + ngAfterViewInit() { + setTimeout(() => { + this.nameElement.nativeElement.focus(); + }, 0); + } + + save() { + this.ser.saveOrUpdate(this.getItem()) + .subscribe( + (result) => { + this.toaster.show('Success', ''); + this.router.navigateByUrl('/sale-categories'); + }, + (error) => { + this.toaster.show('Danger', error.error); + } + ); + } + + delete() { + this.ser.delete(this.item.id) + .subscribe( + (result) => { + this.toaster.show('Success', ''); + this.router.navigateByUrl('/sale-categories'); + }, + (error) => { + this.toaster.show('Danger', error.error); + } + ); + } + + confirmDelete(): void { + const dialogRef = this.dialog.open(ConfirmDialogComponent, { + width: '250px', + data: {title: 'Delete Sale Category?', content: 'Are you sure? This cannot be undone.'} + }); + + dialogRef.afterClosed().subscribe((result: boolean) => { + if (result) { + this.delete(); + } + }); + } + + getItem(): SaleCategory { + const formModel = this.form.value; + this.item.name = formModel.name; + this.item.tax.id = formModel.tax; + return this.item; + } +} diff --git a/bookie/src/app/sale-category/sale-category-list-resolver.service.spec.ts b/bookie/src/app/sale-category/sale-category-list-resolver.service.spec.ts new file mode 100644 index 0000000..0a45b1a --- /dev/null +++ b/bookie/src/app/sale-category/sale-category-list-resolver.service.spec.ts @@ -0,0 +1,14 @@ +import {inject, TestBed} from '@angular/core/testing'; +import {SaleCategoryListResolver} from './sale-category-list-resolver.service'; + +describe('SaleCategoryListResolver', () => { + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [SaleCategoryListResolver] + }); + }); + + it('should be created', inject([SaleCategoryListResolver], (service: SaleCategoryListResolver) => { + expect(service).toBeTruthy(); + })); +}); diff --git a/bookie/src/app/sale-category/sale-category-list-resolver.service.ts b/bookie/src/app/sale-category/sale-category-list-resolver.service.ts new file mode 100644 index 0000000..84fcc03 --- /dev/null +++ b/bookie/src/app/sale-category/sale-category-list-resolver.service.ts @@ -0,0 +1,18 @@ +import { Injectable } from '@angular/core'; +import { ActivatedRouteSnapshot, Resolve, Router, RouterStateSnapshot } from '@angular/router'; +import { SaleCategory } from '../core/sale-category'; +import { Observable } from 'rxjs/internal/Observable'; +import { SaleCategoryService } from './sale-category.service'; + +@Injectable({ + providedIn: 'root' +}) +export class SaleCategoryListResolver implements Resolve { + + constructor(private ser: SaleCategoryService, private router: Router) { + } + + resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable { + return this.ser.list(); + } +} diff --git a/bookie/src/app/sale-category/sale-category-list/sale-category-list-datasource.ts b/bookie/src/app/sale-category/sale-category-list/sale-category-list-datasource.ts new file mode 100644 index 0000000..a0dcc53 --- /dev/null +++ b/bookie/src/app/sale-category/sale-category-list/sale-category-list-datasource.ts @@ -0,0 +1,22 @@ +import { DataSource } from '@angular/cdk/collections'; +import { Observable } from 'rxjs'; +import { SaleCategory } from '../../core/sale-category'; +import { tap } from "rxjs/operators"; + +export class SaleCategoryListDatasource extends DataSource { + private data: SaleCategory[]; + + constructor(private readonly dataObs: Observable) { + super(); + this.dataObs = dataObs.pipe( + tap(x => this.data = x) + ); + } + + connect(): Observable { + return this.dataObs; + } + + disconnect() { + } +} diff --git a/bookie/src/app/sale-category/sale-category-list/sale-category-list.component.css b/bookie/src/app/sale-category/sale-category-list/sale-category-list.component.css new file mode 100644 index 0000000..e69de29 diff --git a/bookie/src/app/sale-category/sale-category-list/sale-category-list.component.html b/bookie/src/app/sale-category/sale-category-list/sale-category-list.component.html new file mode 100644 index 0000000..3c93f80 --- /dev/null +++ b/bookie/src/app/sale-category/sale-category-list/sale-category-list.component.html @@ -0,0 +1,28 @@ + + + Sale Categories + + add_box + Add + + + + + + + + Name + {{row.name}} + + + + +- Tax + {{row.tax.rate | percent:'1.2-2'}} {{row.tax.name}} + + + + + + + diff --git a/bookie/src/app/sale-category/sale-category-list/sale-category-list.component.spec.ts b/bookie/src/app/sale-category/sale-category-list/sale-category-list.component.spec.ts new file mode 100644 index 0000000..6e2f9af --- /dev/null +++ b/bookie/src/app/sale-category/sale-category-list/sale-category-list.component.spec.ts @@ -0,0 +1,23 @@ +import {ComponentFixture, fakeAsync, TestBed} from '@angular/core/testing'; + +import {SaleCategoryListComponent} from './sale-category-list.component'; + +describe('SaleCategoryListComponent', () => { + let component: SaleCategoryListComponent; + let fixture: ComponentFixture; + + beforeEach(fakeAsync(() => { + TestBed.configureTestingModule({ + declarations: [SaleCategoryListComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(SaleCategoryListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + })); + + it('should compile', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/bookie/src/app/sale-category/sale-category-list/sale-category-list.component.ts b/bookie/src/app/sale-category/sale-category-list/sale-category-list.component.ts new file mode 100644 index 0000000..6228afc --- /dev/null +++ b/bookie/src/app/sale-category/sale-category-list/sale-category-list.component.ts @@ -0,0 +1,42 @@ +import { Component, OnInit, ViewChild } from '@angular/core'; +import { SaleCategoryListDatasource } from './sale-category-list-datasource'; +import { SaleCategory } from '../../core/sale-category'; +import { ActivatedRoute, Router } from '@angular/router'; +import { MatTable } from "@angular/material"; +import { ToasterService } from "../../core/toaster.service"; +import { SaleCategoryService } from "../sale-category.service"; +import { BehaviorSubject } from "rxjs"; + +@Component({ + selector: 'app-sale-category-list', + templateUrl: './sale-category-list.component.html', + styleUrls: ['./sale-category-list.component.css'] +}) +export class SaleCategoryListComponent implements OnInit { + @ViewChild('table', { static: true }) table: MatTable; + dataSource: SaleCategoryListDatasource; + list: SaleCategory[]; + data: BehaviorSubject; + /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */ + displayedColumns = ['name', 'tax']; + + constructor( + private route: ActivatedRoute, + private router: Router, + private toaster: ToasterService, + private ser: SaleCategoryService + ) { + this.data = new BehaviorSubject([]); + this.data.subscribe((data: SaleCategory[]) => { + this.list = data; + }) + } + + ngOnInit() { + this.route.data + .subscribe((data: { list: SaleCategory[] }) => { + this.data.next(data.list); + }); + this.dataSource = new SaleCategoryListDatasource(this.data); + } +} diff --git a/bookie/src/app/sale-category/sale-category-resolver.service.spec.ts b/bookie/src/app/sale-category/sale-category-resolver.service.spec.ts new file mode 100644 index 0000000..446e4d1 --- /dev/null +++ b/bookie/src/app/sale-category/sale-category-resolver.service.spec.ts @@ -0,0 +1,14 @@ +import { inject, TestBed } from '@angular/core/testing'; +import { SaleCategoryResolver } from './sale-category-resolver.service'; + +describe('SaleCategoryResolver', () => { + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [SaleCategoryResolver] + }); + }); + + it('should be created', inject([SaleCategoryResolver], (service: SaleCategoryResolver) => { + expect(service).toBeTruthy(); + })); +}); diff --git a/bookie/src/app/sale-category/sale-category-resolver.service.ts b/bookie/src/app/sale-category/sale-category-resolver.service.ts new file mode 100644 index 0000000..4a94539 --- /dev/null +++ b/bookie/src/app/sale-category/sale-category-resolver.service.ts @@ -0,0 +1,19 @@ +import { Injectable } from '@angular/core'; +import { ActivatedRouteSnapshot, Resolve, Router, RouterStateSnapshot } from '@angular/router'; +import { SaleCategoryService } from './sale-category.service'; +import { SaleCategory } from '../core/sale-category'; +import { Observable } from 'rxjs/internal/Observable'; + +@Injectable({ + providedIn: 'root' +}) +export class SaleCategoryResolver implements Resolve { + + constructor(private ser: SaleCategoryService, private router: Router) { + } + + resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable { + const id = route.paramMap.get('id'); + return this.ser.get(id); + } +} diff --git a/bookie/src/app/sale-category/sale-category.service.spec.ts b/bookie/src/app/sale-category/sale-category.service.spec.ts new file mode 100644 index 0000000..43611b1 --- /dev/null +++ b/bookie/src/app/sale-category/sale-category.service.spec.ts @@ -0,0 +1,15 @@ +import {inject, TestBed} from '@angular/core/testing'; + +import {SaleCategoryService} from './sale-category.service'; + +describe('SaleCategoryService', () => { + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [SaleCategoryService] + }); + }); + + it('should be created', inject([SaleCategoryService], (service: SaleCategoryService) => { + expect(service).toBeTruthy(); + })); +}); diff --git a/bookie/src/app/sale-category/sale-category.service.ts b/bookie/src/app/sale-category/sale-category.service.ts new file mode 100644 index 0000000..47f43c1 --- /dev/null +++ b/bookie/src/app/sale-category/sale-category.service.ts @@ -0,0 +1,72 @@ +import {Injectable} from '@angular/core'; +import {HttpClient, HttpHeaders, HttpParams} from '@angular/common/http'; +import {ErrorLoggerService} from '../core/error-logger.service'; +import {catchError} from 'rxjs/operators'; +import {Observable} from 'rxjs/internal/Observable'; +import {SaleCategory} from '../core/sale-category'; + +const httpOptions = { + headers: new HttpHeaders({'Content-Type': 'application/json'}) +}; +const url = '/v1/sale-categories'; +const serviceName = 'SaleCategoryService'; + +@Injectable({ + providedIn: 'root' +}) +export class SaleCategoryService { + constructor(private http: HttpClient, private log: ErrorLoggerService) { + } + + get(id: string): Observable { + const getUrl: string = (id === null) ? `${url}/new` : `${url}/${id}`; + return >this.http.get(getUrl) + .pipe( + catchError(this.log.handleError(serviceName, `get id=${id}`)) + ); + } + + list(): Observable { + const options = {params: new HttpParams().set('l', '')}; + return >this.http.get(url, options) + .pipe( + catchError(this.log.handleError(serviceName, 'list')) + ); + } + + save(saleCategory: SaleCategory): Observable { + return >this.http.post(`${url}/new`, saleCategory, httpOptions) + .pipe( + catchError(this.log.handleError(serviceName, 'save')) + ); + } + + update(saleCategory: SaleCategory): Observable { + return >this.http.put(`${url}/${saleCategory.id}`, saleCategory, httpOptions) + .pipe( + catchError(this.log.handleError(serviceName, 'update')) + ); + } + + updateSortOrder(list: SaleCategory[]): Observable { + return >this.http.post(url, list, httpOptions) + .pipe( + catchError(this.log.handleError(serviceName, 'updateSortOrder')) + ); + } + + saveOrUpdate(saleCategory: SaleCategory): Observable { + if (!saleCategory.id) { + return this.save(saleCategory); + } else { + return this.update(saleCategory); + } + } + + delete(id: string): Observable { + return >this.http.delete(`${url}/${id}`, httpOptions) + .pipe( + catchError(this.log.handleError(serviceName, 'delete')) + ); + } +} 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 54806d6..bd7fba8 100644 --- a/bookie/src/app/tables/table-list/table-list.component.ts +++ b/bookie/src/app/tables/table-list/table-list.component.ts @@ -3,7 +3,7 @@ import { TableListDataSource } from './table-list-datasource'; import { Table } from '../../core/table'; import { ActivatedRoute, Router } from '@angular/router'; import { MatTable } from "@angular/material"; -import { ProductGroup } from "../../core/product-group"; +import { MenuCategory } from "../../core/menu-category"; import { BehaviorSubject } from "rxjs"; import { CdkDragDrop, moveItemInArray } from "@angular/cdk/drag-drop"; import { ToasterService } from "../../core/toaster.service"; @@ -15,7 +15,7 @@ import { TableService } from "../table.service"; styleUrls: ['./table-list.component.css'] }) export class TableListComponent implements OnInit { - @ViewChild('table', { static: true }) table: MatTable; + @ViewChild('table', { static: true }) table: MatTable; dataSource: TableListDataSource; list: Table[]; data: BehaviorSubject; @@ -54,7 +54,7 @@ export class TableListComponent implements OnInit { ); } - dropTable(event: CdkDragDrop) { + dropTable(event: CdkDragDrop) { const prevIndex = this.list.indexOf(event.item.data); moveItemInArray(this.list, prevIndex, event.currentIndex); this.data.next(this.list);