From 669821a64398dbe779282da1644863be7244180b Mon Sep 17 00:00:00 2001 From: tanshu Date: Sat, 20 Mar 2021 08:05:50 +0530 Subject: [PATCH] Using Half-Round-Even rounding in the bill amounts as this is what python round uses. When the bill amounts were Odd number + .5, payment could not be received as javascript rounded it up, but python rounded it down. We are now using the python rounding (Half Round Even / Banker's Rounding) in the bill service. --- bookie/src/app/sales/bill.service.ts | 17 ++++++++++------- bookie/src/app/shared/math.service.ts | 12 +++++++++++- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/bookie/src/app/sales/bill.service.ts b/bookie/src/app/sales/bill.service.ts index 3af4bce..fa5a51b 100644 --- a/bookie/src/app/sales/bill.service.ts +++ b/bookie/src/app/sales/bill.service.ts @@ -1,7 +1,6 @@ import { SelectionModel } from '@angular/cdk/collections'; import { Injectable } from '@angular/core'; import { MatDialog } from '@angular/material/dialog'; -import { round } from 'mathjs'; import { BehaviorSubject, throwError } from 'rxjs'; import { Observable } from 'rxjs/internal/Observable'; import { tap } from 'rxjs/operators'; @@ -14,9 +13,9 @@ import { SaleCategory } from '../core/sale-category'; import { Table } from '../core/table'; import { ToasterService } from '../core/toaster.service'; import { ModifierCategoryService } from '../modifier-categories/modifier-category.service'; +import { MathService } from '../shared/math.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'; @@ -39,6 +38,7 @@ export class BillService { constructor( private dialog: MatDialog, private toaster: ToasterService, + private math: MathService, private ser: VoucherService, private modifierCategoryService: ModifierCategoryService, ) { @@ -75,7 +75,10 @@ export class BillService { productId: i.product.id, isHappyHour: i.isHappyHour, isPrinted: !!k.id, - info: `${i.product.name} @ ${i.price} - ${round(i.discount * 100, 2)}%`, + info: `${i.product.name} @ ${i.price} - ${this.math.halfRoundEven( + i.discount * 100, + 2, + )}%`, quantity: i.quantity, modifiers: i.modifiers, }), @@ -284,7 +287,7 @@ export class BillService { updateAmounts() { this.netAmount.next( - round( + this.math.halfRoundEven( this.bill.kots.reduce( (t, k) => k.inventories.reduce((a, c) => a + (c.isHappyHour ? 0 : c.price) * c.quantity, 0) + t, @@ -293,7 +296,7 @@ export class BillService { ), ); this.discountAmount.next( - round( + this.math.halfRoundEven( this.bill.kots.reduce( (t, k) => k.inventories.reduce( @@ -305,7 +308,7 @@ export class BillService { ), ); this.taxAmount.next( - round( + this.math.halfRoundEven( this.bill.kots.reduce( (t, k) => k.inventories.reduce( @@ -318,7 +321,7 @@ export class BillService { ), ); this.amountBs.next( - round( + this.math.halfRoundEven( this.bill.kots.reduce( (t, k) => k.inventories.reduce( diff --git a/bookie/src/app/shared/math.service.ts b/bookie/src/app/shared/math.service.ts index 83117e7..df37ee2 100644 --- a/bookie/src/app/shared/math.service.ts +++ b/bookie/src/app/shared/math.service.ts @@ -5,7 +5,6 @@ import { evaluate, round } from 'mathjs'; providedIn: 'root', }) export class MathService { - // eslint-disable-next-line class-methods-use-this parseAmount(amount: string = '', rounding: number = 2): number { const cleaned = `${amount}`.replace(new RegExp('(₹[s]*)|(,)|(s)', 'g'), ''); if (cleaned === '') { @@ -13,4 +12,15 @@ export class MathService { } return round(evaluate(cleaned), rounding); } + + halfRoundEven(x: number, n = 0): number { + const fraction = Math.round(x * Math.pow(10, n + 8)) % Math.pow(10, 8); + if (fraction > 50000000 - 1 && fraction < 50000000 + 1) { + // To compensate for floating point rounding errors + const floor = Math.floor(x * Math.pow(10, n)); + return floor % 2 === 0 ? floor / Math.pow(10, n) : (floor + 1) / Math.pow(10, n); + } else { + return round(x, n); + } + } }