diff --git a/barker/barker/routers/modifier_category.py b/barker/barker/routers/modifier_category.py index 2c4e46f..18ef656 100644 --- a/barker/barker/routers/modifier_category.py +++ b/barker/barker/routers/modifier_category.py @@ -2,7 +2,7 @@ import uuid from datetime import date, datetime, timedelta from functools import reduce -from typing import List, Optional +from typing import List import barker.schemas.master as schemas @@ -41,9 +41,10 @@ def effective_date(d: str = None) -> date: @router.post("", response_model=schemas.ModifierCategory) def save( data: schemas.ModifierCategoryIn, + date_: date = Depends(effective_date), db: Session = Depends(get_db), user: UserToken = Security(get_user, scopes=["modifiers"]), -): +) -> schemas.ModifierCategory: try: item = ModifierCategory( name=data.name, @@ -54,7 +55,7 @@ def save( db.add(item) add_products(item, data.menu_categories, db) db.commit() - return modifier_category_info(item, db=db) + return modifier_category_info(item, date_, db=db) except SQLAlchemyError as e: db.rollback() raise HTTPException( @@ -73,7 +74,7 @@ def update( date_: date = Depends(effective_date), db: Session = Depends(get_db), user: UserToken = Security(get_user, scopes=["modifiers"]), -): +) -> schemas.ModifierCategory: try: item: ModifierCategory = db.query(ModifierCategory).filter(ModifierCategory.id == id_).first() item.name = data.name @@ -94,17 +95,18 @@ def update( raise -@router.delete("/{id_}") +@router.delete("/{id_}", response_model=schemas.ModifierCategoryIn) def delete( id_: uuid.UUID, + date_: date = Depends(effective_date), db: Session = Depends(get_db), user: UserToken = Security(get_user, scopes=["modifiers"]), -): +) -> schemas.ModifierCategoryIn: try: item: ModifierCategory = db.query(ModifierCategory).filter(ModifierCategory.id == id_).first() db.delete(item) db.commit() - return modifier_category_info(None, db=db) + return modifier_category_blank(date_, db=db) except SQLAlchemyError as e: db.rollback() raise HTTPException( @@ -116,12 +118,13 @@ def delete( raise -@router.get("") +@router.get("", response_model=schemas.ModifierCategoryIn) def show_blank( db: Session = Depends(get_db), + date_: date = Depends(effective_date), user: UserToken = Security(get_user, scopes=["modifiers"]), -): - return modifier_category_info(None, db=db) +) -> schemas.ModifierCategoryIn: + return modifier_category_info(date_, db=db) @router.get("/list") @@ -178,6 +181,7 @@ def show_list( @router.get("/for-product/{id_}") def for_product( id_: uuid.UUID, + date_: date = Depends(effective_date), db: Session = Depends(get_db), user: UserToken = Security(get_user), ): @@ -201,18 +205,18 @@ def for_product( ] -@router.get("/{id_}") +@router.get("/{id_}", response_model=schemas.ModifierCategory) def show_id( id_: uuid.UUID, date_: date = Depends(effective_date), db: Session = Depends(get_db), user: UserToken = Security(get_user, scopes=["modifiers"]), -): +) -> schemas.ModifierCategory: item: ModifierCategory = db.query(ModifierCategory).filter(ModifierCategory.id == id_).first() return modifier_category_info(item, date_, db=db) -def modifier_category_info(item: Optional[ModifierCategory], date_: date, db: Session): +def modifier_category_info(item: ModifierCategory, date_: date, db: Session) -> schemas.ModifierCategory: menu_categories = ( db.query(MenuCategory) .join(MenuCategory.products) @@ -235,48 +239,71 @@ def modifier_category_info(item: Optional[ModifierCategory], date_: date, db: Se ) .all() ) - if item is None: - return { - "name": "", - "minimum": 0, - "maximum": 0, - "isActive": True, - "menuCategories": [ - { - "id": mc.id, - "name": mc.name, - "enabled": False, - "products": [{"id": p.id, "name": p.name, "enabled": False} for p in mc.products], - } - for mc in menu_categories - ], - "sortOrder": item.sort_order, - } products = [p.id for p in item.products] - return { - "id": item.id, - "name": item.name, - "minimum": item.minimum, - "maximum": item.maximum, - "isActive": item.is_active, - "menuCategories": [ - { - "id": mc.id, - "name": mc.name, - "enabled": False, - "products": [ - { - "id": p.id, - "name": p.name, - "enabled": True if p.product_id in products else False, - } + return schemas.ModifierCategory( + id=item.id, + name=item.name, + minimum=item.minimum, + maximum=item.maximum, + isActive=item.is_active, + menuCategories=[ + schemas.MenuCategoryLink( + id=mc.id, + name=mc.name, + enabled=False, + products=[ + schemas.ProductLink( + id=p.id, + name=p.name, + enabled=True if p.product_id in products else False, + ) for p in mc.products ], - } + ) for mc in menu_categories ], - "sortOrder": item.sort_order, - } + sortOrder=item.sort_order, + ) + + +def modifier_category_blank(date_: date, db: Session) -> schemas.ModifierCategoryIn: + menu_categories = ( + db.query(MenuCategory) + .join(MenuCategory.products) + .filter( + and_( + or_( + ProductVersion.valid_from == None, # noqa: E711 + ProductVersion.valid_from <= date_, + ), + or_( + ProductVersion.valid_till == None, # noqa: E711 + ProductVersion.valid_till >= date_, + ), + ) + ) + .order_by(MenuCategory.sort_order, ProductVersion.sort_order, ProductVersion.name) + .options( + joinedload(MenuCategory.products, innerjoin=True), + contains_eager(MenuCategory.products), + ) + .all() + ) + return schemas.ModifierCategoryIn( + name="", + minimum=0, + maximum=0, + isActive=True, + menuCategories=[ + schemas.MenuCategoryLink( + id=mc.id, + name=mc.name, + enabled=False, + products=[schemas.ProductLink(id=p.id, name=p.name, enabled=False) for p in mc.products], + ) + for mc in menu_categories + ], + ) def add_products(modifier_category: ModifierCategory, menu_categories: List[schemas.MenuCategoryLink], db: Session): diff --git a/bookie/.eslintrc.js b/bookie/.eslintrc.js index 0bbf8cb..fe395d1 100644 --- a/bookie/.eslintrc.js +++ b/bookie/.eslintrc.js @@ -38,6 +38,6 @@ module.exports = { "@typescript-eslint/lines-between-class-members": ["error", "always", { "exceptAfterSingleLine": true }], "class-methods-use-this": ["error", {"exceptMethods": ["disconnect", "displayFn", "transform"]}], "import/order": ["error", {"alphabetize": {"order": "asc", "caseInsensitive": true}, "newlines-between": "always"}], - "@typescript-eslint/no-explicit-any": "off", // Disabled for now, but needed to transition to strict compiling + "@typescript-eslint/no-explicit-any": "error", } }; diff --git a/bookie/src/app/auth/auth.service.ts b/bookie/src/app/auth/auth.service.ts index 87347ca..8af38bb 100644 --- a/bookie/src/app/auth/auth.service.ts +++ b/bookie/src/app/auth/auth.service.ts @@ -89,7 +89,7 @@ export class AuthService { formData.append('otp', otp); formData.append('grant_type', 'password'); return this.http - .post(loginUrl, formData) + .post<{ access_token: string; token_type: string }>(loginUrl, formData) .pipe(map((u) => u.access_token)) .pipe(map((u) => AuthService.parseJwt(u))) .pipe( @@ -118,7 +118,7 @@ export class AuthService { refreshToken() { return this.http - .post(refreshUrl, {}) + .post<{ access_token: string; token_type: string }>(refreshUrl, {}) .pipe(map((u) => u.access_token)) .pipe(map((u) => AuthService.parseJwt(u))) .pipe( diff --git a/bookie/src/app/cashier-report/cashier-report.component.ts b/bookie/src/app/cashier-report/cashier-report.component.ts index ddb110c..a9e82f7 100644 --- a/bookie/src/app/cashier-report/cashier-report.component.ts +++ b/bookie/src/app/cashier-report/cashier-report.component.ts @@ -70,14 +70,16 @@ export class CashierReportComponent implements OnInit { } print() { - this.ser.print(this.info.cashier.id as string, this.info.startDate, this.info.finishDate).subscribe( - () => { - this.toaster.show('', 'Successfully Printed'); - }, - (error) => { - this.toaster.show('Error', error.error); - }, - ); + this.ser + .print(this.info.cashier.id as string, this.info.startDate, this.info.finishDate) + .subscribe( + () => { + this.toaster.show('', 'Successfully Printed'); + }, + (error) => { + this.toaster.show('Error', error.error); + }, + ); } getInfo(): CashierReport { diff --git a/bookie/src/app/core/bill-view-item.ts b/bookie/src/app/core/bill-view-item.ts index dc3bb0d..55124d5 100644 --- a/bookie/src/app/core/bill-view-item.ts +++ b/bookie/src/app/core/bill-view-item.ts @@ -3,9 +3,8 @@ import { Product } from './product'; import { Tax } from './tax'; export class BillViewItem { - id: string; + id: string | undefined; isKot: boolean; - oldKot: boolean; info: string; kotId: string; @@ -20,10 +19,16 @@ export class BillViewItem { tax: Tax; modifiers: Modifier[]; + public get isOldKot(): boolean { + return this.isKot && this.id !== undefined; + } + + public get isNewKot(): boolean { + return this.isKot && this.id === undefined; + } + public constructor(init?: Partial) { - this.id = ''; this.isKot = true; - this.oldKot = false; this.info = ''; this.kotId = ''; this.product = new Product(); diff --git a/bookie/src/app/core/error-logger.service.ts b/bookie/src/app/core/error-logger.service.ts index 5cf63a6..3d875cf 100644 --- a/bookie/src/app/core/error-logger.service.ts +++ b/bookie/src/app/core/error-logger.service.ts @@ -19,7 +19,7 @@ export class ErrorLoggerService { */ // eslint-disable-next-line @typescript-eslint/no-unused-vars, class-methods-use-this public handleError(serviceName = 'error-logger', operation = 'operation', result?: T) { - return (error: any): Observable => { + return (error: unknown): Observable => { ErrorLoggerService.log(serviceName, `${operation} failed: ${error}`); return throwError(error); }; diff --git a/bookie/src/app/core/http-auth-interceptor.ts b/bookie/src/app/core/http-auth-interceptor.ts index 1d1001c..25c2b4b 100644 --- a/bookie/src/app/core/http-auth-interceptor.ts +++ b/bookie/src/app/core/http-auth-interceptor.ts @@ -19,7 +19,7 @@ export class ErrorInterceptor implements HttpInterceptor { private toaster: ToasterService, ) {} - intercept(request: HttpRequest, next: HttpHandler): Observable> { + intercept(request: HttpRequest, next: HttpHandler): Observable> { return next.handle(request).pipe( catchError((err) => { // We don't want to refresh token for some requests like login or refresh token itself diff --git a/bookie/src/app/core/jwt.interceptor.ts b/bookie/src/app/core/jwt.interceptor.ts index 4076b8d..0f4529a 100644 --- a/bookie/src/app/core/jwt.interceptor.ts +++ b/bookie/src/app/core/jwt.interceptor.ts @@ -10,7 +10,7 @@ export class JwtInterceptor implements HttpInterceptor { constructor(private authService: AuthService) {} - intercept(request: HttpRequest, next: HttpHandler): Observable> { + intercept(request: HttpRequest, next: HttpHandler): Observable> { // add authorization header with jwt token if available // We use this line to debug token refreshing diff --git a/bookie/src/app/header-footer/header-footer.component.ts b/bookie/src/app/header-footer/header-footer.component.ts index e92b93c..929f3bb 100644 --- a/bookie/src/app/header-footer/header-footer.component.ts +++ b/bookie/src/app/header-footer/header-footer.component.ts @@ -1,6 +1,7 @@ import { Component, ElementRef, OnInit, ViewChild } from '@angular/core'; import { FormBuilder, FormGroup } from '@angular/forms'; import { MatDialog } from '@angular/material/dialog'; +import { MatSelectChange } from '@angular/material/select'; import { ActivatedRoute, Router } from '@angular/router'; import { map } from 'rxjs/operators'; @@ -74,7 +75,7 @@ export class HeaderFooterComponent implements OnInit { return item; } - show(val: any) { + show(val: MatSelectChange) { this.router.navigate(['/header-footer', val.value]); } } diff --git a/bookie/src/app/modifier-categories/modifier-category-detail/modifier-category-detail.component.ts b/bookie/src/app/modifier-categories/modifier-category-detail/modifier-category-detail.component.ts index 38028b4..b429d87 100644 --- a/bookie/src/app/modifier-categories/modifier-category-detail/modifier-category-detail.component.ts +++ b/bookie/src/app/modifier-categories/modifier-category-detail/modifier-category-detail.component.ts @@ -4,6 +4,7 @@ import { FormBuilder, FormGroup } from '@angular/forms'; import { MatDialog } from '@angular/material/dialog'; import { MatTreeNestedDataSource } from '@angular/material/tree'; import { ActivatedRoute, Router } from '@angular/router'; +import { map } from 'rxjs/operators'; import { MenuCategory } from '../../core/menu-category'; import { ModifierCategory } from '../../core/modifier-category'; @@ -11,6 +12,7 @@ import { Product } from '../../core/product'; import { ToasterService } from '../../core/toaster.service'; import { ConfirmDialogComponent } from '../../shared/confirm-dialog/confirm-dialog.component'; import { ModifierCategoryService } from '../modifier-category.service'; +import { NodeItem } from '../node-item'; @Component({ selector: 'app-role-detail', @@ -21,8 +23,8 @@ export class ModifierCategoryDetailComponent implements OnInit, AfterViewInit { @ViewChild('nameElement', { static: true }) nameElement?: ElementRef; form: FormGroup; item: ModifierCategory = new ModifierCategory(); - treeControl = new NestedTreeControl((node) => node.products); - dataSource = new MatTreeNestedDataSource(); + treeControl = new NestedTreeControl((node: NodeItem) => node.children); + dataSource = new MatTreeNestedDataSource(); products: Map = new Map(); productsOfMenuCategory: Map = new Map(); @@ -45,15 +47,26 @@ export class ModifierCategoryDetailComponent implements OnInit, AfterViewInit { } ngOnInit() { - this.route.data.subscribe((value) => { - const data = value as { item: ModifierCategory }; - this.showItem(data.item); - }); + this.route.data + .pipe( + map((value) => { + const data = value as { item: ModifierCategory }; + const tree: NodeItem[] = data.item.menuCategories.map((x: MenuCategory) => ({ + id: x.id as string, + name: x.name, + children: x.products.map((y: Product) => ({ id: y.id as string, name: y.name })), + })); + return { item: data.item, tree }; + }), + ) + .subscribe((data) => { + this.showItem(data.item, data.tree); + }); } - showItem(item: ModifierCategory) { + showItem(item: ModifierCategory, tree: NodeItem[]) { this.item = item; - this.dataSource.data = item.menuCategories; + this.dataSource.data = tree; this.form.patchValue({ name: this.item.name || '', minimum: `${this.item.minimum}`, @@ -133,22 +146,22 @@ export class ModifierCategoryDetailComponent implements OnInit, AfterViewInit { return this.item; } - hasChild = (_: number, node: any) => !!node.products && node.products.length > 0; + hasChild = (_: number, node: NodeItem) => !!node.children && node.children.length > 0; - isProductSelected(node: Product) { - return (this.products.get(node.id as string) as Product).enabled; + isProductSelected(node: NodeItem) { + return (this.products.get(node.id) as Product).enabled; } - isMenuCategorySelected(node: MenuCategory) { - return (this.productsOfMenuCategory.get(node.id as string) as Product[]).reduce( + isMenuCategorySelected(node: NodeItem) { + return (this.productsOfMenuCategory.get(node.id) as Product[]).reduce( (acc: boolean, current: Product) => acc && current.enabled, true, ); } - isMenuCategoryPartiallySelected(node: MenuCategory) { - const total = (this.productsOfMenuCategory.get(node.id as string) as Product[]).length; - const ticked = (this.productsOfMenuCategory.get(node.id as string) as Product[]).reduce( + isMenuCategoryPartiallySelected(node: NodeItem) { + const total = (this.productsOfMenuCategory.get(node.id) as Product[]).length; + const ticked = (this.productsOfMenuCategory.get(node.id) as Product[]).reduce( (acc, current) => { if (current.enabled) { // eslint-disable-next-line no-param-reassign @@ -161,12 +174,12 @@ export class ModifierCategoryDetailComponent implements OnInit, AfterViewInit { return ticked > 0 && ticked < total; } - toggleProductSelection(node: Product) { - (this.products.get(node.id as string) as Product).enabled = !(this.products.get(node.id as string) as Product) + toggleProductSelection(node: NodeItem) { + (this.products.get(node.id) as Product).enabled = !(this.products.get(node.id) as Product) .enabled; } - toggleMenuCategorySelection(node: MenuCategory) { + toggleMenuCategorySelection(node: NodeItem) { const sel = !this.isMenuCategorySelected(node); (this.productsOfMenuCategory.get(node.id as string) as Product[]).forEach((p) => { p.enabled = sel; diff --git a/bookie/src/app/modifier-categories/node-item.ts b/bookie/src/app/modifier-categories/node-item.ts new file mode 100644 index 0000000..321da4c --- /dev/null +++ b/bookie/src/app/modifier-categories/node-item.ts @@ -0,0 +1,5 @@ +export interface NodeItem { + id: string; + name: string; + children?: NodeItem[]; +} diff --git a/bookie/src/app/modifiers/modifier-list/modifier-list.component.ts b/bookie/src/app/modifiers/modifier-list/modifier-list.component.ts index 1e26f5c..4eb4658 100644 --- a/bookie/src/app/modifiers/modifier-list/modifier-list.component.ts +++ b/bookie/src/app/modifiers/modifier-list/modifier-list.component.ts @@ -1,5 +1,6 @@ import { Component, OnInit, ViewChild } from '@angular/core'; import { FormBuilder, FormGroup } from '@angular/forms'; +import { MatSelectChange } from '@angular/material/select'; import { MatTable } from '@angular/material/table'; import { ActivatedRoute, Router } from '@angular/router'; import { BehaviorSubject } from 'rxjs'; @@ -34,7 +35,7 @@ export class ModifierListComponent implements OnInit { }); } - filterOn(val: any) { + filterOn(val: MatSelectChange) { this.filter.next(val.value); } diff --git a/bookie/src/app/sales/bill-type/bill-type.component.ts b/bookie/src/app/sales/bill-type/bill-type.component.ts index efad905..f21e96d 100644 --- a/bookie/src/app/sales/bill-type/bill-type.component.ts +++ b/bookie/src/app/sales/bill-type/bill-type.component.ts @@ -20,9 +20,9 @@ export class BillTypeComponent { } accept(): void { - if (this.selected === 'REGULAR_BILL') this.dialogRef.close(VoucherType.Bill) - else if (this.selected === 'STAFF') this.dialogRef.close(VoucherType.Staff) - else if (this.selected === 'NO_CHARGE') this.dialogRef.close(VoucherType.NoCharge) + if (this.selected === 'REGULAR_BILL') this.dialogRef.close(VoucherType.Bill); + else if (this.selected === 'STAFF') this.dialogRef.close(VoucherType.Staff); + else if (this.selected === 'NO_CHARGE') this.dialogRef.close(VoucherType.NoCharge); else this.dialogRef.close(); } } diff --git a/bookie/src/app/sales/bill.service.ts b/bookie/src/app/sales/bill.service.ts index 22890d5..d34efa9 100644 --- a/bookie/src/app/sales/bill.service.ts +++ b/bookie/src/app/sales/bill.service.ts @@ -21,14 +21,14 @@ import { ModifiersComponent } from './modifiers/modifiers.component'; @Injectable() export class BillService { - public dataObs; - public data: any[]; + 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 selection = new SelectionModel(true, []); constructor( private dialog: MatDialog, @@ -37,7 +37,7 @@ export class BillService { private modifierCategoryService: ModifierCategoryService, ) { this.data = []; - this.dataObs = new BehaviorSubject(this.data); + this.dataObs = new BehaviorSubject(this.data); this.netAmount = new BehaviorSubject(0); this.discountAmount = new BehaviorSubject(0); this.taxAmount = new BehaviorSubject(0); @@ -50,7 +50,6 @@ export class BillService { new BillViewItem({ id: k.id, isKot: true, - oldKot: true, info: `Kot: ${k.code} / ${k.date} (${k.user.name}) `, }), ...k.inventories.map( @@ -74,7 +73,7 @@ export class BillService { ), ]); this.data = view.reduce((a, c) => a.concat(c), []); - this.data.push({ isKot: true, newKot: true, info: '== New Kot ==' }); + this.data.push(new BillViewItem({ isKot: true, info: '== New Kot ==' })); this.dataObs.next(this.data); this.updateAmounts(); } @@ -101,7 +100,7 @@ export class BillService { if (old !== undefined) { old.quantity += quantity; } else { - const item = { + const item = new BillViewItem({ isKot: false, product, productId: product.id, @@ -113,11 +112,11 @@ export class BillService { taxRate: product.tax.rate, tax: product.tax, modifiers: [], - }; + }); this.data.push(item); this.modifierCategoryService.listForProduct(product.id as string).subscribe((result) => { if ( - result.reduce((a: any, c: ModifierCategory) => { + result.reduce((a: number, c: ModifierCategory) => { return a + c.minimum; }, 0) ) { @@ -129,14 +128,14 @@ export class BillService { this.updateAmounts(); } - showModifier(item: any): void { + showModifier(item: BillViewItem): void { // [routerLink]="['/sales', 'modifiers', item.id]" const dialogRef = this.dialog.open(ModifiersComponent, { position: { top: '10vh', }, data: { - list: this.modifierCategoryService.listForProduct(item.productId), + list: this.modifierCategoryService.listForProduct(item.productId as string), selected: item.modifiers, }, }); @@ -148,20 +147,23 @@ export class BillService { }); } - addOne(item: any): void { + addOne(item: BillViewItem): void { item.quantity += 1; this.dataObs.next(this.data); this.updateAmounts(); } - quantity(item: any, quantity: number): void { + quantity(item: BillViewItem, quantity: number): void { item.quantity = quantity; this.dataObs.next(this.data); this.updateAmounts(); } - subtractOne(item: any, canEdit: boolean): void { - if (item.quantity > 1 || (canEdit && this.minimum(item.productId, item.isHappyHour) >= 1)) { + subtractOne(item: BillViewItem, canEdit: boolean): void { + if ( + item.quantity > 1 || + (canEdit && this.minimum(item.productId as string, item.isHappyHour) >= 1) + ) { item.quantity -= 1; this.dataObs.next(this.data); this.updateAmounts(); @@ -170,13 +172,13 @@ export class BillService { } } - removeItem(item: any): void { + removeItem(item: BillViewItem): void { this.data.splice(this.data.indexOf(item), 1); this.dataObs.next(this.data); this.updateAmounts(); } - modifier(item: any): void { + modifier(item: BillViewItem): void { this.showModifier(item); } @@ -230,7 +232,7 @@ export class BillService { 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).discount; + i.discount = (this.data.find((x) => !x.isKot && x.id === i.id) as BillViewItem).discount; }); }); item.kots.push(this.getKot()); @@ -273,7 +275,10 @@ export class BillService { math.round( this.data .filter((x) => !x.isKot) - .reduce((ca: number, c: any) => ca + (c.isHappyHour ? 0 : c.price) * c.quantity, 0), + .reduce( + (ca: number, c: BillViewItem) => ca + (c.isHappyHour ? 0 : c.price) * c.quantity, + 0, + ), ), ); this.discountAmount.next( @@ -281,7 +286,7 @@ export class BillService { this.data .filter((x) => !x.isKot) .reduce( - (ca: number, c: Inventory) => + (ca: number, c: BillViewItem) => ca + (c.isHappyHour ? 0 : c.price) * c.quantity * c.discount, 0, ), @@ -292,7 +297,7 @@ export class BillService { this.data .filter((x) => !x.isKot) .reduce( - (ca: number, c: Inventory) => + (ca: number, c: BillViewItem) => ca + (c.isHappyHour ? 0 : c.price) * c.quantity * (1 - c.discount) * c.taxRate, 0, ), @@ -303,7 +308,7 @@ export class BillService { this.data .filter((x) => !x.isKot) .reduce( - (ca: number, c: Inventory) => + (ca: number, c: BillViewItem) => ca + (c.isHappyHour ? 0 : c.price) * c.quantity * (1 - c.discount) * (1 + c.taxRate), 0, ), @@ -327,7 +332,9 @@ export class BillService { } splitBill(table: Table): Observable { - const inventoriesToMove: string[] = this.selection.selected.map((x: any) => x.id); + const inventoriesToMove: string[] = this.selection.selected.map( + (x: BillViewItem) => x.id as string, + ); return this.ser.splitBill(this.bill.id as string, inventoriesToMove, table); } } diff --git a/bookie/src/app/sales/bills/bill.ts b/bookie/src/app/sales/bills/bill.ts index 74a6dda..e6bd2f1 100644 --- a/bookie/src/app/sales/bills/bill.ts +++ b/bookie/src/app/sales/bills/bill.ts @@ -16,12 +16,12 @@ export class Bill { kotId: string; table: Table; guest: GuestBook; - settlements: any[]; + // settlements: any[]; voidReason: string; voucherType: string; serial: number; kots: Kot[]; - reprints: any[]; + // reprints: any[]; get dateTip(): string { return this.date; @@ -46,12 +46,12 @@ export class Bill { this.kotId = ''; this.table = new Table(); this.guest = new GuestBook(); - this.settlements = []; + // this.settlements = []; this.voidReason = ''; this.voucherType = ''; this.serial = 0; this.kots = []; - this.reprints = []; + // this.reprints = []; Object.assign(this, init); } } diff --git a/bookie/src/app/sales/bills/bills-datasource.ts b/bookie/src/app/sales/bills/bills-datasource.ts index 96e1c42..a82066d 100644 --- a/bookie/src/app/sales/bills/bills-datasource.ts +++ b/bookie/src/app/sales/bills/bills-datasource.ts @@ -1,12 +1,14 @@ import { DataSource } from '@angular/cdk/collections'; import { Observable } from 'rxjs'; -export class BillsDataSource extends DataSource { - constructor(private data: Observable) { +import { BillViewItem } from '../../core/bill-view-item'; + +export class BillsDataSource extends DataSource { + constructor(private data: Observable) { super(); } - connect(): Observable { + connect(): Observable { return this.data; } diff --git a/bookie/src/app/sales/bills/bills.component.html b/bookie/src/app/sales/bills/bills.component.html index 5950a16..8137a21 100644 --- a/bookie/src/app/sales/bills/bills.component.html +++ b/bookie/src/app/sales/bills/bills.component.html @@ -52,7 +52,7 @@ - + {{ row.info }} @@ -123,7 +123,12 @@ > assignment - @@ -166,8 +171,8 @@ diff --git a/bookie/src/app/sales/bills/bills.component.ts b/bookie/src/app/sales/bills/bills.component.ts index e356f84..87f97aa 100644 --- a/bookie/src/app/sales/bills/bills.component.ts +++ b/bookie/src/app/sales/bills/bills.component.ts @@ -5,6 +5,7 @@ import { Observable } from 'rxjs'; import { map, switchMap } from 'rxjs/operators'; import { AuthService } from '../../auth/auth.service'; +import { BillViewItem } from '../../core/bill-view-item'; import { Table } from '../../core/table'; import { ToasterService } from '../../core/toaster.service'; import { ConfirmDialogComponent } from '../../shared/confirm-dialog/confirm-dialog.component'; @@ -68,7 +69,7 @@ export class BillsComponent implements OnInit { isAllSelected(kot: Kot) { return this.bs.data .filter((x) => x.kotId === kot.id) - .reduce((p: boolean, c: any) => p && this.bs.selection.isSelected(c), true); + .reduce((p: boolean, c: BillViewItem) => p && this.bs.selection.isSelected(c), true); } isAnySelected(kot: Kot) { @@ -76,7 +77,7 @@ export class BillsComponent implements OnInit { let found = 0; this.bs.data .filter((x) => x.kotId === kot.id) - .forEach((c: any) => { + .forEach((c: BillViewItem) => { total += 1; if (this.bs.selection.isSelected(c)) { found += 1; @@ -94,11 +95,11 @@ export class BillsComponent implements OnInit { ); } - addOne(item: any): void { + addOne(item: BillViewItem): void { this.bs.addOne(item); } - quantity(item: any): void { + quantity(item: BillViewItem): void { const dialogRef = this.dialog.open(QuantityComponent, { // width: '750px', data: item.quantity, @@ -123,16 +124,16 @@ export class BillsComponent implements OnInit { }); } - subtractOne(item: any): void { + subtractOne(item: BillViewItem): void { const canEdit = this.auth.allowed('edit-printed-product'); this.bs.subtractOne(item, canEdit); } - removeItem(item: any): void { + removeItem(item: BillViewItem): void { this.bs.removeItem(item); } - modifier(item: any): void { + modifier(item: BillViewItem): void { this.bs.modifier(item); } @@ -202,7 +203,7 @@ export class BillsComponent implements OnInit { ); } - rowQuantityDisabled(row: any) { + rowQuantityDisabled(row: BillViewItem) { if (!row.isPrinted) { return false; } diff --git a/bookie/src/app/sales/discount/discount.component.ts b/bookie/src/app/sales/discount/discount.component.ts index 8b672ac..1564f57 100644 --- a/bookie/src/app/sales/discount/discount.component.ts +++ b/bookie/src/app/sales/discount/discount.component.ts @@ -11,7 +11,7 @@ import { DiscountDataSource } from './discount-datasource'; styleUrls: ['./discount.component.css'], }) export class DiscountComponent { - list: any[] = []; + list: { name: string; discount: number }[] = []; form: FormGroup; dataSource: DiscountDataSource = new DiscountDataSource([]); @@ -20,12 +20,12 @@ export class DiscountComponent { constructor( public dialogRef: MatDialogRef, private fb: FormBuilder, - @Inject(MAT_DIALOG_DATA) public data: Observable, + @Inject(MAT_DIALOG_DATA) public data: Observable<{ name: string; discount: number }[]>, ) { this.form = this.fb.group({ discounts: '', }); - this.data.subscribe((list: any[]) => { + this.data.subscribe((list: { name: string; discount: number }[]) => { this.list = list; this.form.setControl( 'discounts', diff --git a/bookie/src/app/sales/home/sales-home.component.ts b/bookie/src/app/sales/home/sales-home.component.ts index 5043fc1..84493a0 100644 --- a/bookie/src/app/sales/home/sales-home.component.ts +++ b/bookie/src/app/sales/home/sales-home.component.ts @@ -249,7 +249,7 @@ export class SalesHomeComponent { } const amount = this.bs.amountVal(); const type = this.bs.type(); - let obs: any; + let obs: Observable; if (type === 'NO_CHARGE' || type === 'STAFF') { obs = this.receivePaymentWithReason(type, amount); } else { diff --git a/bookie/src/app/section-printers/section-printer.component.ts b/bookie/src/app/section-printers/section-printer.component.ts index 51d48a4..bc52315 100644 --- a/bookie/src/app/section-printers/section-printer.component.ts +++ b/bookie/src/app/section-printers/section-printer.component.ts @@ -1,6 +1,7 @@ import { Component, ElementRef, OnInit, ViewChild } from '@angular/core'; import { AbstractControl, FormArray, FormBuilder, FormGroup } from '@angular/forms'; import { MatDialog } from '@angular/material/dialog'; +import { MatSelectChange } from '@angular/material/select'; import { ActivatedRoute, Router } from '@angular/router'; import { BehaviorSubject } from 'rxjs'; import { map } from 'rxjs/operators'; @@ -127,7 +128,7 @@ export class SectionPrinterComponent implements OnInit { return this.list; } - show(val: any) { + show(val: MatSelectChange) { this.router.navigate(['/section-printers', val.value]); } } diff --git a/bookie/src/app/shared/clear.pipe.ts b/bookie/src/app/shared/clear.pipe.ts index 0d8ef17..e7403ce 100644 --- a/bookie/src/app/shared/clear.pipe.ts +++ b/bookie/src/app/shared/clear.pipe.ts @@ -4,7 +4,8 @@ import { Pipe, PipeTransform } from '@angular/core'; name: 'clear', }) export class ClearPipe implements PipeTransform { - transform(value: any): any { + transform(value: string | null): string { + if (value === null) return ''; return value === '₹ 0.00' || value === '0.00' ? '' : value; } } diff --git a/bookie/src/app/shared/confirm-dialog/confirm-dialog.component.ts b/bookie/src/app/shared/confirm-dialog/confirm-dialog.component.ts index 437ec3a..a22e1b9 100644 --- a/bookie/src/app/shared/confirm-dialog/confirm-dialog.component.ts +++ b/bookie/src/app/shared/confirm-dialog/confirm-dialog.component.ts @@ -9,6 +9,6 @@ import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; export class ConfirmDialogComponent { constructor( public dialogRef: MatDialogRef, - @Inject(MAT_DIALOG_DATA) public data: any, + @Inject(MAT_DIALOG_DATA) public data: { title: string; content: string }, ) {} } diff --git a/bookie/src/app/shared/image-dialog/image-dialog.component.ts b/bookie/src/app/shared/image-dialog/image-dialog.component.ts index 69efa1d..3878fc2 100644 --- a/bookie/src/app/shared/image-dialog/image-dialog.component.ts +++ b/bookie/src/app/shared/image-dialog/image-dialog.component.ts @@ -9,7 +9,7 @@ import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; export class ImageDialogComponent { constructor( public dialogRef: MatDialogRef, - @Inject(MAT_DIALOG_DATA) public data: any, + @Inject(MAT_DIALOG_DATA) public data: string, ) {} close(): void { diff --git a/bookie/src/app/shared/math.service.ts b/bookie/src/app/shared/math.service.ts index 6ccfc4c..83117e7 100644 --- a/bookie/src/app/shared/math.service.ts +++ b/bookie/src/app/shared/math.service.ts @@ -5,16 +5,6 @@ import { evaluate, round } from 'mathjs'; providedIn: 'root', }) export class MathService { - // eslint-disable-next-line class-methods-use-this - journalAmount(amount: string = '', debit: number): any { - const val = this.parseAmount(amount, 2); - let newDebit = debit; - if (val < 0) { - newDebit *= -1; - } - return { debit: newDebit, amount: Math.abs(val) }; - } - // eslint-disable-next-line class-methods-use-this parseAmount(amount: string = '', rounding: number = 2): number { const cleaned = `${amount}`.replace(new RegExp('(₹[s]*)|(,)|(s)', 'g'), ''); diff --git a/bookie/src/app/shared/to-csv-type.ts b/bookie/src/app/shared/to-csv-type.ts new file mode 100644 index 0000000..87d1981 --- /dev/null +++ b/bookie/src/app/shared/to-csv-type.ts @@ -0,0 +1,3 @@ +export interface ToCsvType { + [column: string]: string | number | boolean | null; +} diff --git a/bookie/src/app/shared/to-csv.service.ts b/bookie/src/app/shared/to-csv.service.ts index 3fcfe65..01654fb 100644 --- a/bookie/src/app/shared/to-csv.service.ts +++ b/bookie/src/app/shared/to-csv.service.ts @@ -1,15 +1,19 @@ import { Injectable } from '@angular/core'; +import { ToCsvType } from './to-csv-type'; + @Injectable({ providedIn: 'root', }) export class ToCsvService { // eslint-disable-next-line class-methods-use-this - toCsv(headers: any, data: any[]): string { + toCsv(headers: { [display: string]: string }, data: unknown[]): string { const header = Object.keys(headers); const replacer = (key: string, value: string | number | null) => (value === null ? '' : value); const csv = data.map((row) => - header.map((fieldName) => JSON.stringify(row[headers[fieldName]], replacer)).join(','), + header + .map((fieldName) => JSON.stringify((row as ToCsvType)[headers[fieldName]], replacer)) + .join(','), ); csv.unshift(header.join(',')); return csv.join('\r\n');