Modifier Category table added as a parent of modifiers

They are also linked to products / menu categroies as to which products they can be used on
The linking to menu categories is done in the frontend, database is linked directly to products
Treeview for menu categories yet to be done in modifier category detail form
This commit is contained in:
Amritanshu
2019-06-20 17:45:28 +05:30
parent 05f8058a15
commit e1c42d4470
34 changed files with 972 additions and 59 deletions

View File

@ -27,7 +27,7 @@ from .master import (
PrintLocation,
Product,
MenuCategory,
MenuCategoryModifier,
ModifierCategory,
SaleCategory,
SettleOption,
Tax

View File

@ -57,15 +57,17 @@ class Client(Base):
user_roles = Table(
'user_roles', Base.metadata,
Column('id', GUID(), primary_key=True, default=uuid.uuid4),
Column('user_id', GUID(), ForeignKey('users.id')),
Column('role_id', GUID(), ForeignKey('roles.id'))
Column('user_id', GUID(), ForeignKey('users.id'), nullable=False),
Column('role_id', GUID(), ForeignKey('roles.id'), nullable=False),
UniqueConstraint('user_id', 'role_id')
)
role_permissions = Table(
'role_permissions', Base.metadata,
Column('id', GUID(), primary_key=True, default=uuid.uuid4),
Column('permission_id', GUID(), ForeignKey('permissions.id')),
Column('role_id', GUID(), ForeignKey('roles.id'))
Column('permission_id', GUID(), ForeignKey('permissions.id'), nullable=False),
Column('role_id', GUID(), ForeignKey('roles.id'), nullable=False),
UniqueConstraint('permission_id', 'role_id')
)

View File

@ -10,7 +10,7 @@ from sqlalchemy import (
Integer,
case,
JSON,
)
Table)
from sqlalchemy.ext.hybrid import hybrid_property
from sqlalchemy.orm import relationship
from .meta import Base
@ -200,6 +200,34 @@ class Product(Base):
return True, ""
modifier_categories_products = Table(
'modifier_categories_products', Base.metadata,
Column('id', GUID(), primary_key=True, default=uuid.uuid4),
Column('product_id', GUID(), ForeignKey('products.id'), nullable=False),
Column('modifier_categories_id', GUID(), ForeignKey('modifier_categories.id'), nullable=False),
UniqueConstraint('product_id', 'modifier_categories_id')
)
class ModifierCategory(Base):
__tablename__ = "modifier_categories"
id = Column("id", GUID(), primary_key=True, default=uuid.uuid4)
name = Column("name", Unicode(255), nullable=False, unique=True)
minimum = Column("minimum", Integer, nullable=False)
maximum = Column("maximum", Integer, nullable=True)
sort_order = Column("sort_order", Numeric, nullable=False)
products = relationship("Product", secondary=modifier_categories_products, backref="modifier_categories")
def __init__(self, name=None, minimum=None, maximum=None, sort_order=0, id=None):
self.id = id
self.name = name
self.minimum = minimum
self.maximum = maximum
self.sort_order = sort_order
class Modifier(Base):
__tablename__ = "modifiers"
@ -207,38 +235,20 @@ class Modifier(Base):
name = Column("name", Unicode(255), nullable=False, unique=True)
show_in_bill = Column("show_in_bill", Boolean, nullable=False)
price = Column("price", Numeric, nullable=False)
modifier_category_id = Column(
"modifier_category_id", GUID(), ForeignKey("modifier_categories.id"), nullable=False
)
def __init__(self, name=None, show_in_bill=None, price=None, id=None):
modifier_category = relationship("ModifierCategory", backref="modifiers")
def __init__(self, name=None, show_in_bill=None, price=None, modifier_category_id=None, id=None):
self.id = id
self.name = name
self.show_in_bill = show_in_bill
self.modifier_category_id = modifier_category_id
self.price = price
class MenuCategoryModifier(Base):
__tablename__ = "menu_category_modifiers"
id = Column("id", GUID(), primary_key=True, default=uuid.uuid4)
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)
menu_category = relationship("MenuCategory", backref="modifiers")
modifier = relationship("Modifier", backref="menu_categories")
def __init__(
self, menu_category_id=None, modifier_id=None, show_automatically=None, id=None
):
self.id = id
self.menu_category_id = menu_category_id
self.modifier_id = modifier_id
self.show_automatically = show_automatically
class DbSetting(Base):
__tablename__ = "settings"

View File

