diff --git a/src/main/java/com/divudi/bean/pharmacy/TransferIssueForRequestsController.java b/src/main/java/com/divudi/bean/pharmacy/TransferIssueForRequestsController.java index 69ef34ff6c..1870fe82cd 100644 --- a/src/main/java/com/divudi/bean/pharmacy/TransferIssueForRequestsController.java +++ b/src/main/java/com/divudi/bean/pharmacy/TransferIssueForRequestsController.java @@ -34,6 +34,7 @@ import com.divudi.core.facade.BillFacade; import com.divudi.core.facade.BillItemFacade; import com.divudi.core.facade.PharmaceuticalBillItemFacade; +import com.divudi.core.facade.StockFacade; import com.divudi.bean.common.ConfigOptionApplicationController; import com.divudi.core.entity.BillFinanceDetails; import com.divudi.core.entity.BillItemFinanceDetails; @@ -72,6 +73,8 @@ public class TransferIssueForRequestsController implements Serializable { @EJB private BillItemFacade billItemFacade; @EJB + private StockFacade stockFacade; + @EJB private PharmacyBean pharmacyBean; @Inject private PharmacyCalculation pharmacyCalculation; @@ -784,6 +787,9 @@ public synchronized void settle() { JsfUtil.addErrorMessage("No Bill Items are added to Transfer"); return; } + // Live stock check: fetch current DB values for every item before committing anything. + // The in-memory Stock object was captured at page-load time and may be stale — a retail + // sale or concurrent issue after page load will not be reflected in it. for (BillItem bi : getBillItems()) { // Single source of truth for the issued quantity (#21266 RC6): the // user-entered qty lives in BillItemFinanceDetails.quantity, but the @@ -795,22 +801,37 @@ public synchronized void settle() { // pbi/billItem qty from the user-entered value BEFORE validating or // moving any stock, keeping the positive pre-settle sign convention. syncStockQtyFromUserEnteredQty(bi); - if (bi.getPharmaceuticalBillItem().getItemBatch() != null) { - if (bi.getPharmaceuticalBillItem().getStock().getStock() < bi.getPharmaceuticalBillItem().getQty()) { - JsfUtil.addErrorMessage("Available quantity is less than issued quantity in " + bi.getPharmaceuticalBillItem().getItemBatch().getItem().getName()); + PharmaceuticalBillItem pbi = bi.getPharmaceuticalBillItem(); + if (pbi == null) { + // createEmptyBillItem() leaves pharmaceuticalBillItem unset when no stock + // was available at generation time - nothing to validate or settle for it. + continue; + } + if (pbi.getItemBatch() == null) { + if (pbi.getQty() > 0) { + String name = bi.getItem() != null ? bi.getItem().getName() : "An item"; + JsfUtil.addErrorMessage(name + " is not available in the stock."); return; } - } else if (bi.getPharmaceuticalBillItem().getItemBatch() == null) { - if (bi.getPharmaceuticalBillItem().getQty() > 0) { - JsfUtil.addErrorMessage(bi.getItem().getName() + " is not available in the stock"); - return; + } else { + if (pbi.getStock() != null && pbi.getStock().getId() != null) { + Stock liveStock = stockFacade.find(pbi.getStock().getId()); + if (liveStock == null || liveStock.getStock() < pbi.getQty()) { + JsfUtil.addErrorMessage("Insufficient stock for one or more items. " + + "Stock levels may have changed since this page was loaded. " + + "Please refresh and try again."); + return; + } } } double remainingQty = getRemainingQuantityForItem(bi.getReferanceBillItem()); - double issuingQty = bi.getBillItemFinanceDetails().getQuantity() != null ? bi.getBillItemFinanceDetails().getQuantity().doubleValue() : 0.0; + double issuingQty = bi.getBillItemFinanceDetails().getQuantity() != null + ? bi.getBillItemFinanceDetails().getQuantity().doubleValue() : 0.0; if (issuingQty > remainingQty) { - JsfUtil.addErrorMessage("Issued quantity (" + issuingQty + ") is higher than remaining requested quantity (" + remainingQty + ") for " + bi.getItem().getName()); + String name = bi.getItem() != null ? bi.getItem().getName() : "one of the items"; + JsfUtil.addErrorMessage("Issued quantity (" + issuingQty + ") is higher than remaining " + + "requested quantity (" + remainingQty + ") for " + name + "."); return; } } @@ -818,7 +839,7 @@ public synchronized void settle() { //Remove Zero Qty Item List billItemList = new ArrayList<>(); for (BillItem bi : getBillItems()) { - if (bi.getPharmaceuticalBillItem().getQty() != 0.0) { + if (bi.getPharmaceuticalBillItem() != null && bi.getPharmaceuticalBillItem().getQty() != 0.0) { billItemList.add(bi); } } @@ -862,14 +883,6 @@ public synchronized void settle() { billItemsInIssue.setPharmaceuticalBillItem(tmpPh); getBillItemFacade().edit(billItemsInIssue); - //Checking User Stock Entity - if (!userStockController.isStockAvailable(tmpPh.getStock(), tmpPh.getQty(), getSessionController().getLoggedUser())) { - billItemsInIssue.setTmpQty(0); - getBillItemFacade().edit(billItemsInIssue); - getIssuedBill().getBillItems().add(billItemsInIssue); - continue; - } - //Remove Department Stock boolean returnFlag = pharmacyBean.deductFromStock(billItemsInIssue.getPharmaceuticalBillItem().getStock(), Math.abs(billItemsInIssue.getPharmaceuticalBillItem().getQty()), diff --git a/src/main/java/com/divudi/ejb/PharmacyBean.java b/src/main/java/com/divudi/ejb/PharmacyBean.java index 1ebbd4f8dd..ab3077ec5c 100644 --- a/src/main/java/com/divudi/ejb/PharmacyBean.java +++ b/src/main/java/com/divudi/ejb/PharmacyBean.java @@ -924,6 +924,14 @@ public Stock addToStock(PharmaceuticalBillItem pharmaceuticalBillItem, double qt s.setItemBatch(pharmaceuticalBillItem.getItemBatch()); s.setStock(qty); ItemBatch ib = pharmaceuticalBillItem.getItemBatch(); + // The ItemBatch may be a minimal DTO-constructed object (id set, but no item/dateOfExpire). + // Load the full entity so metadata fields on the Staff Stock row are populated correctly. + if (ib != null && ib.getItem() == null && ib.getId() != null) { + ItemBatch full = itemBatchFacade.find(ib.getId()); + if (full != null) { + ib = full; + } + } Item i = null; if (ib != null) { i = ib.getItem(); @@ -1061,6 +1069,12 @@ public boolean deductFromStock(PharmaceuticalBillItem pharmaceuticalBillItem, do s.setStaff(staff); s.setItemBatch(pharmaceuticalBillItem.getItemBatch()); ItemBatch ib = pharmaceuticalBillItem.getItemBatch(); + if (ib != null && ib.getItem() == null && ib.getId() != null) { + ItemBatch full = itemBatchFacade.find(ib.getId()); + if (full != null) { + ib = full; + } + } Item i = null; if (ib != null) { i = ib.getItem();