From 0938626631d47b71ce9b6d458d047e42e2ac992c Mon Sep 17 00:00:00 2001 From: buddhika Date: Mon, 13 Jul 2026 03:23:39 +0530 Subject: [PATCH] Fix incorrect wholesale value calculation from unrounded batch rate ItemBatch.wholesaleRate is frequently stored with more than 2 decimal places (e.g. 8.4564), but the UI always displays rates rounded to 2dp. WholesaleSaleNativeSqlController used the raw unrounded rate for all value/discount math, so the displayed Rate x Qty didn't match the displayed Value (e.g. 8.46 x 10 showed as 84.56 instead of 84.60). Round the wholesale rate to currency precision at the point it's consumed for billing (add, substitute, live preview, row edit), using the existing CommonFunctions.round() convention already used for wholesale rates elsewhere in the pharmacy module. Closes #21912 Co-Authored-By: Claude Sonnet 5 --- .../WholesaleSaleNativeSqlController.java | 25 +++++++++++++------ 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/divudi/bean/pharmacy/WholesaleSaleNativeSqlController.java b/src/main/java/com/divudi/bean/pharmacy/WholesaleSaleNativeSqlController.java index 084e6c2461..b38908189e 100644 --- a/src/main/java/com/divudi/bean/pharmacy/WholesaleSaleNativeSqlController.java +++ b/src/main/java/com/divudi/bean/pharmacy/WholesaleSaleNativeSqlController.java @@ -785,9 +785,15 @@ public void addBillItem() { bid.setFreeQty(0.0); // For wholesale sale, retailRate/batchRetailRate are kept as bookkeeping metadata // (from the batch lookup); the actual charged rate comes from wholesaleRate. + // The charged rate is rounded to currency precision (2dp) so the displayed Rate + // and the calculated Value always agree (ItemBatch.wholesaleRate is frequently + // stored with more than 2 decimal places, e.g. 8.4564 - issue #21912). + double lineWholesaleRate = CommonFunctions.round( + stockDto.getWholesaleRate() != null ? stockDto.getWholesaleRate() : 0.0); + bid.setRetailRate(batchRetailRate); bid.setPurchaseRate(batchPurchaseRate); - bid.setWholesaleRate(stockDto.getWholesaleRate() != null ? stockDto.getWholesaleRate() : 0.0); + bid.setWholesaleRate(lineWholesaleRate); bid.setCostRate(batchCostRate != null ? batchCostRate : batchPurchaseRate); bid.setBatchRetailRate(batchRetailRate); bid.setBatchPurchaseRate(batchPurchaseRate); @@ -798,7 +804,6 @@ public void addBillItem() { bid.setCreatedAt(new Date()); bid.setCreaterId(sessionController.getLoggedUser().getId()); - double lineWholesaleRate = stockDto.getWholesaleRate() != null ? stockDto.getWholesaleRate() : 0.0; double grossValue = lineWholesaleRate * qty; double discountPct = 0.0; double discountValue = 0.0; @@ -1081,10 +1086,13 @@ public void replaceSelectedSubstitute() { bid.setItemBatchId(sub.getItemBatchId()); bid.setPbiQty(-Math.abs(qty)); // For wholesale sale, retailRate/batchRetailRate are kept as bookkeeping metadata; - // the actual charged rate comes from the substitute's wholesaleRate. + // the actual charged rate comes from the substitute's wholesaleRate, rounded to + // currency precision so the displayed Rate and calculated Value agree (#21912). + double lineWholesaleRate = CommonFunctions.round(batchWholesaleRate); + bid.setRetailRate(batchRetailRate); bid.setPurchaseRate(batchPurchaseRate); - bid.setWholesaleRate(batchWholesaleRate); + bid.setWholesaleRate(lineWholesaleRate); bid.setCostRate(batchCostRate != null ? batchCostRate : batchPurchaseRate); bid.setBatchRetailRate(batchRetailRate); bid.setBatchPurchaseRate(batchPurchaseRate); @@ -1093,7 +1101,6 @@ public void replaceSelectedSubstitute() { bid.setDoe(sub.getDateOfExpire()); bid.setDescription(sub.getItemName()); - double lineWholesaleRate = batchWholesaleRate; double grossValue = lineWholesaleRate * qty; double discountPct = 0.0; double discountValue = 0.0; @@ -1189,7 +1196,8 @@ public void calculateDobFromAge() { public void calculateBillItemListner() { if (stockDto != null && intQty != null) { - double rate = stockDto.getWholesaleRate() != null ? stockDto.getWholesaleRate() : 0.0; + double rate = CommonFunctions.round( + stockDto.getWholesaleRate() != null ? stockDto.getWholesaleRate() : 0.0); getBillItem().setRate(rate); getBillItem().setNetRate(rate); getBillItem().setNetValue(rate * intQty); @@ -1641,12 +1649,13 @@ public void setToStaff(Staff toStaff) { public Double getPreviewRate() { if (stockDto == null) return null; - return stockDto.getWholesaleRate(); + return stockDto.getWholesaleRate() != null ? CommonFunctions.round(stockDto.getWholesaleRate()) : null; } public Double getPreviewNetValue() { if (stockDto == null || intQty == null) return null; - double rate = stockDto.getWholesaleRate() != null ? stockDto.getWholesaleRate() : 0.0; + double rate = CommonFunctions.round( + stockDto.getWholesaleRate() != null ? stockDto.getWholesaleRate() : 0.0); return rate * intQty; }