@ -63,6 +63,14 @@ def includeme(config):
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("modifier_categories_new", "/modifier-categories/new")
config.add_route("modifier_categories_id", "/modifier-categories/{id}")
config.add_route("modifier_categories_list", "/modifier-categories")
config.add_route("v1_modifier_categories_new", "/v1/modifier-categories/new")
config.add_route("v1_modifier_categories_id", "/v1/modifier-categories/{id}")
config.add_route("v1_modifier_categories_list", "/v1/modifier-categories")
config.add_route("v1_modifier_category_types_list", "/v1/modifier-category-types")
config.add_route("v1_bills_new", "/v1/bills/new")
config.add_route("v1_bills_id", "/v1/bills/{id}")

View File

@ -32,7 +32,8 @@ from barker.models import (
Printer,
Product,
MenuCategory,
MenuCategoryModifier,
ModifierCategory,
SaleCategory,
Reprint,
Role,
role_permissions,

View File

@ -5,10 +5,10 @@ import transaction
from pyramid.view import view_config
from sqlalchemy import or_
from barker.models import Modifier, MenuCategoryModifier
from barker.models import Modifier, ModifierCategory
@view_config(request_method='PUT', route_name='modifier', renderer='json', permission='Modifiers', trans=True)
@view_config(request_method='POST', route_name='modifier', renderer='json', permission='Modifiers', trans=True)
def save(request):
json = request.json_body
item = Modifier(json['Name'], json['ShowInBill'], json['Price'])
@ -19,7 +19,7 @@ def save(request):
return modifier_info(item)
@view_config(request_method='POST', route_name='modifier_id', renderer='json', permission='Modifiers', trans=True)
@view_config(request_method='PUT', route_name='modifier_id', renderer='json', permission='Modifiers', trans=True)
def update(request):
json = request.json_body
item = request.dbsession.query(Modifier).filter(Modifier.id == uuid.UUID(request.matchdict['id'])).first()

View File

@ -0,0 +1,260 @@
import uuid
import transaction
from pyramid.view import view_config
from sqlalchemy import or_
from sqlalchemy.orm import joinedload, Load
from barker.models import ModifierCategory, Product
from barker.models.validation_exception import ValidationError
from barker.views import product
@view_config(
request_method="POST",
route_name="v1_modifier_categories_new",
renderer="json",
permission="Modifiers",
trans=True,
)
def save(request):
json = request.json_body
name = json.get("name", "").strip()
if name == "":
raise ValidationError("Name cannot be blank")
try:
minimum = int(json.get("minimum", 0))
if minimum < 0:
raise ValidationError("Minimum must be an integer >= 0")
except ValueError:
raise ValidationError("Minimum must be an integer >= 0")
try:
maximum = json.get("maximum", None)
if maximum is not None:
maximum = int(maximum)
if maximum < 0:
raise ValidationError(
"Maximum must be an integer and cannot be less than zero"
)
elif maximum == 0:
maximum = None
except ValueError:
raise ValidationError("Maximum must be an integer and cannot be less than zero")
item = ModifierCategory(name, minimum, maximum)
request.dbsession.add(item)
add_products(item, json["menuCategories"], request.dbsession)
transaction.commit()
return modifier_category_info(item.id, request.dbsession)
@view_config(
request_method="PUT",
route_name="v1_modifier_categories_id",
renderer="json",
permission="Modifiers",
trans=True,
)
def update(request):
item = (
request.dbsession.query(ModifierCategory)
.filter(ModifierCategory.id == uuid.UUID(request.matchdict["id"]))
.first()
)
json = request.json_body
item.name = json["name"].strip()
if item.name == "":
raise ValidationError("Name cannot be blank")
try:
item.minimum = int(json.get("minimum", 0))
if item.minimum < 0:
raise ValidationError("Minimum must be an integer >= 0")
except ValueError:
raise ValidationError("Minimum must be an integer >= 0")
try:
item.maximum = json.get("maximum", None)
if item.maximum is not None:
item.maximum = int(item.maximum)
if item.maximum < 0:
raise ValidationError(
"Maximum must be an integer and cannot be less than zero"
)
elif item.maximum == 0:
item.maximum = None
except ValueError:
raise ValidationError("Maximum must be an integer and cannot be less than zero")
add_products(item, json["menuCategories"], request.dbsession)
transaction.commit()
return modifier_category_info(item.id, request.dbsession)
@view_config(
request_method="DELETE",
route_name="v1_modifier_categories_id",
renderer="json",
permission="Modifiers",
trans=True,
)
def delete(request):
item = (
request.dbsession.query(ModifierCategory)
.filter(ModifierCategory.id == uuid.UUID(request.matchdict["id"]))
.first()
)
request.dbsession.delete(item)
transaction.commit()
return {None, request.dbsession}
@view_config(
request_method="GET",
route_name="v1_modifier_categories_id",
renderer="json",
permission="Authenticated",
)
def show_id(request):
id_ = uuid.UUID(request.matchdict["id"])
return modifier_category_info(id_, request.dbsession)
@view_config(
request_method="GET",
route_name="v1_modifier_categories_new",
renderer="json",
permission="Authenticated",
)
def show_blank(request):
return modifier_category_info(None, request.dbsession)
@view_config(
request_method="GET",
route_name="v1_modifier_categories_list",
renderer="json",
permission="Authenticated",
)
def show_list(request):
list_ = (
request.dbsession.query(ModifierCategory)
.order_by(ModifierCategory.sort_order)
.order_by(ModifierCategory.name)
.all()
)
modifier_categories = []
for item in list_:
modifier_categories.append(
{
"id": item.id,
"name": item.name,
"minimum": item.minimum,
"maximum": item.maximum,
"products": [p.name for p in item.products],
}
)
return modifier_categories
@view_config(
request_method="GET",
route_name="v1_modifier_categories_list",
renderer="json",
request_param="pg",
permission="Authenticated",
)
def show_for_pg(request):
menu_category_id = uuid.UUID(request.GET["pg"])
pgm_list = (
request.dbsession.query(MenuCategoryModifier)
.filter(
or_(
MenuCategoryModifier.menu_category == None,
MenuCategoryModifier.menu_category_id == menu_category_id,
)
)
.all()
)
pg_modifiers = []
for item in pgm_list:
pg_modifiers.append(
{
"ModifierID": item.modifier_id,
"Name": item.modifier.name,
"ShowInBill": item.modifier.show_in_bill,
"Price": item.modifier.price,
}
)
return pg_modifiers
def modifier_category_info(item, dbsession):
from barker.models import MenuCategory
menu_categories = (
dbsession.query(MenuCategory)
.options(joinedload(MenuCategory.products, innerjoin=True))
.filter(Product.is_active == True)
.order_by(MenuCategory.sort_order, Product.sort_order, Product.name)
.all()
)
if item is None:
return {
"name": "",
"minimum": 0,
"maximum": 0,
"menuCategories": [
{
"id": mc.id,
"name": mc.name,
"enabled": False,
"products": [
{"id": p.id, "name": p.name, "enabled": False}
for p in mc.products
],
}
for mc in menu_categories
],
}
if type(item) is uuid.UUID:
item = (
dbsession.query(ModifierCategory)
.filter(ModifierCategory.id == item)
.first()
)
return {
"id": item.id,
"name": item.name,
"minimum": item.minimum,
"maximum": item.maximum,
"menuCategories": [
{
"id": mc.id,
"name": mc.name,
"enabled": False,
"products": [
{
"id": p.id,
"name": p.name,
"enabled": True if p in item.products else False,
}
for p in mc.products
],
}
for mc in menu_categories
],
}
def add_products(modifier_category, menu_categories, dbsession):
for mc in menu_categories:
for p in mc['products']:
id_ = uuid.UUID(p["id"])
old = [p for p in modifier_category.products if p.id == id_]
old = None if len(old) == 0 else old[0]
if p["enabled"] and old is None:
product_object = (
dbsession.query(Product).filter(Product.id == id_).one()
)
modifier_category.products.append(product_object)
elif not p["enabled"] and old:
modifier_category.products.remove(old)

View File

@ -13,9 +13,7 @@ def save(request):
request.dbsession.add(item)
add_permissions(item, request.json_body['permissions'], request.dbsession)
transaction.commit()
item = request.dbsession.query(Role).filter(Role.id == item.id).first()
permissions = request.dbsession.query(Permission).order_by(Permission.name).all()
return role_info(item, permissions)
return role_info(item.id, request.dbsession)
@view_config(request_method='PUT', route_name='v1_roles_id', renderer='json', permission='Users', trans=True)
@ -25,9 +23,7 @@ def update(request):
item.name = request.json_body['name']
add_permissions(item, request.json_body['permissions'], request.dbsession)
transaction.commit()
item = request.dbsession.query(Role).filter(Role.id == item.id).first()
permissions = request.dbsession.query(Permission).order_by(Permission.name).all()
return role_info(item, permissions)
return role_info(item.id, request.dbsession)
def add_permissions(role, permissions, dbsession):
@ -58,15 +54,12 @@ def delete(request):
@view_config(request_method='GET', route_name='v1_roles_id', renderer='json', permission='Authenticated')
def show_id(request):
id_ = uuid.UUID(request.matchdict['id'])
item = request.dbsession.query(Role).filter(Role.id == id_).first()
permissions = request.dbsession.query(Permission).order_by(Permission.name).all()
return role_info(item, permissions)
return role_info(id_, request.dbsession)
@view_config(request_method='GET', route_name='v1_roles_new', renderer='json', permission='Authenticated')
def show_blank(request):
permissions = request.dbsession.query(Permission).order_by(Permission.name).all()
return role_info(None, permissions)
return role_info(None, request.dbsession)
@view_config(request_method='GET', route_name='v1_roles_list', renderer='json', permission='Authenticated')
@ -77,16 +70,18 @@ def show_list(request):
]
def role_info(item, permissions):
if item is not None:
def role_info(item, dbsession):
permissions = dbsession.query(Permission).order_by(Permission.name).all()
if item is None:
return {
'name': '',
'permissions': [{'id': p.id, 'name': p.name, 'enabled': False} for p in permissions]
}
if type(item) is uuid.UUID:
item = dbsession.query(Role).filter(Role.id == item).first()
return {
'id': item.id,
'name': item.name,
'permissions': [{'id': p.id, 'name': p.name, 'enabled': True if p in item.permissions else False}
for p in permissions]
}
else:
return {
'name': '',
'permissions': [{'id': p.id, 'name': p.name, 'enabled': False} for p in permissions]
}

