Bills initially working just as proof of concept

ng linted
modifier categories list is better at displaying data sanely now
This commit is contained in:
Amritanshu
2019-07-11 12:17:41 +05:30
parent d69ab0063a
commit 4513e8b263
74 changed files with 599 additions and 235 deletions

View File

@ -0,0 +1,12 @@
import { TestBed } from '@angular/core/testing';
import { BillService } from './bill.service';
describe('BillService', () => {
beforeEach(() => TestBed.configureTestingModule({}));
it('should be created', () => {
const service: BillService = TestBed.get(BillService);
expect(service).toBeTruthy();
});
});

View File

@ -0,0 +1,84 @@
import { Injectable } from '@angular/core';
import { Product } from '../core/product';
import { ModifiersComponent } from './modifiers/modifiers.component';
import { MatDialog } from '@angular/material';
import { ModifierCategoryService } from '../modifier-categories/modifier-category.service';
import {Subject} from "rxjs";
import {Modifier} from "../core/modifier";
import {ModifierCategory} from "../core/modifier-category";
import {isNotNullOrUndefined} from "codelyzer/util/isNotNullOrUndefined";
@Injectable()
export class BillService {
public dataObs = new Subject<any[]>();
public data = [];
constructor(
private dialog: MatDialog,
private modifierCategoryService: ModifierCategoryService
) { }
addProduct(product: Product) {
let item = {
isKot: false,
product: product,
productId: product.id,
info: `${product.name} (${product.units}) @ ${product.price}`,
quantity: 1,
modifiers: []
};
this.data.push(item);
this.modifierCategoryService.listIsActiveOfProduct(product.id).subscribe(result => {
if (result.reduce((a: any, c: ModifierCategory) => {return a + c.minimum}, 0)) {
this.showModifier(item);
}
});
this.dataObs.next(this.data);
}
showModifier(item: any): void {
// [routerLink]="['/sales', 'modifiers', item.id]"
const dialogRef = this.dialog.open(ModifiersComponent, {
position: {
top: '10vh'
},
data: {
list: this.modifierCategoryService.listIsActiveOfProduct(item.productId),
selected: item.modifiers
}
});
dialogRef.afterClosed().subscribe(result => {
if (isNotNullOrUndefined(result)) {
item.modifiers = result;
}
});
}
addOne(item: any): void {
item.quantity += 1;
this.dataObs.next(this.data);
}
quantity(item: any): void {
}
subtractOne(item: any): void {
if (item.quantity > 1) {
item.quantity -= 1;
this.dataObs.next(this.data);
} else if (item.quantity === 0) {
this.removeItem(item);
}
}
removeItem(item: any): void {
this.data.splice(this.data.indexOf(item), 1);
this.dataObs.next(this.data);
}
modifier(item: any): void {
this.showModifier(item);
}
}

View File

