From 85ba7b326ac90c95f88def0e1fa9502b684e5dbf Mon Sep 17 00:00:00 2001 From: Amritanshu Date: Wed, 2 Sep 2026 13:06:34 +0000 Subject: [PATCH] Fix: Edge cases where backend and frontend totals are off and you cannot settle the bill. --- barker/barker/routers/guest_book.py | 4 +-- bookie/src/app/core/auth.interceptor.ts | 45 +++++++++++++---------- bookie/src/app/sales/bill.service.ts | 47 ++++++++++++++++++++----- 3 files changed, 67 insertions(+), 29 deletions(-) diff --git a/barker/barker/routers/guest_book.py b/barker/barker/routers/guest_book.py index 79f7f0e..bd1c341 100644 --- a/barker/barker/routers/guest_book.py +++ b/barker/barker/routers/guest_book.py @@ -121,7 +121,7 @@ def show_list( guest_book: list[schemas.GuestBookListItem] = [] count = 0 for i, item in enumerate(db.execute(list_).scalars().all()): - status = GuestBookType(item.type_.name) if item.status is None else GuestBookType(item.status.status.name) + item_status = GuestBookType(item.type_.name) if item.status is None else GuestBookType(item.status.status.name) if item.type_ != GuestBookType.booking: count += item.pax gbli = schemas.GuestBookListItem( @@ -134,7 +134,7 @@ def show_list( booking_date=item.booking_date, arrival_date=item.arrival_date, last_edit_date=item.last_edit_date, - status=status, + status=item_status, table_id=None if item.status is None else item.status.food_table.id, voucher_id=None if item.status is None else item.status.voucher_id, table_name=None if item.status is None else item.status.food_table.name, diff --git a/bookie/src/app/core/auth.interceptor.ts b/bookie/src/app/core/auth.interceptor.ts index c3cba7a..0cffd1d 100644 --- a/bookie/src/app/core/auth.interceptor.ts +++ b/bookie/src/app/core/auth.interceptor.ts @@ -10,6 +10,11 @@ import { AuthService } from '../auth/auth.service'; import { ConfirmDialogComponent } from '../shared/confirm-dialog/confirm-dialog.component'; export const authInterceptor: HttpInterceptorFn = (req, next) => { + const authService = inject(AuthService); + const snackBar = inject(MatSnackBar); + const dialog = inject(MatDialog); + const router = inject(Router); + return next(req).pipe( catchError((err) => { // We don't want to refresh token for some requests like login or refresh token itself @@ -18,34 +23,36 @@ export const authInterceptor: HttpInterceptorFn = (req, next) => { // We do another check to see if refresh token failed // In this case we want to logout user and to redirect it to login page if (req.url.includes('/refresh')) { - inject(AuthService).logout(); + authService.logout(); } return throwError(() => err); } // If error status is different than 401 we want to skip refresh token // So we check that and throw the error if it's the case if (err.status !== 401) { - const error = err.error.message || err.error.detail || err.statusText; + const error = err.error?.message || err.error?.detail || err.statusText || err; return throwError(() => error); } // auto logout if 401 response returned from api - inject(AuthService).logout(); - inject(MatSnackBar).open('User has been logged out', 'Danger'); - const dialogRef = inject(MatDialog).open(ConfirmDialogComponent, { - width: '250px', - data: { - title: 'Logged out!', - content: - 'You have been logged out.\n' + - 'You can press Cancel to stay on page and login in another tab to resume here, ' + - 'or you can press Ok to navigate to the login page.', - }, - }); - dialogRef.afterClosed().subscribe((result: boolean) => { - if (result) { - inject(Router).navigate(['login']); - } - }); + authService.logout(); + if (dialog.openDialogs.length === 0) { + snackBar.open('User has been logged out', 'Danger'); + const dialogRef = dialog.open(ConfirmDialogComponent, { + width: '350px', + data: { + title: 'Logged out!', + content: + 'You have been logged out.\n' + + 'You can press Cancel to stay on page and login in another tab to resume here, ' + + 'or you can press Ok to navigate to the login page.', + }, + }); + dialogRef.afterClosed().subscribe((result: boolean) => { + if (result) { + router.navigate(['/login']); + } + }); + } return throwError(() => err); }), ); diff --git a/bookie/src/app/sales/bill.service.ts b/bookie/src/app/sales/bill.service.ts index c5b84ba..f3bb5b2 100644 --- a/bookie/src/app/sales/bill.service.ts +++ b/bookie/src/app/sales/bill.service.ts @@ -37,25 +37,36 @@ export class BillService { public grossAmount = computed(() => this.math.halfRoundEven( - this.data().reduce((t, k) => k.inventories.reduce((a, c) => a + c.price * c.quantity, 0) + t, 0), + this.data().reduce( + (t, k) => k.inventories.filter((c) => !c.parentId).reduce((a, c) => a + c.price * c.quantity, 0) + t, + 0, + ), + 2, ), ); public hhAmount = computed(() => this.math.halfRoundEven( this.data().reduce( - (t, k) => k.inventories.reduce((a, c) => a + (c.isHappyHour ? c.price : 0) * c.quantity, 0) + t, + (t, k) => + k.inventories.filter((c) => !c.parentId).reduce((a, c) => a + (c.isHappyHour ? c.price : 0) * c.quantity, 0) + + t, 0, ), + 2, ), ); public discountAmount = computed(() => this.math.halfRoundEven( this.data().reduce( - (t, k) => k.inventories.reduce((a, c) => a + (c.isHappyHour ? 0 : c.price) * c.quantity * c.discount, 0) + t, + (t, k) => + k.inventories + .filter((c) => !c.parentId) + .reduce((a, c) => a + (c.isHappyHour ? 0 : c.price) * c.quantity * c.discount, 0) + t, 0, ), + 2, ), ); @@ -63,16 +74,36 @@ export class BillService { this.math.halfRoundEven( this.data().reduce( (t, k) => - k.inventories.reduce( - (a, c) => a + (c.isHappyHour ? 0 : c.price) * c.quantity * (1 - c.discount) * c.taxRate, - 0, - ) + t, + k.inventories + .filter((c) => !c.parentId) + .reduce((a, c) => a + (c.isHappyHour ? 0 : c.price) * c.quantity * (1 - c.discount) * c.taxRate, 0) + t, 0, ), + 2, + ), + ); + + public amount = computed(() => + this.math.halfRoundEven( + this.data().reduce( + (t, k) => + k.inventories + .filter((c) => !c.parentId) + .reduce( + (a, c) => + a + + this.math.halfRoundEven( + (c.isHappyHour ? 0 : c.price) * c.quantity * (1 - c.discount) * (1 + c.taxRate), + 2, + ), + 0, + ) + t, + 0, + ), + 0, ), ); - public amount = computed(() => this.grossAmount() - this.discountAmount() + this.taxAmount()); public selection = new SelectionModel(true, []); private updateTable = signal(true); private allowDeactivate = signal(false);