No automatic signout
Voucher basic working running tables shifted to cards from buttons, this gives us immense styling oportunities
This commit is contained in:
@ -6,4 +6,5 @@ export class Table {
|
||||
seats: number;
|
||||
section: Section;
|
||||
isActive: boolean;
|
||||
voucherId?: string;
|
||||
}
|
||||
|
||||
@ -1,37 +1,54 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { MatDialog } from '@angular/material';
|
||||
import { BehaviorSubject } from "rxjs";
|
||||
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";
|
||||
import { ModifierCategory } from "../core/modifier-category";
|
||||
|
||||
@Injectable()
|
||||
export class BillService {
|
||||
public dataObs = new Subject<any[]>();
|
||||
public data = [];
|
||||
constructor(
|
||||
private dialog: MatDialog,
|
||||
private modifierCategoryService: ModifierCategoryService
|
||||
) { }
|
||||
public dataObs;
|
||||
public data;
|
||||
|
||||
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);
|
||||
}
|
||||
});
|
||||
constructor(
|
||||
private dialog: MatDialog,
|
||||
private modifierCategoryService: ModifierCategoryService
|
||||
) {
|
||||
this.data = [];
|
||||
this.dataObs = new BehaviorSubject<any[]>(this.data);
|
||||
}
|
||||
|
||||
loadData(d: any): void {
|
||||
console.log("data loaded");
|
||||
this.data = d;
|
||||
this.data.push({isKot: true, newKot: true, info: "== New Kot =="})
|
||||
this.dataObs.next(this.data);
|
||||
|
||||
}
|
||||
addProduct(product: Product): void {
|
||||
let old = this.data.find(x=> !x.isKot && x.productId == product.id && x.isHappyHour == product.hasHappyHour);
|
||||
if (old !== undefined) {
|
||||
old.quantity += 1;
|
||||
} else {
|
||||
let item = {
|
||||
isKot: false,
|
||||
product: product,
|
||||
productId: product.id,
|
||||
isHappyHour: product.hasHappyHour,
|
||||
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);
|
||||
}
|
||||
|
||||
@ -48,7 +65,7 @@ export class BillService {
|
||||
});
|
||||
|
||||
dialogRef.afterClosed().subscribe(result => {
|
||||
if (isNotNullOrUndefined(result)) {
|
||||
if (result !== undefined) {
|
||||
item.modifiers = result;
|
||||
}
|
||||
});
|
||||
|
||||
@ -1,19 +1,21 @@
|
||||
import {Injectable} from '@angular/core';
|
||||
import {ActivatedRouteSnapshot, Resolve, Router, RouterStateSnapshot} from '@angular/router';
|
||||
import {Observable} from 'rxjs/internal/Observable';
|
||||
import {TableService} from '../../tables/table.service';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { ActivatedRouteSnapshot, Resolve, Router, RouterStateSnapshot } from '@angular/router';
|
||||
import { Observable } from 'rxjs/internal/Observable';
|
||||
import { VoucherService } from "./voucher.service";
|
||||
import { Bill } from "./bill";
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class BillResolver implements Resolve<any[]> {
|
||||
export class BillResolver implements Resolve<Bill> {
|
||||
|
||||
constructor(private ser: TableService, private router: Router) {
|
||||
constructor(private ser: VoucherService, private router: Router) {
|
||||
}
|
||||
|
||||
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<any[]> {
|
||||
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Bill> {
|
||||
const tableId = route.queryParamMap.get('table');
|
||||
const guestId = route.queryParamMap.get('guest');
|
||||
return this.ser.list();
|
||||
const voucherId = route.queryParamMap.get('voucher');
|
||||
return this.ser.getFromTable(tableId, voucherId, guestId);
|
||||
}
|
||||
}
|
||||
|
||||
@ -15,7 +15,7 @@ export class Inventory {
|
||||
taxRate: number;
|
||||
tax: Tax;
|
||||
discount: number;
|
||||
modifiers: Modifier;
|
||||
modifiers: Modifier[];
|
||||
}
|
||||
|
||||
export class Kot {
|
||||
|
||||
@ -1,6 +1,11 @@
|
||||
.kot {
|
||||
background-color: red;
|
||||
font-weight: bold;
|
||||
background-color: hotpink;
|
||||
}
|
||||
.printed {
|
||||
background-color: lightpink;
|
||||
}
|
||||
.new-kot {
|
||||
background-color: lightblue;
|
||||
}
|
||||
|
||||
.square-button {
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
<mat-table #table [dataSource]="dataSource" aria-label="Elements">
|
||||
<!-- Info Column -->
|
||||
<ng-container matColumnDef="info">
|
||||
<mat-cell *matCellDef="let row" fxLayout="column" fxLayoutAlign="space-around start" [class.kot]="row.isKot">
|
||||
<mat-cell *matCellDef="let row" fxLayout="column" fxLayoutAlign="start space-between end">
|
||||
<span>
|
||||
{{row.info}}
|
||||
</span>
|
||||
@ -19,26 +19,27 @@
|
||||
<ng-container matColumnDef="quantity">
|
||||
<mat-header-cell *matHeaderCellDef>Quantity</mat-header-cell>
|
||||
<mat-cell *matCellDef="let row">
|
||||
<button mat-icon-button (click)="subtractOne(row)">
|
||||
<button mat-icon-button (click)="subtractOne(row)" [disabled]="row.isPrinted" *ngIf="!row.isKot">
|
||||
<mat-icon class="del">indeterminate_check_box</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button (click)="quantity(row)">
|
||||
<button mat-icon-button (click)="quantity(row)" [disabled]="row.isPrinted" *ngIf="!row.isKot">
|
||||
{{row.quantity}}
|
||||
</button>
|
||||
<button mat-icon-button (click)="addOne(row)">
|
||||
<button mat-icon-button (click)="addOne(row)" [disabled]="row.isPrinted" *ngIf="!row.isKot">
|
||||
<mat-icon class="del">control_point</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button (click)="removeItem(row)">
|
||||
<button mat-icon-button (click)="removeItem(row)" [disabled]="row.isPrinted" *ngIf="!row.isKot">
|
||||
<mat-icon class="del">cancel</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button (click)="modifier(row)">
|
||||
<button mat-icon-button (click)="modifier(row)" [disabled]="row.isPrinted" *ngIf="!row.isKot">
|
||||
<mat-icon class="del">assignment</mat-icon>
|
||||
</button>
|
||||
</mat-cell>
|
||||
</ng-container>
|
||||
|
||||
|
||||
<mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
|
||||
<mat-row *matRowDef="let row; columns: displayedColumns;" [class.kot]="row.isKot" [class.new-kot]="row.newKot"
|
||||
[class.printed]="row.isPrinted"></mat-row>
|
||||
</mat-table>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
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";
|
||||
|
||||
@ -13,7 +12,6 @@ import {BillService} from "../bill.service";
|
||||
export class BillsComponent implements OnInit {
|
||||
dataSource: BillsDataSource;
|
||||
item: Bill;
|
||||
view: any[];
|
||||
/** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */
|
||||
displayedColumns: string[] = ['info', 'quantity'];
|
||||
|
||||
@ -24,18 +22,35 @@ export class BillsComponent implements OnInit {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
console.log("ds set")
|
||||
this.dataSource = new BillsDataSource(this.bs.dataObs);
|
||||
this.route.data
|
||||
.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) => {
|
||||
//
|
||||
// }, [])
|
||||
let view = item.kots.map(k => {
|
||||
return [{
|
||||
isKot: true,
|
||||
}, ...k.inventories.map(i => {
|
||||
return {
|
||||
id: i.id,
|
||||
isKot: false,
|
||||
product: i.product,
|
||||
productId: i.product.id,
|
||||
isHappyHour: i.isHappyHour,
|
||||
isPrinted: true,
|
||||
info: `${i.product.name} (${i.product.units}) @ ${i.price}`,
|
||||
quantity: 1,
|
||||
modifiers: i.modifiers
|
||||
}
|
||||
})]
|
||||
});
|
||||
view = view.reduce((a, c) => {return a.concat(c)} , []);
|
||||
this.bs.loadData(view);
|
||||
}
|
||||
|
||||
addOne(item: any): void {
|
||||
|
||||
70
bookie/src/app/sales/bills/voucher.service.ts
Normal file
70
bookie/src/app/sales/bills/voucher.service.ts
Normal file
@ -0,0 +1,70 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Observable } from 'rxjs/internal/Observable';
|
||||
import { catchError } from 'rxjs/operators';
|
||||
import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http';
|
||||
import { ErrorLoggerService } from '../../core/error-logger.service';
|
||||
import {Bill} from "./bill";
|
||||
|
||||
const httpOptions = {
|
||||
headers: new HttpHeaders({'Content-Type': 'application/json'})
|
||||
};
|
||||
|
||||
const url = '/v1/vouchers';
|
||||
const serviceName = 'VoucherService';
|
||||
|
||||
@Injectable({providedIn: 'root'})
|
||||
export class VoucherService {
|
||||
|
||||
constructor(private http: HttpClient, private log: ErrorLoggerService) {
|
||||
}
|
||||
|
||||
get(id: string): Observable<Bill> {
|
||||
return <Observable<Bill>>this.http.get<Bill>(`${url}/${id}`)
|
||||
.pipe(
|
||||
catchError(this.log.handleError(serviceName, `get id=${id}`))
|
||||
);
|
||||
}
|
||||
|
||||
getFromTable(tableId: string, voucherId: string, guestId: string): Observable<Bill> {
|
||||
let params = new HttpParams();
|
||||
if (tableId !== null) {
|
||||
params = params.set('t', tableId);
|
||||
}
|
||||
if (voucherId !== null) {
|
||||
params = params.set('v', voucherId);
|
||||
}
|
||||
if (guestId !== null) {
|
||||
params = params.set('g', guestId);
|
||||
}
|
||||
|
||||
return <Observable<Bill>>this.http.get<Bill>(`${url}/new`, {params: params})
|
||||
.pipe(
|
||||
catchError(this.log.handleError(
|
||||
serviceName,
|
||||
`getFromTable tableId=${tableId} voucherId=${voucherId} guestId=${guestId}`
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
save(voucher: Bill): Observable<Bill> {
|
||||
return <Observable<Bill>>this.http.post<Bill>(`${url}/new`, voucher, httpOptions)
|
||||
.pipe(
|
||||
catchError(this.log.handleError(serviceName, 'save'))
|
||||
);
|
||||
}
|
||||
|
||||
update(voucher: Bill): Observable<Bill> {
|
||||
return <Observable<Bill>>this.http.put<Bill>(`${url}/${voucher.id}`, voucher, httpOptions)
|
||||
.pipe(
|
||||
catchError(this.log.handleError(serviceName, 'update'))
|
||||
);
|
||||
}
|
||||
|
||||
saveOrUpdate(voucher: Bill): Observable<Bill> {
|
||||
if (!voucher.id) {
|
||||
return this.save(voucher);
|
||||
} else {
|
||||
return this.update(voucher);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -13,6 +13,6 @@ export class RunningTablesResolver implements Resolve<Table[]> {
|
||||
}
|
||||
|
||||
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Table[]> {
|
||||
return this.ser.list();
|
||||
return this.ser.running();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,23 @@
|
||||
.running {
|
||||
background-color: green;
|
||||
}
|
||||
|
||||
.printed {
|
||||
background-color: firebrick;
|
||||
}
|
||||
|
||||
.square-button {
|
||||
min-width: 150px;
|
||||
max-width: 150px;
|
||||
min-height: 150px;
|
||||
max-height: 150px;
|
||||
margin: 20px;
|
||||
}
|
||||
.item-name {
|
||||
text-align: center;
|
||||
padding: 0.5rem;
|
||||
}
|
||||
|
||||
.center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@ -3,7 +3,13 @@
|
||||
<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"
|
||||
*ngFor="let table of list" [routerLink]="['../bill']" [queryParams]="{table: table.id}" queryParamsHandling="merge">{{table.name}}</button>
|
||||
<mat-card fxLayout="column" class="square-button"
|
||||
*ngFor="let table of list" (click)="navigateToBill(table)"
|
||||
[class.running]="table.status === 'running'" [class.printed]="table.status === 'printed'">
|
||||
<h3 class="item-name">{{table.name}}</h3>
|
||||
<span class="center">{{table.pax || 0}} / {{table.seats}} Seats</span>
|
||||
<span class="center" *ngIf="table.date">{{table.date}}</span>
|
||||
<span class="center" *ngIf="table.amount">{{table.amount}}</span>
|
||||
</mat-card>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { ActivatedRoute, NavigationExtras, Router } from '@angular/router';
|
||||
import { Table } from '../../core/table';
|
||||
|
||||
@Component({
|
||||
@ -10,7 +10,7 @@ import { Table } from '../../core/table';
|
||||
export class RunningTablesComponent implements OnInit {
|
||||
list: Table[];
|
||||
|
||||
constructor(private route: ActivatedRoute) {
|
||||
constructor(private router: Router, private route: ActivatedRoute) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
@ -19,4 +19,17 @@ export class RunningTablesComponent implements OnInit {
|
||||
this.list = data.list;
|
||||
});
|
||||
}
|
||||
|
||||
navigateToBill(table: Table): void {
|
||||
let qp = {table: table.id};
|
||||
if (table.voucherId) {
|
||||
qp["voucher"] = table.voucherId;
|
||||
}
|
||||
let navigationExtras: NavigationExtras = {
|
||||
queryParams: qp,
|
||||
queryParamsHandling: 'merge',
|
||||
preserveFragment: true
|
||||
};
|
||||
this.router.navigate(['/sales', 'bill'], navigationExtras);
|
||||
}
|
||||
}
|
||||
|
||||
@ -43,7 +43,7 @@ const routes: Routes = [
|
||||
permission: 'Guest Book'
|
||||
},
|
||||
resolve: {
|
||||
list: BillResolver
|
||||
item: BillResolver
|
||||
},
|
||||
children: [
|
||||
{
|
||||
|
||||
@ -34,6 +34,14 @@ export class TableService {
|
||||
);
|
||||
}
|
||||
|
||||
running(): Observable<Table[]> {
|
||||
const options = {params: new HttpParams().set('a', 'true')};
|
||||
return <Observable<Table[]>>this.http.get<Table[]>(url, options)
|
||||
.pipe(
|
||||
catchError(this.log.handleError(serviceName, 'running'))
|
||||
);
|
||||
}
|
||||
|
||||
save(tables: Table): Observable<Table> {
|
||||
return <Observable<Table>>this.http.post<Table>(`${url}/new`, tables, httpOptions)
|
||||
.pipe(
|
||||
|
||||
Reference in New Issue
Block a user