View File

@ -13,6 +13,10 @@ const routes: Routes = [
path: 'guest-book',
loadChildren: () => import('./guest-book/guest-book.module').then(mod => mod.GuestBookModule)
},
{
path: 'modifier-categories',
loadChildren: () => import('./modifier-categories/modifier-categories.module').then(mod => mod.ModifierCategoriesModule)
},
{
path: 'printers',
loadChildren: () => import('./printers/printers.module').then(mod => mod.PrintersModule)

View File

@ -1,3 +1,5 @@
import {Product} from "./product";
export class MenuCategory {
id: string;
name: string;
@ -6,4 +8,6 @@ export class MenuCategory {
isActive: boolean;
isFixture: boolean;
sortOrder: number;
products: Product[];
enabled?: boolean;
}

View File

@ -14,4 +14,6 @@ export class Product {
quantity: number;
isActive: boolean;
sortOrder: number;
enabled?: boolean;
}

View File

@ -19,7 +19,7 @@
</div>
</form>
<mat-table [dataSource]="dataSource" aria-label="Elements">
<!-- Id Column -->
<!-- SNo Column -->
<ng-container matColumnDef="sno">
<mat-header-cell *matHeaderCellDef>S. No</mat-header-cell>
<mat-cell *matCellDef="let row">{{row.serial}}</mat-cell>
@ -31,13 +31,13 @@
<mat-cell *matCellDef="let row">{{row.name}}</mat-cell>
</ng-container>
<!-- Name Column -->
<!-- Phone Column -->
<ng-container matColumnDef="phone">
<mat-header-cell *matHeaderCellDef>Phone</mat-header-cell>
<mat-cell *matCellDef="let row">{{row.phone}}</mat-cell>
</ng-container>
<!-- Name Column -->
<!-- Pax Column -->
<ng-container matColumnDef="pax">
<mat-header-cell *matHeaderCellDef>Pax</mat-header-cell>
<mat-cell *matCellDef="let row">{{row.pax}}</mat-cell>

View File

@ -19,6 +19,9 @@
<a mat-raised-button routerLink="/products">
Products
</a>
<a mat-raised-button routerLink="/modifier-categories">
Modifier Categories
</a>
<a mat-raised-button routerLink="/taxes">
Taxes
</a>

View File

@ -0,0 +1,13 @@
import { ModifierCategoriesRoutingModule } from './modifier-categories-routing.module';
describe('ModifierCategoriesRoutingModule', () => {
let rolesRoutingModule: ModifierCategoriesRoutingModule;
beforeEach(() => {
rolesRoutingModule = new ModifierCategoriesRoutingModule();
});
it('should create an instance', () => {
expect(rolesRoutingModule).toBeTruthy();
});
});

View File

@ -0,0 +1,61 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule, Routes } from '@angular/router';
import { ModifierCategoryListResolver } from './modifier-category-list-resolver.service';
import { ModifierCategoryResolver } from './modifier-category-resolver.service';
import { ModifierCategoryListComponent } from './modifier-category-list/modifier-category-list.component';
import { ModifierCategoryDetailComponent } from './modifier-category-detail/modifier-category-detail.component';
import { AuthGuard } from '../auth/auth-guard.service';
const roleRoutes: Routes = [
{
path: '',
component: ModifierCategoryListComponent,
canActivate: [AuthGuard],
data: {
permission: 'Users'
},
resolve: {
list: ModifierCategoryListResolver
}
},
{
path: 'new',
component: ModifierCategoryDetailComponent,
canActivate: [AuthGuard],
data: {
permission: 'Users'
},
resolve: {
item: ModifierCategoryResolver,
}
},
{
path: ':id',
component: ModifierCategoryDetailComponent,
canActivate: [AuthGuard],
data: {
permission: 'Users'
},
resolve: {
item: ModifierCategoryResolver
}
}
];
@NgModule({
imports: [
CommonModule,
RouterModule.forChild(roleRoutes)
],
exports: [
RouterModule
],
providers: [
ModifierCategoryListResolver,
ModifierCategoryResolver
]
})
export class ModifierCategoriesRoutingModule {
}

View File

@ -0,0 +1,13 @@
import { ModifierCategoriesModule } from './modifier-categories.module';
describe('ModifierCategoriesModule', () => {
let rolesModule: ModifierCategoriesModule;
beforeEach(() => {
rolesModule = new ModifierCategoriesModule();
});
it('should create an instance', () => {
expect(rolesModule).toBeTruthy();
});
});

View File

@ -0,0 +1,43 @@
import {NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
import {ModifierCategoryListComponent} from './modifier-category-list/modifier-category-list.component';
import {ModifierCategoryDetailComponent} from './modifier-category-detail/modifier-category-detail.component';
import {ModifierCategoriesRoutingModule} from './modifier-categories-routing.module';
import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { MatDividerModule } from '@angular/material/divider';
import { MatIconModule } from '@angular/material/icon';
import { MatInputModule } from '@angular/material/input';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { MatTableModule } from '@angular/material/table';
import {CdkTableModule} from '@angular/cdk/table';
import {ReactiveFormsModule} from '@angular/forms';
import {SharedModule} from '../shared/shared.module';
import {FlexLayoutModule} from '@angular/flex-layout';
@NgModule({
imports: [
CommonModule,
CdkTableModule,
FlexLayoutModule,
MatButtonModule,
MatCardModule,
MatCheckboxModule,
MatDividerModule,
MatIconModule,
MatInputModule,
MatProgressSpinnerModule,
MatTableModule,
ReactiveFormsModule,
SharedModule,
ModifierCategoriesRoutingModule
],
declarations: [
ModifierCategoryListComponent,
ModifierCategoryDetailComponent
]
})
export class ModifierCategoriesModule {
}

View File

@ -0,0 +1,3 @@
.example-card {
max-width: 400px;
}

View File

@ -0,0 +1,46 @@
<div fxLayout="row" fxFlex="50%" fxLayoutAlign="space-around center" class="example-card">
<mat-card fxFlex>
<mat-card-title-group>
<mat-card-title>ModifierCategory</mat-card-title>
</mat-card-title-group>
<mat-card-content>
<form [formGroup]="form" fxLayout="column">
<div fxLayout="row" fxLayoutAlign="space-around start" fxLayout.lt-md="column" fxLayoutGap="20px"
fxLayoutGap.lt-md="0px">
<mat-form-field fxFlex>
<mat-label>Name</mat-label>
<input matInput #nameElement placeholder="Name" formControlName="name">
</mat-form-field>
</div>
<div fxLayout="row" fxLayoutAlign="space-around start" fxLayout.lt-md="column" fxLayoutGap="20px"
fxLayoutGap.lt-md="0px">
<mat-form-field fxFlex>
<mat-label>Minimum</mat-label>
<input matInput placeholder="Minimum" type="number" formControlName="minimum">
</mat-form-field>
<mat-form-field fxFlex>
<mat-label>Maximum</mat-label>
<input matInput placeholder="Maximum" type="number" formControlName="maximum">
</mat-form-field>
</div>
<mat-divider></mat-divider>
<div formArrayName="menuCategories">
<div *ngFor="let mc of item.menuCategories; index as i" [formGroupName]="i">
<mat-checkbox formControlName="menuCategory" fxFlex>{{mc.name}}</mat-checkbox>
<div formArrayName="products">
<div fxLayout="row" *ngFor="let p of mc.products; index as j" [formGroupName]="j" fxLayout="row"
fxLayoutAlign="space-around start" fxLayout.lt-md="column" fxLayoutGap="20px"
fxLayoutGap.lt-md="0px">
<mat-checkbox formControlName="product" fxFlex>{{p.name}}</mat-checkbox>
</div>
</div>
</div>
</div>
</form>
</mat-card-content>
<mat-card-actions>
<button mat-raised-button color="primary" (click)="save()">Save</button>
<button mat-raised-button color="warn" (click)="confirmDelete()">Delete</button>
</mat-card-actions>
</mat-card>
</div>

View File

@ -0,0 +1,25 @@
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
import {ModifierCategoryDetailComponent} from './modifier-category-detail.component';
describe('ModifierCategoryDetailComponent', () => {
let component: ModifierCategoryDetailComponent;
let fixture: ComponentFixture<ModifierCategoryDetailComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ModifierCategoryDetailComponent]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ModifierCategoryDetailComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,146 @@
import { AfterViewInit, Component, ElementRef, OnInit, ViewChild } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { ModifierCategoryService } from '../modifier-category.service';
import { ModifierCategory } from '../modifier-category';
import { ToasterService } from '../../core/toaster.service';
import { ConfirmDialogComponent } from '../../shared/confirm-dialog/confirm-dialog.component';
import { MatDialog } from '@angular/material/dialog';
import { FormArray, FormBuilder, FormGroup } from '@angular/forms';
import {Product} from "../../core/product";
@Component({
selector: 'app-role-detail',
templateUrl: './modifier-category-detail.component.html',
styleUrls: ['./modifier-category-detail.component.css']
})
export class ModifierCategoryDetailComponent implements OnInit, AfterViewInit {
@ViewChild('nameElement', { static: true }) nameElement: ElementRef;
form: FormGroup;
item: ModifierCategory;
constructor(
private route: ActivatedRoute,
private router: Router,
private fb: FormBuilder,
private toaster: ToasterService,
private dialog: MatDialog,
private ser: ModifierCategoryService
) {
this.createForm();
}
createForm() {
this.form = this.fb.group({
name: '',
minimum: '',
maximum: '',
menuCategories: this.fb.array([])
});
// this.setMenuCategories();
}
setMenuCategories(){
this.form.setControl('menuCategories', this.fb.array(
this.item.menuCategories.map(
x => this.fb.group({
menuCategory: x.enabled,
products: new FormArray(
x.products.map(
y => this.fb.group({
product: y.enabled
})
)
)
})
)
));
}
setProducts(x: any[]){
return ;
}
ngOnInit() {
this.route.data
.subscribe((data: { item: ModifierCategory }) => {
this.showItem(data.item);
});
}
showItem(item: ModifierCategory) {
this.item = item;
console.log(item);
this.form.patchValue({
name: this.item.name || '',
minimum: '' + this.item.minimum,
maximum: '' + this.item.maximum
});
this.setMenuCategories();
// this.form.setControl('menuCategories', this.fb.array(
// this.item.menuCategories.map(
// x => this.fb.group({
// product: x.enabled
// })
// )
// ));
}
ngAfterViewInit() {
setTimeout(() => {
this.nameElement.nativeElement.focus();
}, 0);
}
save() {
this.ser.saveOrUpdate(this.getItem())
.subscribe(
(result) => {
this.toaster.show('Success', '');
this.router.navigateByUrl('/modifier-categories');
},
(error) => {
this.toaster.show('Danger', error.error);
}
);
}
delete() {
this.ser.delete(this.item.id)
.subscribe(
(result) => {
this.toaster.show('Success', '');
this.router.navigateByUrl('/modifier-categories');
},
(error) => {
this.toaster.show('Danger', error.error);
}
);
}
confirmDelete(): void {
const dialogRef = this.dialog.open(ConfirmDialogComponent, {
width: '250px',
data: {title: 'Delete Modifier Category?', content: 'Are you sure? This cannot be undone.'}
});
dialogRef.afterClosed().subscribe((result: boolean) => {
if (result) {
this.delete();
}
});
}
getItem(): ModifierCategory {
const formModel = this.form.value;
this.item.name = formModel.name;
this.item.minimum = +formModel.minimum;
this.item.maximum = +formModel.maximum;
const mc = this.form.get('menuCategories') as FormArray;
this.item.menuCategories.forEach((item, i) => {
item.products.forEach((prod, j) => {
prod.enabled = mc.value[i].products[j].product;
});
});
return this.item;
}
}

View File

@ -0,0 +1,15 @@
import {inject, TestBed} from '@angular/core/testing';
import {ModifierCategoryListResolver} from './modifier-category-list-resolver.service';
describe('ModifierCategoryListResolver', () => {
beforeEach(() => {
TestBed.configureTestingModule({
providers: [ModifierCategoryListResolver]
});
});
it('should be created', inject([ModifierCategoryListResolver], (service: ModifierCategoryListResolver) => {
expect(service).toBeTruthy();
}));
});

View File

@ -0,0 +1,18 @@
import {Injectable} from '@angular/core';
import {ActivatedRouteSnapshot, Resolve, Router, RouterStateSnapshot} from '@angular/router';
import {ModifierCategory} from './modifier-category';
import {Observable} from 'rxjs/internal/Observable';
import {ModifierCategoryService} from './modifier-category.service';
@Injectable({
providedIn: 'root'
})
export class ModifierCategoryListResolver implements Resolve<ModifierCategory[]> {
constructor(private ser: ModifierCategoryService, private router: Router) {
}
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<ModifierCategory[]> {
return this.ser.list();
}
}

View File

@ -0,0 +1,17 @@
import { DataSource } from '@angular/cdk/collections';
import { Observable, of as observableOf } from 'rxjs';
import { ModifierCategory } from '../modifier-category';
export class ModifierCategoryListDatasource extends DataSource<ModifierCategory> {
constructor(public data: ModifierCategory[]) {
super();
}
connect(): Observable<ModifierCategory[]> {
return observableOf(this.data);
}
disconnect() {
}
}

View File

@ -0,0 +1,44 @@
<mat-card>
<mat-card-title-group>
<mat-card-title>Modifier Categories</mat-card-title>
<a mat-button [routerLink]="['/modifier-categories', 'new']">
<mat-icon>add_box</mat-icon>
Add
</a>
</mat-card-title-group>
<mat-card-content>
<mat-table #table [dataSource]="dataSource" aria-label="Elements">
<!-- Name Column -->
<ng-container matColumnDef="name">
<mat-header-cell *matHeaderCellDef>Name</mat-header-cell>
<mat-cell *matCellDef="let row"><a [routerLink]="['/modifier-categories', row.id]">{{row.name}}</a></mat-cell>
</ng-container>
<!-- Minimum Column -->
<ng-container matColumnDef="minimum">
<mat-header-cell *matHeaderCellDef>Minimum</mat-header-cell>
<mat-cell *matCellDef="let row">{{row.minimum}}</mat-cell>
</ng-container>
<!-- Maximum Column -->
<ng-container matColumnDef="maximum">
<mat-header-cell *matHeaderCellDef>Maximum</mat-header-cell>
<mat-cell *matCellDef="let row">{{row.maximum}}</mat-cell>
</ng-container>
<!-- Permissions Column -->
<ng-container matColumnDef="products">
<mat-header-cell *matHeaderCellDef>Products</mat-header-cell>
<mat-cell *matCellDef="let row">
<ul>
<li *ngFor="let product of row.products">{{product}}</li>
</ul>
</mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
<mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
</mat-table>
</mat-card-content>
</mat-card>

View File

@ -0,0 +1,23 @@
import {ComponentFixture, fakeAsync, TestBed} from '@angular/core/testing';
import {ModifierCategoryListComponent} from './modifier-category-list.component';
describe('ModifierCategoryListComponent', () => {
let component: ModifierCategoryListComponent;
let fixture: ComponentFixture<ModifierCategoryListComponent>;
beforeEach(fakeAsync(() => {
TestBed.configureTestingModule({
declarations: [ModifierCategoryListComponent]
})
.compileComponents();
fixture = TestBed.createComponent(ModifierCategoryListComponent);
component = fixture.componentInstance;
fixture.detectChanges();
}));
it('should compile', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,27 @@
import { Component, OnInit } from '@angular/core';
import { ModifierCategoryListDatasource } from './modifier-category-list-datasource';
import { ModifierCategory } from '../modifier-category';
import { ActivatedRoute } from '@angular/router';
@Component({
selector: 'app-modifier-category-list',
templateUrl: './modifier-category-list.component.html',
styleUrls: ['./modifier-category-list.component.css']
})
export class ModifierCategoryListComponent implements OnInit {
dataSource: ModifierCategoryListDatasource;
list: ModifierCategory[];
/** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */
displayedColumns = ['name', 'minimum', 'maximum', 'products'];
constructor(private route: ActivatedRoute) {
}
ngOnInit() {
this.route.data
.subscribe((data: { list: ModifierCategory[] }) => {
this.list = data.list;
});
this.dataSource = new ModifierCategoryListDatasource(this.list);
}
}

View File

@ -0,0 +1,15 @@
import {inject, TestBed} from '@angular/core/testing';
import {ModifierCategoryResolver} from './modifier-category-resolver.service';
describe('ModifierCategoryResolver', () => {
beforeEach(() => {
TestBed.configureTestingModule({
providers: [ModifierCategoryResolver]
});
});
it('should be created', inject([ModifierCategoryResolver], (service: ModifierCategoryResolver) => {
expect(service).toBeTruthy();
}));
});

View File

@ -0,0 +1,19 @@
import {Injectable} from '@angular/core';
import {ActivatedRouteSnapshot, Resolve, Router, RouterStateSnapshot} from '@angular/router';
import {ModifierCategory} from './modifier-category';
import {Observable} from 'rxjs/internal/Observable';
import {ModifierCategoryService} from './modifier-category.service';
@Injectable({
providedIn: 'root'
})
export class ModifierCategoryResolver implements Resolve<ModifierCategory> {
constructor(private ser: ModifierCategoryService, private router: Router) {
}
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<ModifierCategory> {
const id = route.paramMap.get('id');
return this.ser.get(id);
}
}

View File

@ -0,0 +1,15 @@
import {inject, TestBed} from '@angular/core/testing';
import {ModifierCategoryService} from './modifier-category.service';
describe('ModifierCategoryService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
providers: [ModifierCategoryService]
});
});
it('should be created', inject([ModifierCategoryService], (service: ModifierCategoryService) => {
expect(service).toBeTruthy();
}));
});

View File

@ -0,0 +1,73 @@
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 {ModifierCategory} from './modifier-category';
const httpOptions = {
headers: new HttpHeaders({'Content-Type': 'application/json'})
};
const url = '/v1/modifier-categories';
const serviceName = 'ModifierCategoryService';
@Injectable({
providedIn: 'root'
})
export class ModifierCategoryService {
constructor(private http: HttpClient, private log: ErrorLoggerService) {
}
get(id: string): Observable<ModifierCategory> {
const getUrl: string = (id === null) ? `${url}/new` : `${url}/${id}`;
return <Observable<ModifierCategory>>this.http.get<ModifierCategory>(getUrl)
.pipe(
catchError(this.log.handleError(serviceName, `get id=${id}`))
);
}
list(): Observable<ModifierCategory[]> {
const options = {params: new HttpParams().set('l', '')};
return <Observable<ModifierCategory[]>>this.http.get<ModifierCategory[]>(url, options)
.pipe(
catchError(this.log.handleError(serviceName, 'list'))
);
}
listOfNames(): Observable<string[]> {
const options = {params: new HttpParams().set('n', '')};
return <Observable<string[]>>this.http.get<string[]>(url, options)
.pipe(
catchError(this.log.handleError(serviceName, 'list'))
);
}
save(role: ModifierCategory): Observable<ModifierCategory> {
return <Observable<ModifierCategory>>this.http.post<ModifierCategory>(`${url}/new`, role, httpOptions)
.pipe(
catchError(this.log.handleError(serviceName, 'save'))
);
}
update(role: ModifierCategory): Observable<ModifierCategory> {
return <Observable<ModifierCategory>>this.http.put<ModifierCategory>(`${url}/${role.id}`, role, httpOptions)
.pipe(
catchError(this.log.handleError(serviceName, 'update'))
);
}
saveOrUpdate(role: ModifierCategory): Observable<ModifierCategory> {
if (!role.id) {
return this.save(role);
} else {
return this.update(role);
}
}
delete(id: string): Observable<ModifierCategory> {
return <Observable<ModifierCategory>>this.http.delete<ModifierCategory>(`${url}/${id}`, httpOptions)
.pipe(
catchError(this.log.handleError(serviceName, 'delete'))
);
}
}

View File

@ -0,0 +1,9 @@
import {MenuCategory} from "../core/menu-category";
export class ModifierCategory {
id: string;
name: string;
minimum: number;
maximum: number;
menuCategories: MenuCategory[];
}

View File

@ -52,7 +52,6 @@ export class ProductDetailComponent implements OnInit, AfterViewInit {
.subscribe((data: { item: Product, menuCategories: MenuCategory[], saleCategories: SaleCategory[] }) => {
this.menuCategories = data.menuCategories;
this.saleCategories = data.saleCategories;
console.log(this.saleCategories);
this.showItem(data.item);
});
}