From 6c83c74424f2dd86da780ef5e423ce8cfd1ce074 Mon Sep 17 00:00:00 2001 From: tanshu Date: Wed, 16 Dec 2020 22:34:41 +0530 Subject: [PATCH] Chore: In overlord / sale / bill.service now the BillViewItem is just a view item The data is kept as the original bill object and this view generated on every change. It has no sanctity. To deal with the challenges of Selection of items in the bill.component.html created a bill selection item. This is converted to string while checking else the selection model fails. Feature: It now checks if Happy Hour items have equivalent regular items in each kot. Feature: Discount won't apply to happy hour items. Checks for both are both in front end and back end. --- barker/barker/routers/voucher/__init__.py | 16 + barker/barker/routers/voucher/save.py | 12 + barker/barker/routers/voucher/update.py | 13 + bookie/src/app/core/bill-view-item.ts | 20 +- bookie/src/app/sales/bill.service.ts | 310 +++++++++--------- .../app/sales/bills/bill-selection-item.ts | 14 + .../src/app/sales/bills/bills.component.html | 4 +- bookie/src/app/sales/bills/bills.component.ts | 108 ++++-- .../app/sales/home/sales-home.component.ts | 2 +- 9 files changed, 304 insertions(+), 195 deletions(-) create mode 100644 bookie/src/app/sales/bills/bill-selection-item.ts diff --git a/barker/barker/routers/voucher/__init__.py b/barker/barker/routers/voucher/__init__.py index f34e95b..3379d69 100644 --- a/barker/barker/routers/voucher/__init__.py +++ b/barker/barker/routers/voucher/__init__.py @@ -2,6 +2,8 @@ import uuid from typing import List, Optional +import barker.schemas.voucher as schemas + from fastapi import HTTPException, status from sqlalchemy import func from sqlalchemy.orm import Session @@ -116,3 +118,17 @@ def do_update_settlements(voucher: Voucher, others: List[SettleSchema], db: Sess for i in (i for i in voucher.settlements if i.settled not in [x.id_ for x in settlements]): voucher.settlements.remove(i) db.delete(i) + + +def happy_hour_items_balanced(inventories: [schemas.Inventory]): + happy = set((i.product.id_, i.quantity) for i in inventories if i.is_happy_hour) + other = set( + (i.product.id_, i.quantity) for i in inventories if not i.is_happy_hour and (i.product.id_, i.quantity) in happy + ) + return happy == other + + +def happy_hour_has_discount(inventories: [schemas.Inventory]): + happy = set(i.product.id_ for i in inventories if i.is_happy_hour) + offenders = [i for i in inventories if i.product.id_ in happy and i.discount != 0] + return len(offenders) > 0 diff --git a/barker/barker/routers/voucher/save.py b/barker/barker/routers/voucher/save.py index 50db798..35b9e20 100644 --- a/barker/barker/routers/voucher/save.py +++ b/barker/barker/routers/voucher/save.py @@ -24,6 +24,8 @@ from ...routers.voucher import ( get_bill_id, get_guest_book, get_tax, + happy_hour_has_discount, + happy_hour_items_balanced, ) from ...schemas.auth import UserToken @@ -99,6 +101,16 @@ def do_save( for k in data.kots: if not len(k.inventories): continue + if not happy_hour_items_balanced(k.inventories): + raise HTTPException( + status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, + detail="Happy hour products are not balanced.", + ) + if happy_hour_has_discount(k.inventories): + raise HTTPException( + status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, + detail="Discount is not allowed on happy hour products.", + ) code = db.query(func.coalesce(func.max(Kot.code), 0) + 1).scalar() kot = Kot(item.id, code, item.food_table_id, item.date, item.user_id) item.kots.append(kot) diff --git a/barker/barker/routers/voucher/update.py b/barker/barker/routers/voucher/update.py index 2e0b7ec..0e90d85 100644 --- a/barker/barker/routers/voucher/update.py +++ b/barker/barker/routers/voucher/update.py @@ -24,6 +24,8 @@ from ...routers.voucher import ( get_bill_id, get_guest_book, get_tax, + happy_hour_has_discount, + happy_hour_items_balanced, ) from ...schemas.auth import UserToken @@ -87,6 +89,17 @@ def update( i.discount = next( round(inv.discount, 5) for ko in data.kots for inv in ko.inventories if inv.id_ == i.id ) + for k in data.kots: + if happy_hour_has_discount(k.inventories): + raise HTTPException( + status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, + detail="Discount is not allowed on happy hour products.", + ) + if not happy_hour_items_balanced(k.inventories): + raise HTTPException( + status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, + detail="Happy hour products are not balanced.", + ) for k in (k for k in data.kots if k.id_ is None and len(k.inventories) > 0): need_to_print_kot = True code = db.query(func.coalesce(func.max(Kot.code), 0) + 1).scalar() diff --git a/bookie/src/app/core/bill-view-item.ts b/bookie/src/app/core/bill-view-item.ts index 55124d5..9e83e80 100644 --- a/bookie/src/app/core/bill-view-item.ts +++ b/bookie/src/app/core/bill-view-item.ts @@ -4,42 +4,32 @@ import { Tax } from './tax'; export class BillViewItem { id: string | undefined; + kotId: string | undefined; isKot: boolean; info: string; - kotId: string; - product: Product; - productId: string | undefined; + productId: string; isHappyHour: boolean; isPrinted: boolean; - price: number; quantity: number; - discount: number; - taxRate: number; - tax: Tax; modifiers: Modifier[]; public get isOldKot(): boolean { - return this.isKot && this.id !== undefined; + return this.isKot && this.kotId !== undefined; } public get isNewKot(): boolean { - return this.isKot && this.id === undefined; + return this.isKot && this.kotId === undefined; } public constructor(init?: Partial) { this.isKot = true; this.info = ''; this.kotId = ''; - this.product = new Product(); - this.productId = this.product.id; + this.productId = ''; this.isHappyHour = false; this.isPrinted = false; - this.price = 0; this.quantity = 0; - this.discount = 0; - this.taxRate = 0; - this.tax = new Tax(); this.modifiers = []; Object.assign(this, init); } diff --git a/bookie/src/app/sales/bill.service.ts b/bookie/src/app/sales/bill.service.ts index d44e359..717516a 100644 --- a/bookie/src/app/sales/bill.service.ts +++ b/bookie/src/app/sales/bill.service.ts @@ -2,8 +2,9 @@ import { SelectionModel } from '@angular/cdk/collections'; import { Injectable } from '@angular/core'; import { MatDialog } from '@angular/material/dialog'; import { round } from 'mathjs'; -import { BehaviorSubject } from 'rxjs'; +import { BehaviorSubject, throwError } from 'rxjs'; import { Observable } from 'rxjs/internal/Observable'; +import { tap } from 'rxjs/operators'; import { BillViewItem } from '../core/bill-view-item'; import { ModifierCategory } from '../core/modifier-category'; @@ -15,6 +16,7 @@ import { ToasterService } from '../core/toaster.service'; import { ModifierCategoryService } from '../modifier-categories/modifier-category.service'; import { Bill } from './bills/bill'; +import { BillSelectionItem } from './bills/bill-selection-item'; import { Inventory } from './bills/inventory'; import { Kot } from './bills/kot'; import { VoucherType } from './bills/voucher-type'; @@ -24,13 +26,13 @@ import { ModifiersComponent } from './modifiers/modifiers.component'; @Injectable() export class BillService { public dataObs: BehaviorSubject; - public data: BillViewItem[]; public bill: Bill = new Bill(); public netAmount: BehaviorSubject; public discountAmount: BehaviorSubject; public taxAmount: BehaviorSubject; public amount: BehaviorSubject; - public selection = new SelectionModel(true, []); + public amountVal: number; + public selection = new SelectionModel(true, []); constructor( private dialog: MatDialog, @@ -38,59 +40,70 @@ export class BillService { private ser: VoucherService, private modifierCategoryService: ModifierCategoryService, ) { - this.data = []; - this.dataObs = new BehaviorSubject(this.data); + this.dataObs = new BehaviorSubject([]); this.netAmount = new BehaviorSubject(0); this.discountAmount = new BehaviorSubject(0); this.taxAmount = new BehaviorSubject(0); this.amount = new BehaviorSubject(0); + this.amountVal = 0; + this.amount.pipe(tap((x) => (this.amountVal = x))); } - loadData(bill: Bill): void { - this.bill = bill; - const view: BillViewItem[][] = this.bill.kots.map((k: Kot) => [ - new BillViewItem({ - id: k.id, - isKot: true, - info: `Kot: ${k.code} / ${k.date} (${k.user.name}) `, - }), - ...k.inventories.map( - (i) => - new BillViewItem({ - id: i.id, - kotId: k.id, - isKot: false, - product: i.product, - productId: i.product.id, - isHappyHour: i.isHappyHour, - isPrinted: true, - info: `${i.product.name} @ ${i.price} - ${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(new BillViewItem({ isKot: true, info: '== New Kot ==' })); - this.dataObs.next(this.data); + displayBill(): void { + const data = this.transformBillToView(this.bill); + this.dataObs.next(data); this.updateAmounts(); } + transformBillToView(bill: Bill): BillViewItem[] { + const view: BillViewItem[] = bill.kots + .map((k: Kot) => [ + new BillViewItem({ + kotId: k.id, + isKot: true, + info: k.id ? `Kot: ${k.code} / ${k.date} (${k.user.name})` : '== New Kot ==', + }), + ...k.inventories.map( + (i) => + new BillViewItem({ + id: i.id, + kotId: k.id, + isKot: false, + productId: i.product.id, + isHappyHour: i.isHappyHour, + isPrinted: !!k.id, + info: `${i.product.name} @ ${i.price} - ${round(i.discount * 100, 2)}%`, + quantity: i.quantity, + modifiers: i.modifiers, + }), + ), + ]) + .reduce((a, c) => a.concat(c), []); + return view; + } + + loadData(bill: Bill): void { + bill.kots.push(new Kot()); + this.bill = bill; + this.displayBill(); + } + minimum(productId: string, happyHour: boolean): number { - return this.data.reduce( - (a, c) => (c.productId === productId && c.isHappyHour === happyHour ? a + c.quantity : a), + return this.bill.kots.reduce( + (t, k) => + k.inventories.reduce( + (a, c) => + c.product.id === productId && c.isHappyHour === happyHour ? a + c.quantity : a, + 0, + ) + t, 0, ); } addProduct(product: Product, quantity: number, discount: number): void { - const old = this.data.find( - (x) => - !x.isKot && !x.id && x.productId === product.id && x.isHappyHour === product.hasHappyHour, + const newKot = this.bill.kots.find((k) => k.id === undefined) as Kot; + const old = newKot.inventories.find( + (x) => x.product.id === product.id && x.isHappyHour === product.hasHappyHour, ); if (quantity < 0) { const minimum = this.minimum(product.id as string, product.hasHappyHour) + quantity; @@ -102,38 +115,34 @@ export class BillService { if (old !== undefined) { old.quantity += quantity; } else { - const item = new BillViewItem({ - isKot: false, + const item = new Inventory({ product, - productId: product.id, - isHappyHour: product.hasHappyHour, - info: `${product.name} @ ${product.price} - ${0}%`, - price: product.price, quantity, - discount, + price: product.price, + isHappyHour: product.hasHappyHour, taxRate: product.tax.rate, tax: product.tax, + discount, modifiers: [], }); - this.data.push(item); + newKot.inventories.push(item); this.modifierCategoryService.listForProduct(product.id as string).subscribe((result) => { if (result.reduce((a: number, c: ModifierCategory) => a + c.minimum, 0)) { this.showModifier(item); } }); } - this.dataObs.next(this.data); - this.updateAmounts(); + this.displayBill(); } - showModifier(item: BillViewItem): void { + showModifier(item: Inventory): void { // [routerLink]="['/sales', 'modifiers', item.id]" const dialogRef = this.dialog.open(ModifiersComponent, { position: { top: '10vh', }, data: { - list: this.modifierCategoryService.listForProduct(item.productId as string), + list: this.modifierCategoryService.listForProduct(item.product.id as string), selected: item.modifiers, }, }); @@ -143,75 +152,99 @@ export class BillService { item.modifiers = result; } }); + this.displayBill(); } addOne(item: BillViewItem): void { - item.quantity += 1; - this.dataObs.next(this.data); - this.updateAmounts(); + const newKot = this.bill.kots.find((k) => k.id === undefined) as Kot; + const old = newKot.inventories.find( + (x) => x.product.id === item.productId && x.isHappyHour === item.isHappyHour, + ) as Inventory; + old.quantity += 1; + this.displayBill(); } quantity(item: BillViewItem, quantity: number): void { - item.quantity = quantity; - this.dataObs.next(this.data); - this.updateAmounts(); + const newKot = this.bill.kots.find((k) => k.id === undefined) as Kot; + const old = newKot.inventories.find( + (x) => x.product.id === item.productId && x.isHappyHour === item.isHappyHour, + ) as Inventory; + old.quantity = quantity; + this.displayBill(); } subtractOne(item: BillViewItem, canEdit: boolean): void { + const newKot = this.bill.kots.find((k) => k.id === undefined) as Kot; + const old = newKot.inventories.find( + (x) => x.product.id === item.productId && x.isHappyHour === item.isHappyHour, + ) as Inventory; if ( item.quantity > 1 || (canEdit && this.minimum(item.productId as string, item.isHappyHour) >= 1) ) { - item.quantity -= 1; - this.dataObs.next(this.data); - this.updateAmounts(); + old.quantity -= 1; } else if (item.quantity === 0) { - this.removeItem(item); + newKot.inventories.splice(newKot.inventories.indexOf(old), 1); } + this.displayBill(); } removeItem(item: BillViewItem): void { - this.data.splice(this.data.indexOf(item), 1); - this.dataObs.next(this.data); - this.updateAmounts(); + const newKot = this.bill.kots.find((k) => k.id === undefined) as Kot; + const old = newKot.inventories.find( + (x) => x.product.id === item.productId && x.isHappyHour === item.isHappyHour, + ) as Inventory; + newKot.inventories.splice(newKot.inventories.indexOf(old), 1); + this.displayBill(); } modifier(item: BillViewItem): void { - this.showModifier(item); + const newKot = this.bill.kots.find((k) => k.id === undefined) as Kot; + const old = newKot.inventories.find( + (x) => x.product.id === item.productId && x.isHappyHour === item.isHappyHour, + ) as Inventory; + this.showModifier(old); } discount(discounts: { id: string; name: string; discount: number }[]): void { - this.data.forEach((x) => { - if (!x.isKot) { - const e = discounts.find((d) => d.id === (x.product.saleCategory as SaleCategory).id); - if (e !== undefined) { - x.discount = e.discount; - x.info = `${x.product.name} @ ${x.price} - ${round(x.discount * 100, 2)}%`; + for (const kot of this.bill.kots) { + const noDiscount = kot.inventories + .filter((x) => x.isHappyHour) + .map((x) => x.product.id as string); + for (const inventory of kot.inventories) { + const e = discounts.find( + (d) => d.id === (inventory.product.saleCategory as SaleCategory).id, + ); + if (e === undefined || noDiscount.indexOf(inventory.product.id as string) !== -1) { + continue; } + inventory.discount = e.discount; } - }); - this.dataObs.next(this.data); - this.updateAmounts(); + } + this.displayBill(); } printKot(guestBookId: string | null): Observable { const item = JSON.parse(JSON.stringify(this.bill)); - const newKot = this.getKot(); + const newKot = this.bill.kots.find((k) => k.id === undefined) as Kot; if (newKot.inventories.length === 0) { - this.toaster.show('Error', 'Cannot print a blank KOT\nPlease add some products!'); + return throwError('Cannot print a blank KOT\nPlease add some products!'); + } + if (!this.happyHourItemsBalanced()) { + return throwError('Happy hour products are not balanced.'); } - item.kots.push(newKot); return this.ser.saveOrUpdate(item, VoucherType.Kot, guestBookId, true); } printBill(guest_book_id: string | null, voucherType: VoucherType): Observable { const item = JSON.parse(JSON.stringify(this.bill)); - item.kots.forEach((k: Kot) => { - k.inventories.forEach((i: Inventory) => { - i.discount = (this.data.find((x) => !x.isKot && x.id === i.id) as BillViewItem).discount; - }); - }); - item.kots.push(this.getKot()); + const newKot = this.bill.kots.find((k) => k.id === undefined) as Kot; + if (item.kots.length === 1 && newKot.inventories.length === 0) { + return throwError('Cannot print a blank Bill\nPlease add some products!'); + } + if (!this.happyHourItemsBalanced()) { + return throwError('Happy hour products are not balanced.'); + } return this.ser.saveOrUpdate(item, voucherType, guest_book_id, true); } @@ -246,88 +279,73 @@ export class BillService { updateAmounts() { this.netAmount.next( round( - this.data - .filter((x) => !x.isKot) - .reduce( - (ca: number, c: BillViewItem) => ca + (c.isHappyHour ? 0 : c.price) * c.quantity, - 0, - ), + this.bill.kots.reduce( + (t, k) => + k.inventories.reduce((a, c) => a + (c.isHappyHour ? 0 : c.price) * c.quantity, 0) + t, + 0, + ), ), ); this.discountAmount.next( round( - this.data - .filter((x) => !x.isKot) - .reduce( - (ca: number, c: BillViewItem) => - ca + (c.isHappyHour ? 0 : c.price) * c.quantity * c.discount, - 0, - ), + this.bill.kots.reduce( + (t, k) => + k.inventories.reduce( + (a, c) => a + (c.isHappyHour ? 0 : c.price) * c.quantity * c.discount, + 0, + ) + t, + 0, + ), ), ); this.taxAmount.next( round( - this.data - .filter((x) => !x.isKot) - .reduce( - (ca: number, c: BillViewItem) => - ca + (c.isHappyHour ? 0 : c.price) * c.quantity * (1 - c.discount) * c.taxRate, - 0, - ), + this.bill.kots.reduce( + (t, k) => + k.inventories.reduce( + (a, c) => + a + (c.isHappyHour ? 0 : c.price) * c.quantity * (1 - c.discount) * c.taxRate, + 0, + ) + t, + 0, + ), ), ); this.amount.next( round( - this.data - .filter((x) => !x.isKot) - .reduce( - (ca: number, c: BillViewItem) => - ca + (c.isHappyHour ? 0 : c.price) * c.quantity * (1 - c.discount) * (1 + c.taxRate), - 0, - ), - ), - ); - } - - amountVal(): number { - return 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, + this.bill.kots.reduce( + (t, k) => + k.inventories.reduce( + (a, c) => + a + (c.isHappyHour ? 0 : c.price) * c.quantity * (1 - c.discount) * (1 + c.taxRate), + 0, + ) + t, + 0, + ), ), ); } splitBill(table: Table): Observable { const inventoriesToMove: string[] = this.selection.selected.map( - (x: BillViewItem) => x.id as string, + (x: string) => (JSON.parse(x) as BillSelectionItem).inventoryId as string, ); return this.ser.splitBill(this.bill.id as string, inventoriesToMove, table); } - 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, - }), - ), - }); + private happyHourItemsBalanced(): boolean { + const newKot = this.bill.kots.find((k) => k.id === undefined) as Kot; + const happyHourItems = newKot.inventories + .filter((x) => x.isHappyHour) + .map((x) => ({ id: x.product.id as string, quantity: x.quantity })); + for (const item of happyHourItems) { + const q = newKot.inventories.find( + (x) => !x.isHappyHour && x.product.id === item.id && x.quantity === item.quantity, + ); + if (q === undefined) { + return false; + } + } + return true; } } diff --git a/bookie/src/app/sales/bills/bill-selection-item.ts b/bookie/src/app/sales/bills/bill-selection-item.ts new file mode 100644 index 0000000..fe1997c --- /dev/null +++ b/bookie/src/app/sales/bills/bill-selection-item.ts @@ -0,0 +1,14 @@ +export class BillSelectionItem { + kotId?: string; + inventoryId?: string; + productId: string; + isHappyHour: boolean; + + public constructor(init?: Partial) { + this.kotId = undefined; + this.inventoryId = undefined; + this.productId = ''; + this.isHappyHour = false; + Object.assign(this, init); + } +} diff --git a/bookie/src/app/sales/bills/bills.component.html b/bookie/src/app/sales/bills/bills.component.html index 8137a21..713998f 100644 --- a/bookie/src/app/sales/bills/bills.component.html +++ b/bookie/src/app/sales/bills/bills.component.html @@ -62,8 +62,8 @@ *ngIf="!row.isKot" [disabled]="!row.id" (click)="$event.stopPropagation()" - (change)="$event ? bs.selection.toggle(row) : null" - [checked]="bs.selection.isSelected(row)" + (change)="$event ? toggle(row) : null" + [checked]="isSelected(row)" > diff --git a/bookie/src/app/sales/bills/bills.component.ts b/bookie/src/app/sales/bills/bills.component.ts index 87f97aa..776d1b4 100644 --- a/bookie/src/app/sales/bills/bills.component.ts +++ b/bookie/src/app/sales/bills/bills.component.ts @@ -16,7 +16,9 @@ import { QuantityComponent } from '../quantity/quantity.component'; import { TablesDialogComponent } from '../tables-dialog/tables-dialog.component'; import { Bill } from './bill'; +import { BillSelectionItem } from './bill-selection-item'; import { BillsDataSource } from './bills-datasource'; +import { Inventory } from './inventory'; import { Kot } from './kot'; import { VoucherType } from './voucher-type'; @@ -66,33 +68,88 @@ export class BillsComponent implements OnInit { }); } - isAllSelected(kot: Kot) { - return this.bs.data - .filter((x) => x.kotId === kot.id) - .reduce((p: boolean, c: BillViewItem) => p && this.bs.selection.isSelected(c), true); + isAllSelected(kotView: BillViewItem): boolean { + const kot = this.bs.bill.kots.find((k) => k.id === kotView.kotId) as Kot; + return kot.inventories.reduce( + (p: boolean, c: Inventory) => + p && + this.bs.selection.isSelected( + JSON.stringify( + new BillSelectionItem({ + kotId: kot.id, + inventoryId: c.id, + productId: c.product.id, + isHappyHour: c.isHappyHour, + }), + ), + ), + true, + ); } - isAnySelected(kot: Kot) { + toggle(invView: BillViewItem) { + const key = JSON.stringify( + new BillSelectionItem({ + kotId: invView.kotId, + inventoryId: invView.id, + productId: invView.productId, + isHappyHour: invView.isHappyHour, + }), + ); + this.bs.selection.toggle(key); + } + + isSelected(invView: BillViewItem): boolean { + const key = JSON.stringify( + new BillSelectionItem({ + kotId: invView.kotId, + inventoryId: invView.id, + productId: invView.productId, + isHappyHour: invView.isHappyHour, + }), + ); + return this.bs.selection.isSelected(key); + } + + isAnySelected(kotView: BillViewItem) { + const kot = this.bs.bill.kots.find((k) => k.id === kotView.kotId) as Kot; let total = 0; let found = 0; - this.bs.data - .filter((x) => x.kotId === kot.id) - .forEach((c: BillViewItem) => { - total += 1; - if (this.bs.selection.isSelected(c)) { - found += 1; - } - }); + for (const item of kot.inventories) { + const key = JSON.stringify( + new BillSelectionItem({ + kotId: kot.id, + inventoryId: item.id, + productId: item.product.id, + isHappyHour: item.isHappyHour, + }), + ); + total += 1; + if (this.bs.selection.isSelected(key)) { + found += 1; + } + } return found > 0 && found < total; } - masterToggle(kot: Kot) { - const isAllSelected = this.isAllSelected(kot); - this.bs.data - .filter((x) => x.kotId === kot.id) - .forEach((row) => - isAllSelected ? this.bs.selection.deselect(row) : this.bs.selection.select(row), + masterToggle(kotView: BillViewItem) { + const isAllSelected = this.isAllSelected(kotView); + const kot = this.bs.bill.kots.find((k) => k.id === kotView.kotId) as Kot; + for (const item of kot.inventories) { + const key = JSON.stringify( + new BillSelectionItem({ + kotId: kot.id, + inventoryId: item.id, + productId: item.product.id, + isHappyHour: item.isHappyHour, + }), ); + if (isAllSelected) { + this.bs.selection.deselect(key); + } else { + this.bs.selection.select(key); + } + } } addOne(item: BillViewItem): void { @@ -109,18 +166,7 @@ export class BillsComponent implements OnInit { if (!result) { return; } - if (!item.isPrinted) { - this.bs.quantity(item, result as number); - } else { - const quantity = result as number; - const product = { - ...item.product, - hasHappyHour: item.isHappyHour, - tax: item.tax, - price: item.price, - }; - this.bs.addProduct(product, quantity, item.discount); - } + this.bs.quantity(item, result as number); }); } diff --git a/bookie/src/app/sales/home/sales-home.component.ts b/bookie/src/app/sales/home/sales-home.component.ts index 3c68b3d..d634f79 100644 --- a/bookie/src/app/sales/home/sales-home.component.ts +++ b/bookie/src/app/sales/home/sales-home.component.ts @@ -191,7 +191,7 @@ export class SalesHomeComponent { if (!this.receivePaymentAllowed()) { return; } - const amount = this.bs.amountVal(); + const amount = this.bs.amountVal; const type = this.bs.type(); this.dialog .open(ReceivePaymentComponent, {