barker/bookie/src/app/sales/bill.service.ts

242 lines
7.1 KiB
TypeScript

import { Injectable } from '@angular/core';
import { MatDialog } from '@angular/material';
import { BehaviorSubject } from 'rxjs';
import { Observable } from 'rxjs/internal/Observable';
import * as math from 'mathjs';
import { Product } from '../core/product';
import { ModifiersComponent } from './modifiers/modifiers.component';
import { ModifierCategoryService } from '../modifier-categories/modifier-category.service';
import { ModifierCategory } from '../core/modifier-category';
import { Bill, Inventory, Kot, PrintType } from './bills/bill';
import { VoucherService } from './bills/voucher.service';
import { ToasterService } from "../core/toaster.service";
import { tap } from "rxjs/operators";
import { Table } from "../core/table";
import {observableToBeFn} from "rxjs/internal/testing/TestScheduler";
@Injectable()
export class BillService {
public dataObs;
public data;
private bill;
constructor(
private dialog: MatDialog,
private toaster: ToasterService,
private ser: VoucherService,
private modifierCategoryService: ModifierCategoryService
) {
this.data = [];
this.dataObs = new BehaviorSubject<any[]>(this.data);
}
loadData(bill: Bill): void {
this.bill = bill;
const view = this.bill.kots.map(k => {
return [{
isKot: true,
oldKot: true,
info: `Kot: ${k.code} / ${k.date} (${k.user.name}) `
}, ...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} - ${math.round(i.discount * 100, 2)}%`,
price: i.price,
quantity: i.quantity,
discount: i.discount,
taxRate: i.taxRate,
tax: i.tax,
modifiers: i.modifiers
};
})];
});
this.data = view.reduce((a, c) => a.concat(c) , []);
this.data.push({isKot: true, newKot: true, info: '== New Kot =='});
this.dataObs.next(this.data);
}
addProduct(product: Product): void {
const old = this.data.find(
x => !x.isKot && !x.id && x.productId === product.id && x.isHappyHour === product.hasHappyHour
);
if (old !== undefined) {
old.quantity += 1;
} else {
const item = {
isKot: false,
product: product,
productId: product.id,
isHappyHour: product.hasHappyHour,
info: `${product.name} (${product.units}) @ ${product.price} - ${0}%`,
price: product.price,
quantity: 1,
discount: 0,
taxRate: product.saleCategory.tax.rate,
tax: product.saleCategory.tax,
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 (result !== undefined) {
item.modifiers = result;
}
});
}
addOne(item: any): void {
item.quantity += 1;
this.dataObs.next(this.data);
}
quantity(item: any, quantity: number): void {
item.quantity = quantity;
this.dataObs.next(this.data);
}
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);
}
discount(discounts:{id: string, name: string, discount: number}[]): void {
this.data.forEach(x=> {
if (!x.isKot) {
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)}%`;
}
});
this.dataObs.next(this.data);
}
private getKot(): Kot {
return new Kot({
inventories: this.data.filter(x => !x.isKot && !x.isPrinted).map(y => new Inventory({
product: y.product,
quantity: y.quantity,
price: y.price,
isHappyHour: y.isHappyHour,
discount: y.discount,
modifiers: y.modifiers,
taxRate: y.taxRate,
tax: y.tax
}))
});
}
printKot(guest_book_id: string): Observable<Bill> {
let item = JSON.parse(JSON.stringify(this.bill));
let newKot = this.getKot();
if (newKot.inventories.length == 0) {
this.toaster.show('Error', 'Cannot print a blank KOT\nPlease add some products!');
}
item.kots.push(newKot);
return this.ser.saveOrUpdate(item, PrintType.Kot, guest_book_id, true).pipe(
tap(x => console.log(x))
);
}
printBill(guest_book_id: string, printType: PrintType): Observable<Bill> {
let item = JSON.parse(JSON.stringify(this.bill));
item.kots.forEach(k => {
k.inventories.forEach(i => {
i.discount = this.data.find(x => !x.isKot && x.id === i.id).discount;
})
});
item.kots.push(this.getKot());
return this.ser.saveOrUpdate(item, printType, guest_book_id, true).pipe(
tap(x => console.log(x))
);
}
type() {
return this.bill.voucherType;
}
receivePayment(amounts: { id: string; name: string; amount: number }[]): Observable<boolean> {
return this.ser.receivePayment(this.bill.id, amounts, true).pipe(
tap(x => console.log(x))
);
}
moveTable(table: Table): Observable<boolean> {
return this.ser.moveTable(this.bill.id, table);
}
voidBill(reason: string): Observable<boolean> {
return this.ser.voidBill(this.bill.id, reason, true);
}
netAmount() {
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)
, 0)
, 0))
}
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)
, 0)
, 0))
}
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)
, 0)
, 0))
}
amount() {
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) * (1 + c.taxRate))
, 0)
, 0))
}
}