@ -1,18 +1,19 @@
import {Injectable} from '@angular/core';
import {ActivatedRouteSnapshot, Resolve, Router, RouterStateSnapshot} from '@angular/router';
import {Observable} from 'rxjs/internal/Observable';
import {Table} from "../../core/table";
import {TableService} from "../../tables/table.service";
import {TableService} from '../../tables/table.service';
@Injectable({
providedIn: 'root'
})
export class BillResolver implements Resolve<Table[]> {
export class BillResolver implements Resolve<any[]> {
constructor(private ser: TableService, private router: Router) {
}
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Table[]> {
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<any[]> {
const tableId = route.queryParamMap.get('table');
const guestId = route.queryParamMap.get('guest');
return this.ser.list();
}
}

View File

@ -0,0 +1,46 @@
import {User} from '../../core/user';
import {Table} from '../../core/table';
import {GuestBook} from '../../guest-book/guest-book';
import {Product} from '../../core/product';
import {Tax} from '../../core/tax';
import {Modifier} from '../../core/modifier';
export class Inventory {
id: string;
sortOrder: number;
product: Product;
quantity: number;
price: number;
isHappyHour: boolean;
taxRate: number;
tax: Tax;
discount: number;
modifiers: Modifier;
}
export class Kot {
id: string;
serial: number;
date: string;
user: User;
inventories: Inventory[];
}
export class Bill {
id: string;
date: string;
user: User;
creationDate: string;
lastEditDate: string;
billId: string;
table: Table;
guest: GuestBook;
settlements: any[];
void: boolean;
voidReason: string;
printed: boolean;
voucherType: string;
serial: number;
kots: Kot[];
reprints: any[];
}

View File

@ -0,0 +1,21 @@
import { DataSource } from '@angular/cdk/collections';
import { Observable } from 'rxjs';
export class BillsDataSource extends DataSource<any> {
constructor(private data: Observable<any[]>
) {
super();
}
connect(): Observable<any[]> {
return this.data;
}
/**
* Called when the table is being destroyed. Use this function, to clean up
* any open connections or free any held resources that were set up during connect.
*/
disconnect() {
}
}

View File

@ -2,12 +2,42 @@
<mat-card-title-group>
<mat-card-title>Bill</mat-card-title>
</mat-card-title-group>
<mat-card-content fxLayout="row wrap" fxLayoutGap="grid 20px">
<mat-card-content>
<mat-table #table [dataSource]="dataSource" aria-label="Elements">
<!-- Info Column -->
<ng-container matColumnDef="info">
<mat-cell *matCellDef="let row" [class.kot]="row.isKot">{{row.info}}</mat-cell>
<mat-cell *matCellDef="let row" fxLayout="column" fxLayoutAlign="space-around start" [class.kot]="row.isKot">
<span>
{{row.info}}
</span>
<ul>
<li *ngFor="let m of row.modifiers">{{m.name}}</li>
</ul>
</mat-cell>
</ng-container>
<!-- Quantity Column -->
<ng-container matColumnDef="quantity">
<mat-header-cell *matHeaderCellDef>Quantity</mat-header-cell>
<mat-cell *matCellDef="let row">
<button mat-icon-button (click)="subtractOne(row)">
<mat-icon class="del">indeterminate_check_box</mat-icon>
</button>
<button mat-icon-button (click)="quantity(row)">
{{row.quantity}}
</button>
<button mat-icon-button (click)="addOne(row)">
<mat-icon class="del">control_point</mat-icon>
</button>
<button mat-icon-button (click)="removeItem(row)">
<mat-icon class="del">cancel</mat-icon>
</button>
<button mat-icon-button (click)="modifier(row)">
<mat-icon class="del">assignment</mat-icon>
</button>
</mat-cell>
</ng-container>
<mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
</mat-table>
</mat-card-content>

View File

@ -1,6 +1,9 @@
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from "@angular/router";
import { Table } from "../../core/table";
import { ActivatedRoute } from '@angular/router';
import {Bill, Inventory, Kot} from './bill';
import {ModifierCategoryListDatasource} from '../../modifier-categories/modifier-category-list/modifier-category-list-datasource';
import {BillsDataSource} from './bills-datasource';
import {BillService} from "../bill.service";
@Component({
selector: 'app-bills',
@ -8,15 +11,50 @@ import { Table } from "../../core/table";
styleUrls: ['./bills.component.css']
})
export class BillsComponent implements OnInit {
list: Table[];
dataSource: BillsDataSource;
item: Bill;
view: any[];
/** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */
displayedColumns: string[] = ['info', 'quantity'];
constructor(private route: ActivatedRoute) {
constructor(
private route: ActivatedRoute,
private bs: BillService
) {
}
ngOnInit() {
this.route.data
.subscribe((data: { list: Table[] }) => {
this.list = data.list;
.subscribe((data: { item: Bill }) => {
this.updateView(data.item);
});
this.dataSource = new BillsDataSource(this.bs.dataObs);
}
updateView(item) {
this.item = item;
// this.view = item.kots.reduce((p: Kot, c:Kot) => {
//
// }, [])
}
addOne(item: any): void {
this.bs.addOne(item);
}
quantity(item: any): void {
this.bs.quantity(item);
}
subtractOne(item: any): void {
this.bs.subtractOne(item);
}
removeItem(item: any): void {
this.bs.removeItem(item);
}
modifier(item: any): void {
this.bs.modifier(item);
}
}

View File

@ -0,0 +1,5 @@
.square-button {
min-width: 150px;
max-width: 150px;
min-height: 150px;
}

View File

@ -0,0 +1,5 @@
<button mat-raised-button class="square-button" [routerLink]="['menu-categories']">Add Product</button>
<button mat-raised-button class="square-button" [routerLink]="['menu-categories']">Print KOT</button>
<button mat-raised-button class="square-button" [routerLink]="['menu-categories']">Print Bill</button>
<button mat-raised-button class="square-button" [routerLink]="['menu-categories']">Back to Tables</button>
<button mat-raised-button class="square-button" [routerLink]="['menu-categories']">Receive Payment</button>

View File

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

View File

@ -0,0 +1,25 @@
import {Component, OnInit} from '@angular/core';
import {Subject} from 'rxjs';
import {AuthService} from '../../auth/auth.service';
@Component({
selector: 'app-sales-home',
templateUrl: './sales-home.component.html',
styleUrls: ['./sales-home.component.css']
})
export class SalesHomeComponent implements OnInit {
public nameObject = new Subject<string>();
constructor(private auth: AuthService) {
}
ngOnInit() {
this.auth.userObservable.subscribe((user) => {
if (user.isAuthenticated) {
this.nameObject.next(user.name);
} else {
this.nameObject.next(null);
}
});
}
}

View File

@ -2,7 +2,7 @@ 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/menu-category.service";
import { MenuCategoryService } from '../../menu-category/menu-category.service';
@Injectable({
providedIn: 'root'

View File

@ -1,6 +1,7 @@
<mat-card>
<mat-card-content fxLayout="row wrap" fxLayoutGap="grid 20px">
<button mat-raised-button class="square-button"
*ngFor="let item of list" [routerLink]="['/sales', 'products', item.id]">{{item.name}}</button>
*ngFor="let item of list" [routerLink]="['../products', item.id]">{{item.name}}</button>
<button mat-raised-button class="square-button" color="warn" (click)="goBack()">Back</button>
</mat-card-content>
</mat-card>

View File

@ -1,6 +1,7 @@
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from "@angular/router";
import { MenuCategory } from "../../core/menu-category";
import { Location } from '@angular/common';
import { ActivatedRoute } from '@angular/router';
import { MenuCategory } from '../../core/menu-category';
@Component({
selector: 'app-menu-category',
@ -10,7 +11,10 @@ import { MenuCategory } from "../../core/menu-category";
export class MenuCategoriesComponent implements OnInit {
list: MenuCategory[];
constructor(private route: ActivatedRoute) {
constructor(
private route: ActivatedRoute,
private location: Location,
) {
}
ngOnInit() {
@ -20,4 +24,8 @@ export class MenuCategoriesComponent implements OnInit {
});
}
goBack(): void {
this.location.back();
}
}

View File

@ -8,10 +8,12 @@
</mat-chip-list>
</ng-template>
<mat-button-toggle-group multiple>
<mat-button-toggle mat-raised-button class="square-button" *ngFor="let m of item.modifiers" (click)="select(m)">{{m.name}}</mat-button-toggle>
<mat-button-toggle mat-raised-button class="square-button" *ngFor="let m of item.modifiers" (click)="select(m)" [checked]="selectedIds.indexOf(m.id) !== -1">
{{m.name}}
</mat-button-toggle>
</mat-button-toggle-group>
</mat-tab>
</mat-tab-group>
<mat-dialog-actions align="end">
<button mat-button mat-dialog-close>Done</button>
<button mat-button [mat-dialog-close]="selected">Done</button>
</mat-dialog-actions>

View File

@ -1,8 +1,8 @@
import { Component, Inject } from '@angular/core';
import { ModifierCategory } from "../../core/modifier-category";
import { Modifier } from "../../core/modifier";
import { MAT_DIALOG_DATA } from "@angular/material";
import {Observable} from "rxjs";
import { ModifierCategory } from '../../core/modifier-category';
import { Modifier } from '../../core/modifier';
import { MAT_DIALOG_DATA } from '@angular/material';
import {Observable} from 'rxjs';
@Component({
selector: 'app-modifiers',
@ -11,16 +11,24 @@ import {Observable} from "rxjs";
})
export class ModifiersComponent {
list: ModifierCategory[];
selected: Modifier[];
selectedIds: string[];
constructor(@Inject(MAT_DIALOG_DATA) public data: Observable<ModifierCategory[]>) {
this.data.subscribe((list: ModifierCategory[]) => {
constructor(@Inject(MAT_DIALOG_DATA) public data: { list: Observable<ModifierCategory[]>, selected: Modifier[] }) {
this.data.list.subscribe((list: ModifierCategory[]) => {
this.list = list;
console.log(this.list);
});
console.log(this.list);
this.selected = data.selected;
this.selectedIds = this.selected.map(e => e.id);
}
select(m: Modifier) {
console.log(m);
let index = this.selectedIds.indexOf(m.id);
if (index === -1) {
this.selected.push(m);
} else {
this.selected.splice(index, 1);
}
this.selectedIds = this.selected.map(e => e.id);
}
}

View File

@ -1,8 +1,8 @@
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, Resolve, Router, RouterStateSnapshot } from "@angular/router";
import { Observable } from "rxjs";
import { Product } from "../../core/product";
import { ProductService } from "../../product/product.service";
import { ActivatedRouteSnapshot, Resolve, Router, RouterStateSnapshot } from '@angular/router';
import { Observable } from 'rxjs';
import { Product } from '../../core/product';
import { ProductService } from '../../product/product.service';
@Injectable({
providedIn: 'root'

View File

@ -1,6 +1,7 @@
<mat-card>
<mat-card-content fxLayout="row wrap" fxLayoutGap="grid 20px">
<button mat-raised-button class="square-button"
*ngFor="let item of list" (click)="showModifier(item)">{{item.name}}</button>
*ngFor="let item of list" (click)="addProduct(item)">{{item.name}}</button>
<button mat-raised-button class="square-button" color="warn" (click)="goBack()">Back</button>
</mat-card-content>
</mat-card>

View File

@ -1,9 +1,8 @@
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from "@angular/router";
import { MatDialog } from "@angular/material";
import { Product } from "../../core/product";
import {ModifiersComponent} from "../modifiers/modifiers.component";
import {ModifierCategoryService} from "../../modifier-categories/modifier-category.service";
import { Location } from '@angular/common';
import { ActivatedRoute } from '@angular/router';
import { Product } from '../../core/product';
import { BillService } from '../bill.service';
@Component({
selector: 'app-products',
@ -13,7 +12,11 @@ import {ModifierCategoryService} from "../../modifier-categories/modifier-catego
export class ProductsComponent implements OnInit {
list: Product[];
constructor(private route: ActivatedRoute, private dialog: MatDialog, private modifierCategoryService: ModifierCategoryService) {
constructor(
private route: ActivatedRoute,
private location: Location,
private bs: BillService
) {
}
ngOnInit() {
@ -23,17 +26,12 @@ export class ProductsComponent implements OnInit {
});
}
showModifier(product: Product): void {
// [routerLink]="['/sales', 'modifiers', item.id]"
let dialogRef = this.dialog.open(ModifiersComponent, {
position: {
top: '10vh'
},
data: this.modifierCategoryService.listIsActiveOfProduct(product.id)
});
dialogRef.afterClosed().subscribe(result => {
console.log('The dialog was closed');
});
addProduct(product: Product): void {
this.bs.addProduct(product);
}
goBack(): void {
this.location.back();
}
}

View File

@ -1,8 +1,8 @@
import {Injectable} from '@angular/core';
import {ActivatedRouteSnapshot, Resolve, Router, RouterStateSnapshot} from '@angular/router';
import {Observable} from 'rxjs/internal/Observable';
import {Table} from "../../core/table";
import {TableService} from "../../tables/table.service";
import {Table} from '../../core/table';
import {TableService} from '../../tables/table.service';
@Injectable({
providedIn: 'root'

View File

@ -3,8 +3,7 @@
<mat-card-title>Running Tables</mat-card-title>
</mat-card-title-group>
<mat-card-content fxLayout="row wrap" fxLayoutGap="grid 20px">
<button mat-raised-button class="square-button" [routerLink]="['/sales', 'menu-categories']">Menu Categories</button>
<button mat-raised-button class="square-button"
*ngFor="let table of list" [routerLink]="['/bills', 'new']" [queryParams]="{table: table.id}" queryParamsHandling="merge">{{table.name}}</button>
*ngFor="let table of list" [routerLink]="['../bill']" [queryParams]="{table: table.id}" queryParamsHandling="merge">{{table.name}}</button>
</mat-card-content>
</mat-card>

View File

@ -1,6 +1,6 @@
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from "@angular/router";
import { Table } from "../../core/table";
import { ActivatedRoute } from '@angular/router';
import { Table } from '../../core/table';
@Component({
selector: 'app-running-tables',

View File

@ -1,14 +1,15 @@
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { AuthGuard } from "../auth/auth-guard.service";
import { RunningTablesResolver } from "./running-tables/running-tables-resolver.service";
import { RunningTablesComponent } from "./running-tables/running-tables.component";
import { MenuCategoriesComponent } from "./menu-categories/menu-categories.component";
import { MenuCategoriesResolver } from "./menu-categories/menu-categories-resolver.service";
import { ProductsComponent } from "./products/products.component";
import { ProductsResolver } from "./products/products-resolver.service";
import { BillsComponent } from "./bills/bills.component";
import { BillResolver } from "./bills/bill-resolver.service";
import { AuthGuard } from '../auth/auth-guard.service';
import { RunningTablesResolver } from './running-tables/running-tables-resolver.service';
import { RunningTablesComponent } from './running-tables/running-tables.component';
import { MenuCategoriesComponent } from './menu-categories/menu-categories.component';
import { MenuCategoriesResolver } from './menu-categories/menu-categories-resolver.service';
import { ProductsComponent } from './products/products.component';
import { ProductsResolver } from './products/products-resolver.service';
import { BillsComponent } from './bills/bills.component';
import { BillResolver } from './bills/bill-resolver.service';
import { SalesHomeComponent } from './home/sales-home.component';
const routes: Routes = [
{
@ -45,6 +46,17 @@ const routes: Routes = [
list: BillResolver
},
children: [
{
path: '',
component: SalesHomeComponent,
canActivate: [AuthGuard],
data: {
permission: 'Guest Book'
},
resolve: {
list: MenuCategoriesResolver
}
},
{
path: 'menu-categories',
component: MenuCategoriesComponent,

View File

@ -6,17 +6,32 @@ import { MatButtonToggleModule } from '@angular/material/button-toggle';
import { MatCardModule } from '@angular/material/card';
import { MatChipsModule } from '@angular/material/chips';
import { MatDialogModule } from '@angular/material/dialog';
import { MatIconModule } from '@angular/material/icon';
import { MatTableModule } from '@angular/material/table';
import { MatTabsModule } from '@angular/material/tabs';
import { FlexLayoutModule } from '@angular/flex-layout';
import { SalesRoutingModule } from './sales-routing.module';
import { RunningTablesComponent } from "./running-tables/running-tables.component";
import { RunningTablesComponent } from './running-tables/running-tables.component';
import { MenuCategoriesComponent } from './menu-categories/menu-categories.component';
import { ProductsComponent } from './products/products.component';
import { ModifiersComponent } from './modifiers/modifiers.component';
import { BillsComponent } from './bills/bills.component';
import { SalesHomeComponent } from './home/sales-home.component';
import { BillService } from './bill.service';
@NgModule({
declarations: [RunningTablesComponent, MenuCategoriesComponent, ProductsComponent, ModifiersComponent],
providers: [
BillService
],
declarations: [
RunningTablesComponent,
MenuCategoriesComponent,
ProductsComponent,
ModifiersComponent,
BillsComponent,
SalesHomeComponent
],
imports: [
CommonModule,
FlexLayoutModule,
@ -26,6 +41,8 @@ import { ModifiersComponent } from './modifiers/modifiers.component';
MatCardModule,
MatChipsModule,
MatDialogModule,
MatIconModule,
MatTableModule,
MatTabsModule,
SalesRoutingModule
],