RoundingUtil { public static void handleRoundingLineItem(Bill bill) { ICashierOptionsService cashOptService = Context.getService(ICashierOptionsService.class); CashierOptions options = cashOptService.getOptions(); if (options.getRoundToNearest().equals(BigDecimal.ZERO)) { return; } if (options.getRoundingItemUuid() == null) { throw new APIException( "No rounding item specified in options. This must be set in order to use rounding for bill totals."); } IItemDataService itemService = Context.getService(IItemDataService.class); Item roundingItem = itemService.getByUuid(options.getRoundingItemUuid()); BillLineItem roundingLineItem = findRoundingLineItem(bill, roundingItem); BigDecimal difference = calculateRoundingValue(bill, options, roundingLineItem); if (difference.equals(BigDecimal.ZERO) && roundingLineItem != null) { bill.removeLineItem(roundingLineItem); } else if (!difference.equals(BigDecimal.ZERO) && roundingLineItem == null) { bill.addLineItem(roundingItem, difference.abs(), "", difference.compareTo(BigDecimal.ZERO) > 0 ? -1 : 1); } else if (!difference.equals(BigDecimal.ZERO)) { updateRoundingItem(bill, difference, roundingLineItem); } bill.recalculateLineItemOrder(); } protected  RoundingUtil(); static BigDecimal round(BigDecimal value, Integer nearest, CashierOptions.RoundingMode mode); static void setupRoundingDeptAndItem(Log log); static void handleRoundingLineItem(Bill bill);  }
@Test public void roundingInAdjustedBill_shouldDeleteRoundingLineItemIfRoundingDifferenceIsZero() throws Exception { Bill bill = new Bill(); BillLineItem item = new BillLineItem(); Item lineItemItem = new Item(1); item.setItem(lineItemItem); item.setLineItemOrder(0); item.setPrice(new BigDecimal(7)); item.setQuantity(1); bill.addLineItem(item); Assert.assertEquals(1, bill.getLineItems().size()); RoundingUtil.handleRoundingLineItem(bill); Assert.assertEquals(2, bill.getLineItems().size()); BillLineItem item2 = new BillLineItem(); item2.setItem(lineItemItem); item2.setLineItemOrder(0); item2.setPrice(new BigDecimal(3)); item2.setQuantity(1); bill.addLineItem(item2); RoundingUtil.handleRoundingLineItem(bill); Assert.assertEquals(2, bill.getLineItems().size()); CashierOptions cashierOptions = cashOptService.getOptions(); IItemDataService itemService = Context.getService(IItemDataService.class); Item roundingItem = itemService.getByUuid(cashierOptions.getRoundingItemUuid()); boolean containsRoundingItem = false; for (BillLineItem lineItem : bill.getLineItems()) { if (roundingItem.equals(lineItem.getItem())) { containsRoundingItem = true; } } Assert.assertEquals(false, containsRoundingItem); }
@Test public void roundingInAdjustedBill_shouldConsiderRoundingOfPreviousBill() throws Exception { CashierOptions cashierOptions = cashOptService.getOptions(); Assert.assertEquals(5, (int)cashierOptions.getRoundToNearest()); Bill bill = new Bill(); BillLineItem item = new BillLineItem(); Item lineItemItem = new Item(1); item.setItem(lineItemItem); item.setLineItemOrder(0); item.setPrice(new BigDecimal(8)); item.setQuantity(1); bill.addLineItem(item); IItemDataService itemService = Context.getService(IItemDataService.class); Item roundingItem = itemService.getByUuid(cashierOptions.getRoundingItemUuid()); Assert.assertEquals(1, bill.getLineItems().size()); RoundingUtil.handleRoundingLineItem(bill); Assert.assertEquals(2, bill.getLineItems().size()); item.setLineItemOrder(1); bill.addLineItem(item); Assert.assertEquals(3, bill.getLineItems().size()); RoundingUtil.handleRoundingLineItem(bill); Assert.assertEquals(3, bill.getLineItems().size()); BigDecimal roundingValue = new BigDecimal(0); BigDecimal itemTotal = new BigDecimal(0); int roundingItemCounter = 0; for (BillLineItem lineItem : bill.getLineItems()) { if (lineItem.getItem() != null && roundingItem.getId().equals(lineItem.getItem().getId())) { roundingValue = roundingValue.add(lineItem.getTotal()); roundingItemCounter++; } else { itemTotal = itemTotal.add(lineItem.getTotal()); } } Assert.assertEquals(16, itemTotal.intValue()); Assert.assertEquals(-1, roundingValue.intValue()); Assert.assertEquals(1, roundingItemCounter); }
@Test public void addRoundingLineItem_shouldAddARoundingLineItemWithTheAppropriateValue() throws Exception { CashierOptions cashierOptions = cashOptService.getOptions(); Assert.assertEquals(5, (int)cashierOptions.getRoundToNearest()); Bill bill = new Bill(); BillLineItem item = new BillLineItem(); Item lineItemItem = new Item(1); item.setItem(lineItemItem); item.setLineItemOrder(0); item.setPrice(new BigDecimal(3)); item.setQuantity(1); bill.addLineItem(item); Assert.assertEquals(1, bill.getLineItems().size()); RoundingUtil.handleRoundingLineItem(bill); Assert.assertEquals(2, bill.getLineItems().size()); BillLineItem rounding = bill.getLineItems().get(1); Assert.assertEquals(new BigDecimal(2), rounding.getTotal()); Assert.assertEquals(new BigDecimal(0), bill.getTotal().remainder( new BigDecimal(cashierOptions.getRoundToNearest()))); }
@Test public void handleRoundingLineItem_shouldRoundBillsWithANonZeroAmountCorrectlyForMID() throws Exception { CashierOptions cashierOptions = cashOptService.getOptions(); Assert.assertEquals(5, (int)cashierOptions.getRoundToNearest()); Assert.assertEquals(CashierOptions.RoundingMode.MID, cashierOptions.getRoundingMode()); Bill bill = new Bill(); BillLineItem item = new BillLineItem(); Item lineItemItem = new Item(1); item.setItem(lineItemItem); item.setLineItemOrder(0); item.setPrice(new BigDecimal(3.5)); item.setQuantity(1); bill.addLineItem(item); Assert.assertEquals(1, bill.getLineItems().size()); RoundingUtil.handleRoundingLineItem(bill); Assert.assertEquals(2, bill.getLineItems().size()); BillLineItem rounding = bill.getLineItems().get(1); Assert.assertEquals(new BigDecimal(1.5), rounding.getTotal()); }
@Test public void handleRoundingLineItem_shouldRoundBillsWithANonZeroAmountCorrectlyForCEILING() throws Exception { CashierSettings settings = ModuleSettings.loadSettings(); settings.setCashierRoundingMode(CashierOptions.RoundingMode.CEILING.toString()); ModuleSettings.saveSettings(settings); settings = ModuleSettings.loadSettings(); Assert.assertEquals(5, (int)settings.getCashierRoundingToNearest()); Assert.assertEquals(CashierOptions.RoundingMode.CEILING.toString(), settings.getCashierRoundingMode()); Bill bill = new Bill(); BillLineItem item = new BillLineItem(); Item lineItemItem = new Item(1); item.setItem(lineItemItem); item.setLineItemOrder(0); item.setPrice(new BigDecimal(3.5)); item.setQuantity(1); bill.addLineItem(item); Assert.assertEquals(1, bill.getLineItems().size()); RoundingUtil.handleRoundingLineItem(bill); Assert.assertEquals(2, bill.getLineItems().size()); BillLineItem rounding = bill.getLineItems().get(1); Assert.assertEquals(new BigDecimal(1.5), rounding.getTotal()); }
@Test public void handleRoundingLineItem_shouldRoundBillsWithANonZeroAmountCorrectlyForFLOOR() throws Exception { CashierSettings settings = ModuleSettings.loadSettings(); settings.setCashierRoundingMode(CashierOptions.RoundingMode.FLOOR.toString()); ModuleSettings.saveSettings(settings); settings = ModuleSettings.loadSettings(); Assert.assertEquals(5, (int)settings.getCashierRoundingToNearest()); Assert.assertEquals(CashierOptions.RoundingMode.FLOOR.toString(), settings.getCashierRoundingMode()); Bill bill = new Bill(); BillLineItem item = new BillLineItem(); Item lineItemItem = new Item(1); item.setItem(lineItemItem); item.setLineItemOrder(0); item.setPrice(new BigDecimal(3.5)); item.setQuantity(1); bill.addLineItem(item); Assert.assertEquals(1, bill.getLineItems().size()); RoundingUtil.handleRoundingLineItem(bill); Assert.assertEquals(2, bill.getLineItems().size()); BillLineItem rounding = bill.getLineItems().get(1); Assert.assertEquals(new BigDecimal(-3.5), rounding.getTotal()); }
@Test public void addRoundingLineItem_shouldNotModifyABillThatNeedsNoRounding() throws Exception { CashierOptions cashierOptions = cashOptService.getOptions(); Assert.assertEquals(5, (int)cashierOptions.getRoundToNearest()); Bill bill = new Bill(); BillLineItem item = new BillLineItem(); Item lineItemItem = new Item(1); item.setItem(lineItemItem); item.setLineItemOrder(0); item.setPrice(new BigDecimal(5)); item.setQuantity(1); bill.addLineItem(item); Assert.assertEquals(1, bill.getLineItems().size()); RoundingUtil.handleRoundingLineItem(bill); Assert.assertEquals(1, bill.getLineItems().size()); }
@Test public void roundingInAdjustedBill_shouldNotAddRoundingLineItemIfRoundingDifferenceIsZero() throws Exception { Bill bill = new Bill(); BillLineItem item = new BillLineItem(); Item lineItemItem = new Item(1); item.setItem(lineItemItem); item.setLineItemOrder(0); item.setPrice(new BigDecimal(5)); item.setQuantity(1); bill.addLineItem(item); Assert.assertEquals(1, bill.getLineItems().size()); RoundingUtil.handleRoundingLineItem(bill); Assert.assertEquals(1, bill.getLineItems().size()); }
@Test public void roundingInAdjustedBill_shouldAddRoundingLineItemIfRoundingDifferenceIsNotZero() throws Exception { Bill bill = new Bill(); BillLineItem item = new BillLineItem(); Item lineItemItem = new Item(1); item.setItem(lineItemItem); item.setLineItemOrder(0); item.setPrice(new BigDecimal(7)); item.setQuantity(1); bill.addLineItem(item); Assert.assertEquals(1, bill.getLineItems().size()); RoundingUtil.handleRoundingLineItem(bill); Assert.assertEquals(2, bill.getLineItems().size()); }
@Test public void roundingInAdjustedBill_shouldUpdateRoundingLineItemIfRoundingDifferenceIsNotZero() throws Exception { Bill bill = new Bill(); BillLineItem item = new BillLineItem(); Item lineItemItem = new Item(1); item.setItem(lineItemItem); item.setLineItemOrder(0); item.setPrice(new BigDecimal(7)); item.setQuantity(1); bill.addLineItem(item); Assert.assertEquals(1, bill.getLineItems().size()); RoundingUtil.handleRoundingLineItem(bill); Assert.assertEquals(2, bill.getLineItems().size()); CashierOptions cashierOptions = cashOptService.getOptions(); IItemDataService itemService = Context.getService(IItemDataService.class); Item roundingItem = itemService.getByUuid(cashierOptions.getRoundingItemUuid()); BillLineItem roundingLineItem = null; for (BillLineItem lineItem : bill.getLineItems()) { if (roundingItem.equals(lineItem.getItem())) { roundingLineItem = lineItem; } } Assert.assertNotNull(roundingLineItem); Assert.assertEquals(roundingLineItem.getTotal().intValue(), -2); bill.addLineItem(item); Assert.assertEquals(3, bill.getLineItems().size()); RoundingUtil.handleRoundingLineItem(bill); Assert.assertEquals(3, bill.getLineItems().size()); roundingLineItem = null; for (BillLineItem lineItem : bill.getLineItems()) { if (roundingItem.equals(lineItem.getItem())) { roundingLineItem = lineItem; } } Assert.assertNotNull(roundingLineItem); Assert.assertEquals(roundingLineItem.getTotal().intValue(), 1); }