From c2c9e369b5c60ed941a90632b8a0d277d57ca252 Mon Sep 17 00:00:00 2001 From: Carlos Ruiz Date: Wed, 24 Jun 2015 20:28:52 -0500 Subject: [PATCH] IDEMPIERE-2629 M_StorageOnHand Qty and Total M_Transaction Qty did not match --- .../org/compiere/process/InOutGenerate.java | 2 +- .../org/compiere/model/MProductionLine.java | 21 +++------ .../org/compiere/model/MStorageOnHand.java | 46 ++++++++++--------- .../compiere/model/MStorageReservation.java | 37 +++++++++++++-- 4 files changed, 65 insertions(+), 41 deletions(-) diff --git a/org.adempiere.base.process/src/org/compiere/process/InOutGenerate.java b/org.adempiere.base.process/src/org/compiere/process/InOutGenerate.java index 3e3c1d4d42..d9d3971b22 100644 --- a/org.adempiere.base.process/src/org/compiere/process/InOutGenerate.java +++ b/org.adempiere.base.process/src/org/compiere/process/InOutGenerate.java @@ -507,7 +507,7 @@ public class InOutGenerate extends SvrProcess throw new IllegalStateException("Could not create Shipment Line"); if (log.isLoggable(Level.FINE)) log.fine("ToDeliver=" + qty + "/" + deliver + " - " + line); toDeliver = toDeliver.subtract(deliver); - // Temp adjustment, actual update happen in MInOut.completeIt + // Temp adjustment, actual update happen in MInOut.completeIt - just in memory - not saved storage.setQtyOnHand(storage.getQtyOnHand().subtract(deliver)); // if (toDeliver.signum() == 0) diff --git a/org.adempiere.base/src/org/compiere/model/MProductionLine.java b/org.adempiere.base/src/org/compiere/model/MProductionLine.java index d395a068d0..c99d7324a9 100644 --- a/org.adempiere.base/src/org/compiere/model/MProductionLine.java +++ b/org.adempiere.base/src/org/compiere/model/MProductionLine.java @@ -120,11 +120,8 @@ public class MProductionLine extends X_M_ProductionLine { } MStorageOnHand storage = MStorageOnHand.getCreate(getCtx(), getM_Locator_ID(), getM_Product_ID(), asi.get_ID(),dateMPolicy, get_TrxName()); - storage.changeQtyOnHand(getMovementQty(), true); - if ( !storage.save(get_TrxName()) ) { - log.log(Level.SEVERE, "Could not update storage for " + toString()); - errorString.append("Could not save transaction for " + toString() + "\n"); - } + storage.addQtyOnHand(getMovementQty()); + storage.load(storage.get_TrxName()); if (log.isLoggable(Level.FINE))log.log(Level.FINE, "Created finished goods line " + getLine()); return errorString.toString(); @@ -182,11 +179,8 @@ public class MProductionLine extends X_M_ProductionLine { if (log.isLoggable(Level.FINE))log.log(Level.FINE, "Saved transaction for " + toString()); } DB.getDatabase().forUpdate(storages[sl], 120); - storages[sl].changeQtyOnHand(lineQty, false); - if ( !storages[sl].save(get_TrxName()) ) { - log.log(Level.SEVERE, "Could not update storage for " + toString()); - errorString.append("Could not update storage for " + toString() + "\n"); - } + storages[sl].addQtyOnHand(lineQty.negate()); + storages[sl].load(storages[sl].get_TrxName()); qtyToMove = qtyToMove.subtract(lineQty); if (log.isLoggable(Level.FINE))log.log(Level.FINE, getLine() + " Qty moved = " + lineQty + ", Remaining = " + qtyToMove ); } @@ -244,11 +238,8 @@ public class MProductionLine extends X_M_ProductionLine { } else { if (log.isLoggable(Level.FINE))log.log(Level.FINE, "Saved transaction for " + toString()); } - storage.changeQtyOnHand(lineQty, false); - if ( !storage.save(get_TrxName()) ) { - log.log(Level.SEVERE, "Could not update storage for " + toString()); - errorString.append("Could not update storage for " + toString() + "\n"); - } + storage.addQtyOnHand(lineQty.negate()); + storage.load(storage.get_TrxName()); qtyToMove = qtyToMove.subtract(lineQty); if (log.isLoggable(Level.FINE))log.log(Level.FINE, getLine() + " Qty moved = " + lineQty + ", Remaining = " + qtyToMove ); } diff --git a/org.adempiere.base/src/org/compiere/model/MStorageOnHand.java b/org.adempiere.base/src/org/compiere/model/MStorageOnHand.java index 0a80755095..14bb46a74e 100644 --- a/org.adempiere.base/src/org/compiere/model/MStorageOnHand.java +++ b/org.adempiere.base/src/org/compiere/model/MStorageOnHand.java @@ -27,6 +27,7 @@ import java.util.List; import java.util.Properties; import java.util.logging.Level; +import org.adempiere.exceptions.AdempiereException; import org.compiere.util.CLogger; import org.compiere.util.DB; import org.compiere.util.Env; @@ -44,7 +45,7 @@ public class MStorageOnHand extends X_M_StorageOnHand /** * */ - private static final long serialVersionUID = -4934837951332485064L; + private static final long serialVersionUID = -3820729340100521329L; /** * @@ -735,15 +736,32 @@ public class MStorageOnHand extends X_M_StorageOnHand return false; } - storage.setQtyOnHand (storage.getQtyOnHand().add (diffQtyOnHand)); + storage.addQtyOnHand(diffQtyOnHand); + storage.load(storage.get_TrxName()); + if (storage.getQtyOnHand().signum() == -1) { + if (MWarehouse.get(Env.getCtx(), M_Warehouse_ID).isDisallowNegativeInv()) { + throw new AdempiereException(Msg.getMsg(ctx, "NegativeInventoryDisallowed")); + } + } if (s_log.isLoggable(Level.FINE)) { StringBuilder diffText = new StringBuilder("(OnHand=").append(diffQtyOnHand).append(") -> ").append(storage.toString()); s_log.fine(diffText.toString()); } - return storage.save (trxName); + return true; } // add - + /** + * Add quantity on hand directly - not using cached value - solving IDEMPIERE-2629 + * @param addition + */ + public void addQtyOnHand(BigDecimal addition) { + final String sql = "UPDATE M_StorageOnHand SET QtyOnHand=QtyOnHand+?, Updated=SYSDATE, UpdatedBy=? " + + "WHERE M_Product_ID=? AND M_Locator_ID=? AND M_AttributeSetInstance_ID=? AND DateMaterialPolicy=?"; + DB.executeUpdateEx(sql, + new Object[] {addition, Env.getAD_User_ID(Env.getCtx()), getM_Product_ID(), getM_Locator_ID(), getM_AttributeSetInstance_ID(), getDateMaterialPolicy()}, + get_TrxName()); + } + /************************************************************************** * Get Location with highest Locator Priority and a sufficient OnHand Qty * @param M_Warehouse_ID warehouse @@ -854,21 +872,6 @@ public class MStorageOnHand extends X_M_StorageOnHand /** Warehouse */ private int m_M_Warehouse_ID = 0; - /** - * Change Qty OnHand - * @param qty quantity - * @param add add if true - */ - public void changeQtyOnHand (BigDecimal qty, boolean add) - { - if (qty == null || qty.signum() == 0) - return; - if (add) - setQtyOnHand(getQtyOnHand().add(qty)); - else - setQtyOnHand(getQtyOnHand().subtract(qty)); - } // changeQtyOnHand - /** * Get M_Warehouse_ID of Locator * @return warehouse @@ -997,8 +1000,9 @@ public class MStorageOnHand extends X_M_StorageOnHand { StringBuffer sb = new StringBuffer("MStorageOnHand[") .append("M_Locator_ID=").append(getM_Locator_ID()) - .append(",M_Product_ID=").append(getM_Product_ID()) - .append(",M_AttributeSetInstance_ID=").append(getM_AttributeSetInstance_ID()) + .append(",M_Product_ID=").append(getM_Product_ID()) + .append(",M_AttributeSetInstance_ID=").append(getM_AttributeSetInstance_ID()) + .append(",DateMaterialPolicy=").append(getDateMaterialPolicy()) .append(": OnHand=").append(getQtyOnHand()) /* @win commented out .append(",Reserved=").append(getQtyReserved()) diff --git a/org.adempiere.base/src/org/compiere/model/MStorageReservation.java b/org.adempiere.base/src/org/compiere/model/MStorageReservation.java index 243842dee2..2155a2ac17 100644 --- a/org.adempiere.base/src/org/compiere/model/MStorageReservation.java +++ b/org.adempiere.base/src/org/compiere/model/MStorageReservation.java @@ -30,7 +30,7 @@ public class MStorageReservation extends X_M_StorageReservation { /** * */ - private static final long serialVersionUID = -8646802850122507899L; + private static final long serialVersionUID = 8179093165315835613L; /** * Get Storage Info @@ -248,14 +248,27 @@ public class MStorageReservation extends X_M_StorageReservation { return false; } - storage.setQty (storage.getQty().add(diffQty)); + storage.addQty(diffQty); + storage.load(storage.get_TrxName()); if (s_log.isLoggable(Level.FINE)) { StringBuilder diffText = new StringBuilder("(Qty=").append(diffQty).append(") -> ").append(storage.toString()); s_log.fine(diffText.toString()); } - return storage.save (trxName); + return true; } - + + /** + * Add quantity on hand directly - not using cached value - solving IDEMPIERE-2629 + * @param addition + */ + public void addQty(BigDecimal addition) { + final String sql = "UPDATE M_StorageReservation SET Qty=Qty+?, Updated=SYSDATE, UpdatedBy=? " + + "WHERE M_Product_ID=? AND M_Warehouse_ID=? AND M_AttributeSetInstance_ID=? AND IsSOTrx=?"; + DB.executeUpdateEx(sql, + new Object[] {addition, Env.getAD_User_ID(Env.getCtx()), getM_Product_ID(), getM_Warehouse_ID(), getM_AttributeSetInstance_ID(), isSOTrx()}, + get_TrxName()); + } + /** * Update Storage Info add. * Called from MProjectIssue @@ -309,4 +322,20 @@ public class MStorageReservation extends X_M_StorageReservation { return retValue; } // getCreate + /** + * String Representation + * @return info + */ + public String toString() + { + StringBuffer sb = new StringBuffer("MStorageReservation[") + .append("M_Warehouse_ID=").append(getM_Warehouse_ID()) + .append(",M_Product_ID=").append(getM_Product_ID()) + .append(",M_AttributeSetInstance_ID=").append(getM_AttributeSetInstance_ID()) + .append(",IsSOTrx=").append(isSOTrx()) + .append(": Qty=").append(getQty()) + .append("]"); + return sb.toString(); + } // toString + }