Tax is added directly to product for sale
Auth guard and auth service simplified and fixed so that user is updated upon login Home component changed to use square buttons Fixed showing the totals in the bill ng linted the project
This commit is contained in:
@ -1,6 +1,5 @@
|
|||||||
import uuid
|
import uuid
|
||||||
from decimal import Decimal, InvalidOperation
|
from decimal import Decimal, InvalidOperation
|
||||||
from functools import reduce
|
|
||||||
|
|
||||||
import transaction
|
import transaction
|
||||||
from pyramid.response import Response
|
from pyramid.response import Response
|
||||||
@ -193,15 +192,49 @@ def show_list_sale(request):
|
|||||||
)
|
)
|
||||||
products = []
|
products = []
|
||||||
for item in list_:
|
for item in list_:
|
||||||
|
products.append(
|
||||||
|
{
|
||||||
|
"id": item.id,
|
||||||
|
"name": item.name,
|
||||||
|
"units": item.units,
|
||||||
|
"saleCategory": {
|
||||||
|
"id": item.sale_category_id,
|
||||||
|
"name": item.sale_category.name,
|
||||||
|
},
|
||||||
|
"tax": {
|
||||||
|
"id": item.sale_category.tax_id,
|
||||||
|
"name": item.sale_category.tax.name,
|
||||||
|
"rate": item.sale_category.tax.rate,
|
||||||
|
},
|
||||||
|
"price": item.price,
|
||||||
|
"hasHappyHour": False,
|
||||||
|
"isNotAvailable": item.is_not_available,
|
||||||
|
"isActive": item.is_active,
|
||||||
|
"sortOrder": item.sort_order,
|
||||||
|
}
|
||||||
|
)
|
||||||
if item.has_happy_hour:
|
if item.has_happy_hour:
|
||||||
p = product_info(item, request.dbsession)
|
products.append(
|
||||||
p["hasHappyHour"] = False
|
{
|
||||||
products.append(p)
|
"id": item.id,
|
||||||
i = product_info(item, request.dbsession)
|
"name": "H H " + item.name,
|
||||||
i["name"] = "H + H " + i["name"]
|
"units": item.units,
|
||||||
products.append(i)
|
"saleCategory": {
|
||||||
else:
|
"id": item.sale_category_id,
|
||||||
products.append(product_info(item, request.dbsession))
|
"name": item.sale_category.name,
|
||||||
|
},
|
||||||
|
"tax": {
|
||||||
|
"id": item.sale_category.tax_id,
|
||||||
|
"name": item.sale_category.tax.name,
|
||||||
|
"rate": item.sale_category.tax.rate,
|
||||||
|
},
|
||||||
|
"price": item.price,
|
||||||
|
"hasHappyHour": True,
|
||||||
|
"isNotAvailable": item.is_not_available,
|
||||||
|
"isActive": item.is_active,
|
||||||
|
"sortOrder": item.sort_order,
|
||||||
|
}
|
||||||
|
)
|
||||||
return products
|
return products
|
||||||
|
|
||||||
|
|
||||||
@ -251,7 +284,10 @@ def product_info(item, dbsession):
|
|||||||
"saleCategory": {
|
"saleCategory": {
|
||||||
"id": item.sale_category_id,
|
"id": item.sale_category_id,
|
||||||
"name": item.sale_category.name,
|
"name": item.sale_category.name,
|
||||||
"tax": {"id": item.sale_category.tax_id, "name": item.sale_category.name},
|
"tax": {
|
||||||
|
"id": item.sale_category.tax_id,
|
||||||
|
"name": item.sale_category.tax.name,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
"price": item.price,
|
"price": item.price,
|
||||||
"hasHappyHour": item.has_happy_hour,
|
"hasHappyHour": item.has_happy_hour,
|
||||||
|
|||||||
@ -23,6 +23,7 @@ import { HomeComponent } from './home/home.component';
|
|||||||
import { CoreModule } from './core/core.module';
|
import { CoreModule } from './core/core.module';
|
||||||
import { ReactiveFormsModule } from '@angular/forms';
|
import { ReactiveFormsModule } from '@angular/forms';
|
||||||
import { SharedModule } from './shared/shared.module';
|
import { SharedModule } from './shared/shared.module';
|
||||||
|
import { FlexLayoutModule } from '@angular/flex-layout';
|
||||||
|
|
||||||
registerLocaleData(enIN);
|
registerLocaleData(enIN);
|
||||||
|
|
||||||
@ -37,6 +38,7 @@ registerLocaleData(enIN);
|
|||||||
BrowserModule,
|
BrowserModule,
|
||||||
AppRoutingModule,
|
AppRoutingModule,
|
||||||
BrowserAnimationsModule,
|
BrowserAnimationsModule,
|
||||||
|
FlexLayoutModule,
|
||||||
MatGridListModule,
|
MatGridListModule,
|
||||||
MatCardModule,
|
MatCardModule,
|
||||||
MatMenuModule,
|
MatMenuModule,
|
||||||
|
|||||||
@ -20,7 +20,8 @@ export class AuthGuard implements CanActivate {
|
|||||||
this.toaster.show('Danger', 'User is not authenticated');
|
this.toaster.show('Danger', 'User is not authenticated');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const hasPermission = permission === undefined || user.perms.indexOf(permission) !== -1;
|
|
||||||
|
const hasPermission = this.auth.hasPermission(permission);
|
||||||
if (!hasPermission) {
|
if (!hasPermission) {
|
||||||
this.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.');
|
||||||
}
|
}
|
||||||
@ -28,14 +29,11 @@ export class AuthGuard implements CanActivate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | boolean {
|
canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | boolean {
|
||||||
if (this.auth.user === undefined) {
|
return this.auth.userObservable
|
||||||
return this.auth.userObservable
|
.pipe(
|
||||||
.pipe(
|
map<User, boolean>((value: User) => this.checkUser(
|
||||||
map<User, boolean>((value: User) => this.checkUser(
|
next.data['permission'], value, state
|
||||||
next.data['permission'], value, state
|
))
|
||||||
))
|
);
|
||||||
);
|
|
||||||
}
|
|
||||||
return this.checkUser(next.data['permission'], this.auth.user, state);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { HttpClient, HttpHeaders } from '@angular/common/http';
|
import { HttpClient, HttpHeaders } from '@angular/common/http';
|
||||||
import { Observable } from 'rxjs/internal/Observable';
|
import { Observable } from 'rxjs/internal/Observable';
|
||||||
import { catchError, tap } from 'rxjs/operators';
|
import { catchError, map, tap } from 'rxjs/operators';
|
||||||
import { Subject } from 'rxjs/internal/Subject';
|
|
||||||
import { ErrorLoggerService } from '../core/error-logger.service';
|
import { ErrorLoggerService } from '../core/error-logger.service';
|
||||||
import { User } from '../core/user';
|
import { User } from '../core/user';
|
||||||
|
import { merge, Subject } from 'rxjs';
|
||||||
|
|
||||||
|
|
||||||
const httpOptions = {
|
const httpOptions = {
|
||||||
@ -19,22 +19,18 @@ const checkUrl = '/v1/auth';
|
|||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
})
|
})
|
||||||
export class AuthService {
|
export class AuthService {
|
||||||
public userObservable = new Subject<User>();
|
private readonly userSubject: Subject<User>;
|
||||||
|
private user: User;
|
||||||
|
public userObservable: Observable<User>;
|
||||||
constructor(private http: HttpClient, private log: ErrorLoggerService) {
|
constructor(private http: HttpClient, private log: ErrorLoggerService) {
|
||||||
this.check().subscribe();
|
this.userSubject = new Subject<User>();
|
||||||
|
this.userObservable = merge(this.checkObserver(), this.userSubject).pipe(
|
||||||
|
tap(x => this.user = x)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _user: User;
|
checkObserver(): Observable<User> {
|
||||||
|
return <Observable<User>>this.http.get<User>(checkUrl, httpOptions);
|
||||||
get user() {
|
|
||||||
return this._user;
|
|
||||||
}
|
|
||||||
|
|
||||||
set user(user: User) {
|
|
||||||
this._user = user;
|
|
||||||
this.log.handleError('AuthService', 'Set User', user);
|
|
||||||
this.userObservable.next(user);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
login(name: string, password: string, otp?: string, clientName?: string): Observable<any> {
|
login(name: string, password: string, otp?: string, clientName?: string): Observable<any> {
|
||||||
@ -49,29 +45,20 @@ export class AuthService {
|
|||||||
|
|
||||||
return this.http.post(loginUrl, data, httpOptions)
|
return this.http.post(loginUrl, data, httpOptions)
|
||||||
.pipe(
|
.pipe(
|
||||||
tap((user: User) => this.user = user),
|
tap((user: User) => this.userSubject.next(user)),
|
||||||
catchError(this.log.handleError('AuthService', 'login'))
|
catchError(this.log.handleError('AuthService', 'login'))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
logout(): Observable<any> {
|
logout(): Observable<boolean> {
|
||||||
return this.http.post(logoutUrl, {}, httpOptions)
|
return <Observable<boolean>>this.http.post<User>(logoutUrl, {}, httpOptions)
|
||||||
.pipe(
|
.pipe(
|
||||||
tap((user: User) => this.user = user),
|
tap((user: User) => this.userSubject.next(user)),
|
||||||
catchError(this.log.handleError('AuthService', 'logout'))
|
map(() => true)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
check(): Observable<any> {
|
hasPermission(permission: string): boolean {
|
||||||
return this.http.get(checkUrl, httpOptions)
|
|
||||||
.pipe(
|
|
||||||
tap((user: User) => this.user = user),
|
|
||||||
catchError(this.log.handleError('AuthService', 'check'))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
hasPermission(permission: string) : boolean {
|
|
||||||
return this.user !== undefined && this.user.isAuthenticated && this.user.perms.indexOf(permission) !== -1;
|
return this.user !== undefined && this.user.isAuthenticated && this.user.perms.indexOf(permission) !== -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import {MenuCategory} from './menu-category';
|
import { MenuCategory } from './menu-category';
|
||||||
import {SaleCategory} from './sale-category';
|
import { SaleCategory } from './sale-category';
|
||||||
|
import { Tax } from './tax';
|
||||||
|
|
||||||
export class Product {
|
export class Product {
|
||||||
id: string;
|
id: string;
|
||||||
@ -16,4 +17,5 @@ export class Product {
|
|||||||
sortOrder: number;
|
sortOrder: number;
|
||||||
|
|
||||||
enabled?: boolean;
|
enabled?: boolean;
|
||||||
|
tax?: Tax;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,17 @@
|
|||||||
|
.square-button {
|
||||||
|
min-width: 150px;
|
||||||
|
max-width: 150px;
|
||||||
|
min-height: 150px;
|
||||||
|
max-height: 150px;
|
||||||
|
cursor: pointer;
|
||||||
|
margin: 20px;
|
||||||
|
}
|
||||||
|
.item-name {
|
||||||
|
text-align: center;
|
||||||
|
padding: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.center {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,53 +1,59 @@
|
|||||||
<h1>Welcome to bookie!</h1>
|
<div fxLayout="row wrap" fxLayoutGap="grid 20px">
|
||||||
<a mat-raised-button routerLink="/login" *ngIf="!(nameObject | async)">
|
<mat-card fxLayout="column" class="square-button" matRipple [routerLink]="['/', 'login']" *ngIf="!(user | async)">
|
||||||
<mat-icon>account_box</mat-icon>
|
<h3 class="item-name">
|
||||||
Login</a>
|
<mat-icon>account_box</mat-icon>
|
||||||
<a mat-raised-button routerLink="/guest-book">
|
Login
|
||||||
Guest Book
|
</h3>
|
||||||
</a>
|
</mat-card>
|
||||||
<a mat-raised-button routerLink="/sales">
|
<mat-card fxLayout="column" class="square-button" matRipple [routerLink]="['/', 'guest-book']">
|
||||||
Sales
|
<h3 class="item-name">Guest Book</h3>
|
||||||
</a>
|
</mat-card>
|
||||||
<a mat-raised-button routerLink="/tables">
|
<mat-card fxLayout="column" class="square-button" matRipple [routerLink]="['/', 'sales']">
|
||||||
Tables
|
<h3 class="item-name">Sales</h3>
|
||||||
</a>
|
</mat-card>
|
||||||
<a mat-raised-button routerLink="/sections">
|
<mat-card fxLayout="column" class="square-button" matRipple [routerLink]="['/', 'tables']">
|
||||||
Sections
|
<h3 class="item-name">Tables</h3>
|
||||||
</a>
|
</mat-card>
|
||||||
<a mat-raised-button routerLink="/menu-categories">
|
<mat-card fxLayout="column" class="square-button" matRipple [routerLink]="['/', 'sections']">
|
||||||
Menu Categories
|
<h3 class="item-name">Sections</h3>
|
||||||
</a>
|
</mat-card>
|
||||||
<a mat-raised-button routerLink="/sale-categories">
|
<mat-card fxLayout="column" class="square-button" matRipple [routerLink]="['/', 'menu-categories']">
|
||||||
Sale Categories
|
<h3 class="item-name">Menu Categories</h3>
|
||||||
</a>
|
</mat-card>
|
||||||
<a mat-raised-button routerLink="/products">
|
<mat-card fxLayout="column" class="square-button" matRipple [routerLink]="['/', 'sale-categories']">
|
||||||
Products
|
<h3 class="item-name">Sale Categories</h3>
|
||||||
</a>
|
</mat-card>
|
||||||
<a mat-raised-button routerLink="/modifier-categories">
|
<mat-card fxLayout="column" class="square-button" matRipple [routerLink]="['/', 'products']">
|
||||||
Modifier Categories
|
<h3 class="item-name">Products</h3>
|
||||||
</a>
|
</mat-card>
|
||||||
<a mat-raised-button routerLink="/modifiers">
|
<mat-card fxLayout="column" class="square-button" matRipple [routerLink]="['/', 'modifier-categories']">
|
||||||
Modifiers
|
<h3 class="item-name">Modifier Categories</h3>
|
||||||
</a>
|
</mat-card>
|
||||||
<a mat-raised-button routerLink="/taxes">
|
<mat-card fxLayout="column" class="square-button" matRipple [routerLink]="['/', 'modifiers']">
|
||||||
Taxes
|
<h3 class="item-name">Modifiers</h3>
|
||||||
</a>
|
</mat-card>
|
||||||
<a mat-raised-button routerLink="/devices">
|
<mat-card fxLayout="column" class="square-button" matRipple [routerLink]="['/', 'taxes']">
|
||||||
Devices
|
<h3 class="item-name">Taxes</h3>
|
||||||
</a>
|
</mat-card>
|
||||||
<a mat-raised-button routerLink="/section-printers">
|
<mat-card fxLayout="column" class="square-button" matRipple [routerLink]="['/', 'devices']">
|
||||||
Section Printers
|
<h3 class="item-name">Devices</h3>
|
||||||
</a>
|
</mat-card>
|
||||||
<a mat-raised-button routerLink="/printers">
|
<mat-card fxLayout="column" class="square-button" matRipple [routerLink]="['/', 'section-printers']">
|
||||||
Printers
|
<h3 class="item-name">Section Printers</h3>
|
||||||
</a>
|
</mat-card>
|
||||||
<a mat-raised-button routerLink="/roles">
|
<mat-card fxLayout="column" class="square-button" matRipple [routerLink]="['/', 'printers']">
|
||||||
Roles
|
<h3 class="item-name">Printers</h3>
|
||||||
</a>
|
</mat-card>
|
||||||
<a mat-raised-button routerLink="/users">
|
<mat-card fxLayout="column" class="square-button" matRipple [routerLink]="['/', 'roles']">
|
||||||
Users
|
<h3 class="item-name">Roles</h3>
|
||||||
</a>
|
</mat-card>
|
||||||
<a mat-raised-button routerLink="/logout" *ngIf="nameObject | async as name">
|
<mat-card fxLayout="column" class="square-button" matRipple [routerLink]="['/', 'users']">
|
||||||
<mat-icon>account_box</mat-icon>
|
<h3 class="item-name">Users</h3>
|
||||||
Logout {{name}}
|
</mat-card>
|
||||||
</a>
|
<mat-card fxLayout="column" class="square-button" matRipple [routerLink]="['/', 'logout']"
|
||||||
|
*ngIf="user | async as name">
|
||||||
|
<h3 class="item-name">
|
||||||
|
<mat-icon>account_box</mat-icon>
|
||||||
|
Logout {{name}}</h3>
|
||||||
|
</mat-card>
|
||||||
|
</div>
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import {Component, OnInit} from '@angular/core';
|
import { Component, OnInit} from '@angular/core';
|
||||||
import {Subject} from 'rxjs';
|
import { AuthService} from '../auth/auth.service';
|
||||||
import {AuthService} from '../auth/auth.service';
|
import { Observable } from 'rxjs';
|
||||||
|
import { map, share } from 'rxjs/operators';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-home',
|
selector: 'app-home',
|
||||||
@ -8,18 +9,15 @@ import {AuthService} from '../auth/auth.service';
|
|||||||
styleUrls: ['./home.component.css']
|
styleUrls: ['./home.component.css']
|
||||||
})
|
})
|
||||||
export class HomeComponent implements OnInit {
|
export class HomeComponent implements OnInit {
|
||||||
public nameObject = new Subject<string>();
|
public user: Observable<string>;
|
||||||
|
|
||||||
constructor(private auth: AuthService) {
|
constructor(private auth: AuthService) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.auth.userObservable.subscribe((user) => {
|
this.user = this.auth.userObservable.pipe(
|
||||||
if (user.isAuthenticated) {
|
map (x => x.isAuthenticated ? x.name : null),
|
||||||
this.nameObject.next(user.name);
|
share()
|
||||||
} else {
|
);
|
||||||
this.nameObject.next(null);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import { MatDialogRef } from '@angular/material';
|
import { MatDialogRef } from '@angular/material';
|
||||||
import { PrintType } from "../bills/bill";
|
import { PrintType } from '../bills/bill';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-bill-type',
|
selector: 'app-bill-type',
|
||||||
|
|||||||
@ -9,16 +9,19 @@ import { ModifierCategoryService } from '../modifier-categories/modifier-categor
|
|||||||
import { ModifierCategory } from '../core/modifier-category';
|
import { ModifierCategory } from '../core/modifier-category';
|
||||||
import { Bill, Inventory, Kot, PrintType } from './bills/bill';
|
import { Bill, Inventory, Kot, PrintType } from './bills/bill';
|
||||||
import { VoucherService } from './bills/voucher.service';
|
import { VoucherService } from './bills/voucher.service';
|
||||||
import { ToasterService } from "../core/toaster.service";
|
import { ToasterService } from '../core/toaster.service';
|
||||||
import { tap } from "rxjs/operators";
|
import { tap } from 'rxjs/operators';
|
||||||
import { Table } from "../core/table";
|
import { Table } from '../core/table';
|
||||||
import {observableToBeFn} from "rxjs/internal/testing/TestScheduler";
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class BillService {
|
export class BillService {
|
||||||
public dataObs;
|
public dataObs;
|
||||||
public data;
|
public data;
|
||||||
private bill;
|
private bill;
|
||||||
|
public netAmount: BehaviorSubject<number>;
|
||||||
|
public discountAmount: BehaviorSubject<number>;
|
||||||
|
public taxAmount: BehaviorSubject<number>;
|
||||||
|
public amount: BehaviorSubject<number>;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private dialog: MatDialog,
|
private dialog: MatDialog,
|
||||||
@ -28,6 +31,10 @@ export class BillService {
|
|||||||
) {
|
) {
|
||||||
this.data = [];
|
this.data = [];
|
||||||
this.dataObs = new BehaviorSubject<any[]>(this.data);
|
this.dataObs = new BehaviorSubject<any[]>(this.data);
|
||||||
|
this.netAmount = new BehaviorSubject(0);
|
||||||
|
this.discountAmount = new BehaviorSubject(0);
|
||||||
|
this.taxAmount = new BehaviorSubject(0);
|
||||||
|
this.amount = new BehaviorSubject(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
loadData(bill: Bill): void {
|
loadData(bill: Bill): void {
|
||||||
@ -58,6 +65,7 @@ export class BillService {
|
|||||||
this.data = view.reduce((a, c) => a.concat(c) , []);
|
this.data = view.reduce((a, c) => a.concat(c) , []);
|
||||||
this.data.push({isKot: true, newKot: true, info: '== New Kot =='});
|
this.data.push({isKot: true, newKot: true, info: '== New Kot =='});
|
||||||
this.dataObs.next(this.data);
|
this.dataObs.next(this.data);
|
||||||
|
this.updateAmounts();
|
||||||
|
|
||||||
}
|
}
|
||||||
addProduct(product: Product): void {
|
addProduct(product: Product): void {
|
||||||
@ -76,8 +84,8 @@ export class BillService {
|
|||||||
price: product.price,
|
price: product.price,
|
||||||
quantity: 1,
|
quantity: 1,
|
||||||
discount: 0,
|
discount: 0,
|
||||||
taxRate: product.saleCategory.tax.rate,
|
taxRate: product.tax.rate,
|
||||||
tax: product.saleCategory.tax,
|
tax: product.tax,
|
||||||
modifiers: []
|
modifiers: []
|
||||||
};
|
};
|
||||||
this.data.push(item);
|
this.data.push(item);
|
||||||
@ -90,6 +98,7 @@ export class BillService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
this.dataObs.next(this.data);
|
this.dataObs.next(this.data);
|
||||||
|
this.updateAmounts();
|
||||||
}
|
}
|
||||||
|
|
||||||
showModifier(item: any): void {
|
showModifier(item: any): void {
|
||||||
@ -114,17 +123,20 @@ export class BillService {
|
|||||||
addOne(item: any): void {
|
addOne(item: any): void {
|
||||||
item.quantity += 1;
|
item.quantity += 1;
|
||||||
this.dataObs.next(this.data);
|
this.dataObs.next(this.data);
|
||||||
|
this.updateAmounts();
|
||||||
}
|
}
|
||||||
|
|
||||||
quantity(item: any, quantity: number): void {
|
quantity(item: any, quantity: number): void {
|
||||||
item.quantity = quantity;
|
item.quantity = quantity;
|
||||||
this.dataObs.next(this.data);
|
this.dataObs.next(this.data);
|
||||||
|
this.updateAmounts();
|
||||||
}
|
}
|
||||||
|
|
||||||
subtractOne(item: any): void {
|
subtractOne(item: any): void {
|
||||||
if (item.quantity > 1) {
|
if (item.quantity > 1) {
|
||||||
item.quantity -= 1;
|
item.quantity -= 1;
|
||||||
this.dataObs.next(this.data);
|
this.dataObs.next(this.data);
|
||||||
|
this.updateAmounts();
|
||||||
} else if (item.quantity === 0) {
|
} else if (item.quantity === 0) {
|
||||||
this.removeItem(item);
|
this.removeItem(item);
|
||||||
}
|
}
|
||||||
@ -133,20 +145,22 @@ export class BillService {
|
|||||||
removeItem(item: any): void {
|
removeItem(item: any): void {
|
||||||
this.data.splice(this.data.indexOf(item), 1);
|
this.data.splice(this.data.indexOf(item), 1);
|
||||||
this.dataObs.next(this.data);
|
this.dataObs.next(this.data);
|
||||||
|
this.updateAmounts();
|
||||||
}
|
}
|
||||||
|
|
||||||
modifier(item: any): void {
|
modifier(item: any): void {
|
||||||
this.showModifier(item);
|
this.showModifier(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
discount(discounts:{id: string, name: string, discount: number}[]): void {
|
discount(discounts: {id: string, name: string, discount: number}[]): void {
|
||||||
this.data.forEach(x=> {
|
this.data.forEach(x => {
|
||||||
if (!x.isKot) {
|
if (!x.isKot) {
|
||||||
x.discount = discounts.find(d => d.id === x.product.saleCategory.id).discount / 100;
|
x.discount = discounts.find(d => d.id === x.product.saleCategory.id).discount / 100;
|
||||||
x.info = `${x.product.name} (${x.product.units}) @ ${x.price} - ${math.round(x.discount * 100, 2)}%`;
|
x.info = `${x.product.name} (${x.product.units}) @ ${x.price} - ${math.round(x.discount * 100, 2)}%`;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.dataObs.next(this.data);
|
this.dataObs.next(this.data);
|
||||||
|
this.updateAmounts();
|
||||||
}
|
}
|
||||||
|
|
||||||
private getKot(): Kot {
|
private getKot(): Kot {
|
||||||
@ -165,28 +179,24 @@ export class BillService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
printKot(guest_book_id: string): Observable<Bill> {
|
printKot(guest_book_id: string): Observable<Bill> {
|
||||||
let item = JSON.parse(JSON.stringify(this.bill));
|
const item = JSON.parse(JSON.stringify(this.bill));
|
||||||
let newKot = this.getKot();
|
const newKot = this.getKot();
|
||||||
if (newKot.inventories.length == 0) {
|
if (newKot.inventories.length == 0) {
|
||||||
this.toaster.show('Error', 'Cannot print a blank KOT\nPlease add some products!');
|
this.toaster.show('Error', 'Cannot print a blank KOT\nPlease add some products!');
|
||||||
}
|
}
|
||||||
item.kots.push(newKot);
|
item.kots.push(newKot);
|
||||||
return this.ser.saveOrUpdate(item, PrintType.Kot, guest_book_id, true).pipe(
|
return this.ser.saveOrUpdate(item, PrintType.Kot, guest_book_id, true);
|
||||||
tap(x => console.log(x))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
printBill(guest_book_id: string, printType: PrintType): Observable<Bill> {
|
printBill(guest_book_id: string, printType: PrintType): Observable<Bill> {
|
||||||
let item = JSON.parse(JSON.stringify(this.bill));
|
const item = JSON.parse(JSON.stringify(this.bill));
|
||||||
item.kots.forEach(k => {
|
item.kots.forEach(k => {
|
||||||
k.inventories.forEach(i => {
|
k.inventories.forEach(i => {
|
||||||
i.discount = this.data.find(x => !x.isKot && x.id === i.id).discount;
|
i.discount = this.data.find(x => !x.isKot && x.id === i.id).discount;
|
||||||
})
|
});
|
||||||
});
|
});
|
||||||
item.kots.push(this.getKot());
|
item.kots.push(this.getKot());
|
||||||
return this.ser.saveOrUpdate(item, printType, guest_book_id, true).pipe(
|
return this.ser.saveOrUpdate(item, printType, guest_book_id, true);
|
||||||
tap(x => console.log(x))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type() {
|
type() {
|
||||||
@ -194,48 +204,49 @@ export class BillService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
receivePayment(amounts: { id: string; name: string; amount: number }[]): Observable<boolean> {
|
receivePayment(amounts: { id: string; name: string; amount: number }[]): Observable<boolean> {
|
||||||
return this.ser.receivePayment(this.bill.id, amounts, true).pipe(
|
return this.ser.receivePayment(this.bill.id, amounts, true);
|
||||||
tap(x => console.log(x))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
moveTable(table: Table): Observable<boolean> {
|
moveTable(table: Table): Observable<boolean> {
|
||||||
return this.ser.moveTable(this.bill.id, table);
|
return this.ser.moveTable(this.bill.id, table);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
moveKot(id: string, table: Table): Observable<boolean> {
|
||||||
|
return this.ser.moveKot(this.bill.id, id, table);
|
||||||
|
}
|
||||||
|
|
||||||
voidBill(reason: string): Observable<boolean> {
|
voidBill(reason: string): Observable<boolean> {
|
||||||
return this.ser.voidBill(this.bill.id, reason, true);
|
return this.ser.voidBill(this.bill.id, reason, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
netAmount() {
|
updateAmounts() {
|
||||||
return math.round(this.bill.kots.reduce(
|
this.netAmount.next(
|
||||||
(ka: number, k: Kot) => ka + k.inventories.reduce(
|
math.round(this.data.filter(x => !x.isKot).reduce(
|
||||||
(ca: number, c: Inventory) => ca + ((c.isHappyHour ? 0 : c.price) * c.quantity)
|
(ca: number, c: any) => ca + ((c.isHappyHour ? 0 : c.price) * c.quantity)
|
||||||
, 0)
|
, 0))
|
||||||
, 0))
|
);
|
||||||
}
|
this.discountAmount.next(
|
||||||
|
math.round(this.data.filter(x => !x.isKot).reduce(
|
||||||
discountAmount() {
|
|
||||||
return math.round(this.bill.kots.reduce(
|
|
||||||
(ka: number, k: Kot) => ka + k.inventories.reduce(
|
|
||||||
(ca: number, c: Inventory) => ca + ((c.isHappyHour ? 0 : c.price) * c.quantity * c.discount)
|
(ca: number, c: Inventory) => ca + ((c.isHappyHour ? 0 : c.price) * c.quantity * c.discount)
|
||||||
, 0)
|
, 0))
|
||||||
, 0))
|
);
|
||||||
}
|
this.taxAmount.next(
|
||||||
|
math.round(this.data.filter(x => !x.isKot).reduce(
|
||||||
taxAmount() {
|
|
||||||
return math.round(this.bill.kots.reduce(
|
|
||||||
(ka: number, k: Kot) => ka + k.inventories.reduce(
|
|
||||||
(ca: number, c: Inventory) => ca + ((c.isHappyHour ? 0 : c.price) * c.quantity * (1 - c.discount) * c.taxRate)
|
(ca: number, c: Inventory) => ca + ((c.isHappyHour ? 0 : c.price) * c.quantity * (1 - c.discount) * c.taxRate)
|
||||||
, 0)
|
, 0))
|
||||||
, 0))
|
);
|
||||||
|
this.amount.next(
|
||||||
|
math.round(this.data.filter(x => !x.isKot).reduce(
|
||||||
|
(ca: number, c: Inventory) => ca + ((c.isHappyHour ? 0 : c.price) * c.quantity * (1 - c.discount) * (1 + c.taxRate))
|
||||||
|
, 0))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
amount() {
|
amountVal(): number {
|
||||||
return math.round(this.bill.kots.reduce(
|
return math.round(this.bill.kots.reduce(
|
||||||
(ka: number, k: Kot) => ka + k.inventories.reduce(
|
(ka: number, k: Kot) => ka + k.inventories.reduce(
|
||||||
(ca: number, c: Inventory) => ca + ((c.isHappyHour ? 0 : c.price) * c.quantity * (1 - c.discount) * (1 + c.taxRate))
|
(ca: number, c: Inventory) => ca + ((c.isHappyHour ? 0 : c.price) * c.quantity * (1 - c.discount) * (1 + c.taxRate))
|
||||||
, 0)
|
, 0)
|
||||||
, 0))
|
, 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -39,26 +39,29 @@
|
|||||||
<button mat-icon-button (click)="modifier(row)" [disabled]="row.isPrinted" *ngIf="!row.isKot">
|
<button mat-icon-button (click)="modifier(row)" [disabled]="row.isPrinted" *ngIf="!row.isKot">
|
||||||
<mat-icon class="del">assignment</mat-icon>
|
<mat-icon class="del">assignment</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
|
<button mat-icon-button (click)="modifier(row)" [disabled]="row.newKot" *ngIf="row.isKot">
|
||||||
|
<mat-icon class="del">open_in_new</mat-icon>
|
||||||
|
</button>
|
||||||
</mat-cell>
|
</mat-cell>
|
||||||
<mat-footer-cell *matFooterCellDef class="grey900 bold right-align">{{ amount() | currency: 'INR' }}</mat-footer-cell>
|
<mat-footer-cell *matFooterCellDef class="grey900 bold right-align">{{ bs.amount | async | currency: 'INR' }}</mat-footer-cell>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<ng-container matColumnDef="net-title">
|
<ng-container matColumnDef="net-title">
|
||||||
<mat-footer-cell *matFooterCellDef class="grey300 bold">Net</mat-footer-cell>
|
<mat-footer-cell *matFooterCellDef class="grey300 bold">Net</mat-footer-cell>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<ng-container matColumnDef="net-amount">
|
<ng-container matColumnDef="net-amount">
|
||||||
<mat-footer-cell *matFooterCellDef class="grey300 bold right-align">{{ netAmount() | currency: 'INR' }}</mat-footer-cell>
|
<mat-footer-cell *matFooterCellDef class="grey300 bold right-align">{{ bs.netAmount | async | currency: 'INR' }}</mat-footer-cell>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<ng-container matColumnDef="discount-title">
|
<ng-container matColumnDef="discount-title">
|
||||||
<mat-footer-cell *matFooterCellDef class="grey500 bold">Discount</mat-footer-cell>
|
<mat-footer-cell *matFooterCellDef class="grey500 bold">Discount</mat-footer-cell>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<ng-container matColumnDef="discount-amount">
|
<ng-container matColumnDef="discount-amount">
|
||||||
<mat-footer-cell *matFooterCellDef class="grey500 bold right-align">{{ discountAmount() | currency: 'INR' }}</mat-footer-cell>
|
<mat-footer-cell *matFooterCellDef class="grey500 bold right-align">{{ bs.discountAmount | async | currency: 'INR' }}</mat-footer-cell>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<ng-container matColumnDef="tax-title">
|
<ng-container matColumnDef="tax-title">
|
||||||
<mat-footer-cell *matFooterCellDef class="grey700 bold">Tax</mat-footer-cell>
|
<mat-footer-cell *matFooterCellDef class="grey700 bold">Tax</mat-footer-cell>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<ng-container matColumnDef="tax-amount">
|
<ng-container matColumnDef="tax-amount">
|
||||||
<mat-footer-cell *matFooterCellDef class="grey700 bold right-align">{{ taxAmount() | currency: 'INR' }}</mat-footer-cell>
|
<mat-footer-cell *matFooterCellDef class="grey700 bold right-align">{{ bs.taxAmount | async | currency: 'INR' }}</mat-footer-cell>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<mat-row *matRowDef="let row; columns: displayedColumns;" [class.blue400]="row.oldKot" [class.blue800]="row.newKot"
|
<mat-row *matRowDef="let row; columns: displayedColumns;" [class.blue400]="row.oldKot" [class.blue800]="row.newKot"
|
||||||
|
|||||||
@ -1,10 +1,17 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { ActivatedRoute } from '@angular/router';
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
import { Bill } from './bill';
|
import { Bill, Kot } from './bill';
|
||||||
import { BillsDataSource } from './bills-datasource';
|
import { BillsDataSource } from './bills-datasource';
|
||||||
import { BillService } from '../bill.service';
|
import { BillService } from '../bill.service';
|
||||||
import { QuantityComponent } from '../quantity/quantity.component';
|
import { QuantityComponent } from '../quantity/quantity.component';
|
||||||
import { MatDialog } from '@angular/material';
|
import { MatDialog } from '@angular/material';
|
||||||
|
import { Table } from '../../core/table';
|
||||||
|
import { Observable, throwError } from 'rxjs';
|
||||||
|
import { ConfirmDialogComponent } from '../../shared/confirm-dialog/confirm-dialog.component';
|
||||||
|
import { map, switchMap } from 'rxjs/operators';
|
||||||
|
import { TablesDialogComponent } from '../tables-dialog/tables-dialog.component';
|
||||||
|
import { TableService } from '../../tables/table.service';
|
||||||
|
import { ToasterService } from '../../core/toaster.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-bills',
|
selector: 'app-bills',
|
||||||
@ -19,8 +26,11 @@ export class BillsComponent implements OnInit {
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private route: ActivatedRoute,
|
private route: ActivatedRoute,
|
||||||
|
private router: Router,
|
||||||
private dialog: MatDialog,
|
private dialog: MatDialog,
|
||||||
private bs: BillService
|
private toaster: ToasterService,
|
||||||
|
private bs: BillService,
|
||||||
|
private tSer: TableService
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,20 +72,4 @@ export class BillsComponent implements OnInit {
|
|||||||
modifier(item: any): void {
|
modifier(item: any): void {
|
||||||
this.bs.modifier(item);
|
this.bs.modifier(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
netAmount(): number {
|
|
||||||
return this.bs.netAmount();
|
|
||||||
}
|
|
||||||
|
|
||||||
discountAmount(): number {
|
|
||||||
return this.bs.discountAmount();
|
|
||||||
}
|
|
||||||
|
|
||||||
taxAmount(): number {
|
|
||||||
return this.bs.taxAmount();
|
|
||||||
}
|
|
||||||
|
|
||||||
amount(): number {
|
|
||||||
return this.bs.amount();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import { catchError } from 'rxjs/operators';
|
|||||||
import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http';
|
import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http';
|
||||||
import { ErrorLoggerService } from '../../core/error-logger.service';
|
import { ErrorLoggerService } from '../../core/error-logger.service';
|
||||||
import { Bill, PrintType } from './bill';
|
import { Bill, PrintType } from './bill';
|
||||||
import { Table } from "../../core/table";
|
import { Table } from '../../core/table';
|
||||||
|
|
||||||
const httpOptions = {
|
const httpOptions = {
|
||||||
headers: new HttpHeaders({'Content-Type': 'application/json'})
|
headers: new HttpHeaders({'Content-Type': 'application/json'})
|
||||||
@ -50,7 +50,7 @@ export class VoucherService {
|
|||||||
save(voucher: Bill, printType: PrintType, guest_book_id: string, updateTable: boolean): Observable<Bill> {
|
save(voucher: Bill, printType: PrintType, guest_book_id: string, updateTable: boolean): Observable<Bill> {
|
||||||
const options = {params: new HttpParams().set('p', printType).set('u', updateTable.toString())};
|
const options = {params: new HttpParams().set('p', printType).set('u', updateTable.toString())};
|
||||||
if (guest_book_id !== null) {
|
if (guest_book_id !== null) {
|
||||||
options.params = options.params.set('g', guest_book_id)
|
options.params = options.params.set('g', guest_book_id);
|
||||||
}
|
}
|
||||||
return <Observable<Bill>>this.http.post<Bill>(`${url}/new`, voucher, options)
|
return <Observable<Bill>>this.http.post<Bill>(`${url}/new`, voucher, options)
|
||||||
.pipe(
|
.pipe(
|
||||||
@ -61,7 +61,7 @@ export class VoucherService {
|
|||||||
update(voucher: Bill, printType: PrintType, guest_book_id: string, updateTable: boolean): Observable<Bill> {
|
update(voucher: Bill, printType: PrintType, guest_book_id: string, updateTable: boolean): Observable<Bill> {
|
||||||
const options = {params: new HttpParams().set('p', printType).set('u', updateTable.toString())};
|
const options = {params: new HttpParams().set('p', printType).set('u', updateTable.toString())};
|
||||||
if (guest_book_id !== null) {
|
if (guest_book_id !== null) {
|
||||||
options.params = options.params.set('g', guest_book_id)
|
options.params = options.params.set('g', guest_book_id);
|
||||||
}
|
}
|
||||||
return <Observable<Bill>>this.http.put<Bill>(`${url}/${voucher.id}`, voucher, options)
|
return <Observable<Bill>>this.http.put<Bill>(`${url}/${voucher.id}`, voucher, options)
|
||||||
.pipe(
|
.pipe(
|
||||||
@ -78,7 +78,7 @@ export class VoucherService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
receivePayment(id: string, amounts: { id: string; name: string; amount: number }[], updateTable: boolean): Observable<boolean> {
|
receivePayment(id: string, amounts: { id: string; name: string; amount: number }[], updateTable: boolean): Observable<boolean> {
|
||||||
const options = {params: new HttpParams().set('receive-payment', "").set('u', updateTable.toString())};
|
const options = {params: new HttpParams().set('receive-payment', '').set('u', updateTable.toString())};
|
||||||
return <Observable<boolean>>this.http.post<boolean>(`${url}/${id}`, amounts, options)
|
return <Observable<boolean>>this.http.post<boolean>(`${url}/${id}`, amounts, options)
|
||||||
.pipe(
|
.pipe(
|
||||||
catchError(this.log.handleError(serviceName, 'receivePayment'))
|
catchError(this.log.handleError(serviceName, 'receivePayment'))
|
||||||
@ -87,14 +87,14 @@ export class VoucherService {
|
|||||||
|
|
||||||
moveTable(id: string, table: Table): Observable<boolean> {
|
moveTable(id: string, table: Table): Observable<boolean> {
|
||||||
const options = {params: new HttpParams().set('move-table', '')};
|
const options = {params: new HttpParams().set('move-table', '')};
|
||||||
return <Observable<boolean>>this.http.post<boolean>(`${url}/${id}`, {table:{id: table.id}}, options)
|
return <Observable<boolean>>this.http.post<boolean>(`${url}/${id}`, {table: {id: table.id}}, options)
|
||||||
.pipe(
|
.pipe(
|
||||||
catchError(this.log.handleError(serviceName, 'moveTable'))
|
catchError(this.log.handleError(serviceName, 'moveTable'))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
voidBill(id: string, reason: string, updateTable: boolean): Observable<boolean> {
|
voidBill(id: string, reason: string, updateTable: boolean): Observable<boolean> {
|
||||||
const options = {params: new HttpParams().set('void-bill', "").set('u', updateTable.toString())};
|
const options = {params: new HttpParams().set('void-bill', '').set('u', updateTable.toString())};
|
||||||
return <Observable<boolean>>this.http.post<boolean>(`${url}/${id}`, {reason: reason}, options)
|
return <Observable<boolean>>this.http.post<boolean>(`${url}/${id}`, {reason: reason}, options)
|
||||||
.pipe(
|
.pipe(
|
||||||
catchError(this.log.handleError(serviceName, 'voidBill'))
|
catchError(this.log.handleError(serviceName, 'voidBill'))
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import { Component, Inject } from '@angular/core';
|
import { Component, Inject } from '@angular/core';
|
||||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material';
|
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { FormArray, FormBuilder, FormGroup, Validators } from "@angular/forms";
|
import { FormArray, FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||||
import { DiscountDataSource } from "./discount-datasource";
|
import { DiscountDataSource } from './discount-datasource';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-modifiers',
|
selector: 'app-modifiers',
|
||||||
@ -28,7 +28,7 @@ export class DiscountComponent {
|
|||||||
this.list.map(
|
this.list.map(
|
||||||
x => this.fb.group({
|
x => this.fb.group({
|
||||||
name: [x.name],
|
name: [x.name],
|
||||||
discount: ["", [Validators.min(0), Validators.max(100)]]
|
discount: ['', [Validators.min(0), Validators.max(100)]]
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
));
|
));
|
||||||
|
|||||||
@ -1,21 +1,21 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { ActivatedRoute, Router } from "@angular/router";
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
import { MatDialog } from "@angular/material";
|
import { MatDialog } from '@angular/material';
|
||||||
import { concatMap, map, switchMap, tap } from "rxjs/operators";
|
import { concatMap, map, switchMap, tap } from 'rxjs/operators';
|
||||||
import { iif, Observable, of as observableOf, throwError } from "rxjs";
|
import { iif, Observable, of as observableOf, throwError } from 'rxjs';
|
||||||
import { BillService } from '../bill.service';
|
import { BillService } from '../bill.service';
|
||||||
import { ToasterService } from "../../core/toaster.service";
|
import { ToasterService } from '../../core/toaster.service';
|
||||||
import { DiscountComponent } from "../discount/discount.component";
|
import { DiscountComponent } from '../discount/discount.component';
|
||||||
import { SaleCategoryService } from "../../sale-category/sale-category.service";
|
import { SaleCategoryService } from '../../sale-category/sale-category.service';
|
||||||
import { BillTypeComponent } from "../bill-type/bill-type.component";
|
import { BillTypeComponent } from '../bill-type/bill-type.component';
|
||||||
import { PrintType } from "../bills/bill";
|
import { PrintType } from '../bills/bill';
|
||||||
import { AuthService } from "../../auth/auth.service";
|
import { AuthService } from '../../auth/auth.service';
|
||||||
import { ReceivePaymentComponent } from "../receive-payment/receive-payment.component";
|
import { ReceivePaymentComponent } from '../receive-payment/receive-payment.component';
|
||||||
import { TableService } from "../../tables/table.service";
|
import { TableService } from '../../tables/table.service';
|
||||||
import { Table } from "../../core/table";
|
import { Table } from '../../core/table';
|
||||||
import { TablesDialogComponent } from "../tables-dialog/tables-dialog.component";
|
import { TablesDialogComponent } from '../tables-dialog/tables-dialog.component';
|
||||||
import { ConfirmDialogComponent } from "../../shared/confirm-dialog/confirm-dialog.component";
|
import { ConfirmDialogComponent } from '../../shared/confirm-dialog/confirm-dialog.component';
|
||||||
import { VoidReasonComponent } from "../void-reason/void-reason.component";
|
import { VoidReasonComponent } from '../void-reason/void-reason.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-sales-home',
|
selector: 'app-sales-home',
|
||||||
@ -40,8 +40,8 @@ export class SalesHomeComponent implements OnInit {
|
|||||||
|
|
||||||
printKot() {
|
printKot() {
|
||||||
let guestBookId = null;
|
let guestBookId = null;
|
||||||
if (this.route.snapshot.queryParamMap.has("guest")) {
|
if (this.route.snapshot.queryParamMap.has('guest')) {
|
||||||
guestBookId = this.route.snapshot.queryParamMap.get("guest");
|
guestBookId = this.route.snapshot.queryParamMap.get('guest');
|
||||||
}
|
}
|
||||||
this.bs.printKot(guestBookId).subscribe(x => {
|
this.bs.printKot(guestBookId).subscribe(x => {
|
||||||
this.toaster.show('Success', '');
|
this.toaster.show('Success', '');
|
||||||
@ -50,7 +50,7 @@ export class SalesHomeComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
discount(): void {
|
discount(): void {
|
||||||
if (this.auth.hasPermission("Discount")) {
|
if (this.auth.hasPermission('Discount')) {
|
||||||
this.showDiscount().subscribe();
|
this.showDiscount().subscribe();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -66,15 +66,15 @@ export class SalesHomeComponent implements OnInit {
|
|||||||
this.bs.discount(result as { id: string, name: string, discount: number }[]);
|
this.bs.discount(result as { id: string, name: string, discount: number }[]);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
discountDialog (canGiveDiscount: boolean) : Observable<any> {
|
discountDialog (canGiveDiscount: boolean): Observable<any> {
|
||||||
let discObs = null;
|
let discObs = null;
|
||||||
if (canGiveDiscount) {
|
if (canGiveDiscount) {
|
||||||
return discObs = this.showDiscount();
|
return discObs = this.showDiscount();
|
||||||
} else {
|
} else {
|
||||||
return discObs = observableOf("");
|
return discObs = observableOf('');
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -83,10 +83,10 @@ export class SalesHomeComponent implements OnInit {
|
|||||||
return this.dialog.open(BillTypeComponent).afterClosed().pipe(
|
return this.dialog.open(BillTypeComponent).afterClosed().pipe(
|
||||||
tap(x => {
|
tap(x => {
|
||||||
if (!x) {
|
if (!x) {
|
||||||
throwError ("No Bill Type Chosen")
|
throwError ('No Bill Type Chosen');
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
confirmMoveTableDialog(table: Table): Observable<{table: Table, confirmed: boolean}> {
|
confirmMoveTableDialog(table: Table): Observable<{table: Table, confirmed: boolean}> {
|
||||||
@ -108,10 +108,10 @@ export class SalesHomeComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
printBill() {
|
printBill() {
|
||||||
const canGiveDiscount = this.auth.hasPermission("Discount");
|
const canGiveDiscount = this.auth.hasPermission('Discount');
|
||||||
let guestBookId = null;
|
let guestBookId = null;
|
||||||
if (this.route.snapshot.queryParamMap.has("guest")) {
|
if (this.route.snapshot.queryParamMap.has('guest')) {
|
||||||
guestBookId = this.route.snapshot.queryParamMap.get("guest");
|
guestBookId = this.route.snapshot.queryParamMap.get('guest');
|
||||||
}
|
}
|
||||||
this.discountDialog(canGiveDiscount).pipe(
|
this.discountDialog(canGiveDiscount).pipe(
|
||||||
concatMap(() => this.billTypeDialog())
|
concatMap(() => this.billTypeDialog())
|
||||||
@ -128,13 +128,13 @@ export class SalesHomeComponent implements OnInit {
|
|||||||
this.router.navigate(['/sales']);
|
this.router.navigate(['/sales']);
|
||||||
},
|
},
|
||||||
x => {
|
x => {
|
||||||
this.toaster.show('Error', "No Bill Type Chosen")
|
this.toaster.show('Error', 'No Bill Type Chosen');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
receivePayment() {
|
receivePayment() {
|
||||||
let amount = this.bs.amount();
|
const amount = this.bs.amountVal();
|
||||||
let type = this.bs.type();
|
const type = this.bs.type();
|
||||||
const dialogRef = this.dialog.open(ReceivePaymentComponent, {
|
const dialogRef = this.dialog.open(ReceivePaymentComponent, {
|
||||||
// width: '750px',
|
// width: '750px',
|
||||||
data: {
|
data: {
|
||||||
@ -149,7 +149,7 @@ export class SalesHomeComponent implements OnInit {
|
|||||||
this.router.navigate(['/sales']);
|
this.router.navigate(['/sales']);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
moveTable() {
|
moveTable() {
|
||||||
@ -164,14 +164,14 @@ export class SalesHomeComponent implements OnInit {
|
|||||||
if (!!x) {
|
if (!!x) {
|
||||||
return this.confirmMoveTableDialog(x as Table);
|
return this.confirmMoveTableDialog(x as Table);
|
||||||
} else {
|
} else {
|
||||||
return throwError("Please choose a table");
|
return throwError('Please choose a table');
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
switchMap((value: { table: Table, confirmed: boolean }, index: number) => {
|
switchMap((value: { table: Table, confirmed: boolean }, index: number) => {
|
||||||
if (!!value.confirmed) {
|
if (!!value.confirmed) {
|
||||||
return this.bs.moveTable(value.table)
|
return this.bs.moveTable(value.table);
|
||||||
} else {
|
} else {
|
||||||
return throwError("Please confirm move")
|
return throwError('Please confirm move');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -180,8 +180,8 @@ export class SalesHomeComponent implements OnInit {
|
|||||||
this.router.navigate(['/sales']);
|
this.router.navigate(['/sales']);
|
||||||
},
|
},
|
||||||
x => {
|
x => {
|
||||||
this.toaster.show('Error', x)
|
this.toaster.show('Error', x);
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
voidBill() {
|
voidBill() {
|
||||||
@ -192,14 +192,14 @@ export class SalesHomeComponent implements OnInit {
|
|||||||
if (!!x) {
|
if (!!x) {
|
||||||
return this.confirmVoidDialog(x as string);
|
return this.confirmVoidDialog(x as string);
|
||||||
} else {
|
} else {
|
||||||
return throwError("Please choose a reason to void the bill");
|
return throwError('Please choose a reason to void the bill');
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
switchMap((x: boolean | string) => {
|
switchMap((x: boolean | string) => {
|
||||||
if (!!x) {
|
if (!!x) {
|
||||||
return this.bs.voidBill(x as string)
|
return this.bs.voidBill(x as string);
|
||||||
} else {
|
} else {
|
||||||
return throwError("You chose not to void the bill")
|
return throwError('You chose not to void the bill');
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
).subscribe((x) => {
|
).subscribe((x) => {
|
||||||
@ -207,7 +207,7 @@ export class SalesHomeComponent implements OnInit {
|
|||||||
this.router.navigate(['/sales']);
|
this.router.navigate(['/sales']);
|
||||||
},
|
},
|
||||||
x => {
|
x => {
|
||||||
this.toaster.show('Error', x)
|
this.toaster.show('Error', x);
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,3 +23,8 @@
|
|||||||
background-color: #d32f2f;
|
background-color: #d32f2f;
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.grey800 {
|
||||||
|
background-color: #424242;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
<mat-card>
|
<mat-card>
|
||||||
<mat-card-content fxLayout="row wrap" fxLayoutGap="grid 20px">
|
<mat-card-content fxLayout="row wrap" fxLayoutGap="grid 20px">
|
||||||
<mat-card fxLayout="column" class="square-button" matRipple *ngFor="let item of list" (click)="addProduct(item)" [class.yellow300]="item.hasHappyHour">
|
<mat-card fxLayout="column" class="square-button" matRipple *ngFor="let item of list" (click)="addProduct(item)"
|
||||||
|
[class.yellow300]="item.hasHappyHour" [class.grey800]="item.isNotAvailable">
|
||||||
<h3 class="item-name">{{item.name}}</h3>
|
<h3 class="item-name">{{item.name}}</h3>
|
||||||
</mat-card>
|
</mat-card>
|
||||||
<mat-card fxLayout="column" class="square-button red700" matRipple [routerLink]="['../../menu-categories']"
|
<mat-card fxLayout="column" class="square-button red700" matRipple [routerLink]="['../../menu-categories']"
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
import { Component, Inject } from '@angular/core';
|
import { Component, Inject } from '@angular/core';
|
||||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material';
|
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material';
|
||||||
import { FormArray, FormBuilder, FormGroup } from "@angular/forms";
|
import { FormArray, FormBuilder, FormGroup } from '@angular/forms';
|
||||||
import { distinctUntilChanged } from "rxjs/operators";
|
import { distinctUntilChanged } from 'rxjs/operators';
|
||||||
import { ReceivePaymentDatasource } from "./receive-payment-datasource";
|
import { ReceivePaymentDatasource } from './receive-payment-datasource';
|
||||||
import { PrintType } from "../bills/bill";
|
import { PrintType } from '../bills/bill';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-receive-payment',
|
selector: 'app-receive-payment',
|
||||||
@ -15,22 +15,22 @@ export class ReceivePaymentComponent {
|
|||||||
REGULAR_BILL: [
|
REGULAR_BILL: [
|
||||||
{
|
{
|
||||||
id: 2,
|
id: 2,
|
||||||
name: "Cash",
|
name: 'Cash',
|
||||||
amount: 0
|
amount: 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 3,
|
id: 3,
|
||||||
name: "Credit Card",
|
name: 'Credit Card',
|
||||||
amount: 0
|
amount: 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 5,
|
id: 5,
|
||||||
name: "Bill To Company",
|
name: 'Bill To Company',
|
||||||
amount: 0
|
amount: 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 6,
|
id: 6,
|
||||||
name: "Tip",
|
name: 'Tip',
|
||||||
amount: 0
|
amount: 0
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -38,14 +38,14 @@ export class ReceivePaymentComponent {
|
|||||||
NO_CHARGE: [
|
NO_CHARGE: [
|
||||||
{
|
{
|
||||||
id: 4,
|
id: 4,
|
||||||
name: "No Charge",
|
name: 'No Charge',
|
||||||
amount: 0
|
amount: 0
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
STAFF: [
|
STAFF: [
|
||||||
{
|
{
|
||||||
id: 10,
|
id: 10,
|
||||||
name: "Staff Account",
|
name: 'Staff Account',
|
||||||
amount: 0
|
amount: 0
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -71,7 +71,7 @@ export class ReceivePaymentComponent {
|
|||||||
this.choices[this.type].map(
|
this.choices[this.type].map(
|
||||||
x => this.fb.group({
|
x => this.fb.group({
|
||||||
name: [x.name],
|
name: [x.name],
|
||||||
amount: [""]
|
amount: ['']
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
));
|
));
|
||||||
@ -91,7 +91,7 @@ export class ReceivePaymentComponent {
|
|||||||
(z, i) => array.controls[i].valueChanges.pipe(
|
(z, i) => array.controls[i].valueChanges.pipe(
|
||||||
distinctUntilChanged()
|
distinctUntilChanged()
|
||||||
).subscribe(x => {
|
).subscribe(x => {
|
||||||
this.choices[this.type].find(s => s.name == x.name).amount = (x.amount === "" ? 0 : parseInt(x.amount, 10));
|
this.choices[this.type].find(s => s.name == x.name).amount = (x.amount === '' ? 0 : parseInt(x.amount, 10));
|
||||||
this.balance = this.amount - this.choices[this.type].reduce((a, c) => a + c.amount, 0);
|
this.balance = this.amount - this.choices[this.type].reduce((a, c) => a + c.amount, 0);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,9 +1,13 @@
|
|||||||
.running {
|
.running {
|
||||||
background-color: green;
|
/* Red 900 */
|
||||||
|
background-color: #b71c1c;
|
||||||
|
color: #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.printed {
|
.printed {
|
||||||
background-color: firebrick;
|
/* Green 900 */
|
||||||
|
background-color: #1b5e20;
|
||||||
|
color: #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.square-button {
|
.square-button {
|
||||||
|
|||||||
@ -15,7 +15,7 @@ import { MatTableModule } from '@angular/material/table';
|
|||||||
import { MatTabsModule } from '@angular/material/tabs';
|
import { MatTabsModule } from '@angular/material/tabs';
|
||||||
import { FlexLayoutModule } from '@angular/flex-layout';
|
import { FlexLayoutModule } from '@angular/flex-layout';
|
||||||
|
|
||||||
import { SharedModule } from "../shared/shared.module";
|
import { SharedModule } from '../shared/shared.module';
|
||||||
import { SalesRoutingModule } from './sales-routing.module';
|
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 { MenuCategoriesComponent } from './menu-categories/menu-categories.component';
|
||||||
@ -25,11 +25,11 @@ import { BillsComponent } from './bills/bills.component';
|
|||||||
import { SalesHomeComponent } from './home/sales-home.component';
|
import { SalesHomeComponent } from './home/sales-home.component';
|
||||||
import { BillService } from './bill.service';
|
import { BillService } from './bill.service';
|
||||||
import { QuantityComponent } from './quantity/quantity.component';
|
import { QuantityComponent } from './quantity/quantity.component';
|
||||||
import { DiscountComponent } from "./discount/discount.component";
|
import { DiscountComponent } from './discount/discount.component';
|
||||||
import { BillTypeComponent } from "./bill-type/bill-type.component";
|
import { BillTypeComponent } from './bill-type/bill-type.component';
|
||||||
import { ReceivePaymentComponent } from "./receive-payment/receive-payment.component";
|
import { ReceivePaymentComponent } from './receive-payment/receive-payment.component';
|
||||||
import { TablesDialogComponent } from "./tables-dialog/tables-dialog.component";
|
import { TablesDialogComponent } from './tables-dialog/tables-dialog.component';
|
||||||
import { VoidReasonComponent } from "./void-reason/void-reason.component";
|
import { VoidReasonComponent } from './void-reason/void-reason.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
providers: [
|
providers: [
|
||||||
|
|||||||
@ -1,9 +1,13 @@
|
|||||||
.running {
|
.running {
|
||||||
background-color: green;
|
/* Red 900 */
|
||||||
|
background-color: #b71c1c;
|
||||||
|
color: #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.printed {
|
.printed {
|
||||||
background-color: firebrick;
|
/* Green 900 */
|
||||||
|
background-color: #1b5e20;
|
||||||
|
color: #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.square-button {
|
.square-button {
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { Component, Inject } from '@angular/core';
|
import { Component, Inject } from '@angular/core';
|
||||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material';
|
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { Table } from "../../core/table";
|
import { Table } from '../../core/table';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-tables-dialog',
|
selector: 'app-tables-dialog',
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import { MatDialogRef } from '@angular/material';
|
import { MatDialogRef } from '@angular/material';
|
||||||
import { VoidReasonDatasource } from "./void-reason-datasource";
|
import { VoidReasonDatasource } from './void-reason-datasource';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-void-reason',
|
selector: 'app-void-reason',
|
||||||
@ -11,14 +11,14 @@ export class VoidReasonComponent {
|
|||||||
dataSource: VoidReasonDatasource;
|
dataSource: VoidReasonDatasource;
|
||||||
selected: string;
|
selected: string;
|
||||||
reasons = [
|
reasons = [
|
||||||
"Discount",
|
'Discount',
|
||||||
"Printing fault",
|
'Printing fault',
|
||||||
"Item changed",
|
'Item changed',
|
||||||
"Quantity reduced",
|
'Quantity reduced',
|
||||||
"Costing bill for party",
|
'Costing bill for party',
|
||||||
"Cashier mistake",
|
'Cashier mistake',
|
||||||
"Management free sale",
|
'Management free sale',
|
||||||
"Other"
|
'Other'
|
||||||
];
|
];
|
||||||
displayedColumns = ['reason'];
|
displayedColumns = ['reason'];
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user