Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand All @@ -795,30 +801,45 @@ 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;
}
}

//Remove Zero Qty Item
List<BillItem> 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);
}
}
Expand Down Expand Up @@ -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()),
Expand Down
14 changes: 14 additions & 0 deletions src/main/java/com/divudi/ejb/PharmacyBean.java
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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();
Expand Down
Loading