IDEMPIERE-3488 Improvement to Error Message for Negative Inventory Disallow exception

This commit is contained in:
Heng Sin Low 2017-09-15 11:15:10 +08:00
parent 8f0c185141
commit e3961c7d61
9 changed files with 795 additions and 607 deletions

View File

@ -0,0 +1,11 @@
SET SQLBLANKLINES ON
SET DEFINE OFF
-- IDEMPIERE-3488 Improvement to Error Message for Negative Inventory Disallow exception
-- Sep 14, 2017 6:28:55 PM GMT+08:00
INSERT INTO AD_Message (MsgType,MsgText,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Message_ID,Value,EntityType,AD_Message_UU) VALUES ('E','The {0} warehouse does not allow negative inventory for Product = {1}, ASI = {2}, Locator = {3} (Shortage of {4})',0,0,'Y',TO_DATE('2017-09-14 18:28:54','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2017-09-14 18:28:54','YYYY-MM-DD HH24:MI:SS'),100,200431,'NegativeInventoryDisallowedInfo','D','1a686715-09f5-4437-9885-882719423bd1')
;
SELECT register_migration_script('201709151000_IDEMPIERE-3488.sql') FROM dual
;

View File

@ -0,0 +1,8 @@
-- IDEMPIERE-3488 Improvement to Error Message for Negative Inventory Disallow exception
-- Sep 14, 2017 6:28:55 PM GMT+08:00
INSERT INTO AD_Message (MsgType,MsgText,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Message_ID,Value,EntityType,AD_Message_UU) VALUES ('E','The {0} warehouse does not allow negative inventory for Product = {1}, ASI = {2}, Locator = {3} (Shortage of {4})',0,0,'Y',TO_TIMESTAMP('2017-09-14 18:28:54','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2017-09-14 18:28:54','YYYY-MM-DD HH24:MI:SS'),100,200431,'NegativeInventoryDisallowedInfo','D','1a686715-09f5-4437-9885-882719423bd1')
;
SELECT register_migration_script('201709151000_IDEMPIERE-3488.sql') FROM dual
;

View File

@ -0,0 +1,88 @@
/*******************************************************************************
* Copyright (C) 2017 Trek Global Inc. *
* Copyright (C) 2017 Low Heng Sin *
* This program is free software; you can redistribute it and/or modify it *
* under the terms version 2 of the GNU General Public License as published *
* by the Free Software Foundation. This program is distributed in the hope *
* that it will be useful, but WITHOUT ANY WARRANTY; without even the implied *
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU General Public License for more details. *
* You should have received a copy of the GNU General Public License along *
* with this program; if not, write to the Free Software Foundation, Inc., *
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
*******************************************************************************/
package org.adempiere.exceptions;
import java.math.BigDecimal;
import java.util.Properties;
import org.compiere.model.MAttributeSetInstance;
import org.compiere.model.MLocator;
import org.compiere.model.MProduct;
import org.compiere.model.MSysConfig;
import org.compiere.model.MWarehouse;
import org.compiere.util.Env;
import org.compiere.util.Msg;
/**
*
* @author hengsin
*
*/
public class NegativeInventoryDisallowedException extends AdempiereException
{
/**
*
*/
private static final long serialVersionUID = 253224414462489886L;
private int M_Warehouse_ID;
private int M_Product_ID;
private int M_AttributeSetInstance_ID;
private int M_Locator_ID;
private BigDecimal QtyOnHand;
private BigDecimal MovementQty;
public NegativeInventoryDisallowedException(Properties ctx, int M_Warehouse_ID, int M_Product_ID, int M_AttributeSetInstance_ID, int M_Locator_ID,
BigDecimal QtyOnHand, BigDecimal MovementQty)
{
super(Msg.getMsg(ctx, "NegativeInventoryDisallowedInfo", new Object[] {
MWarehouse.get(ctx, M_Warehouse_ID).getName(),
MProduct.get(ctx, M_Product_ID).getValue() + MSysConfig.getValue(MSysConfig.IDENTIFIER_SEPARATOR, "_", Env.getAD_Client_ID(ctx)) + MProduct.get(ctx, M_Product_ID).getName(),
M_AttributeSetInstance_ID > 0 ? MAttributeSetInstance.get(ctx, M_AttributeSetInstance_ID, M_Product_ID).getDescription() : "0",
M_Locator_ID > 0 ? MLocator.get(ctx, M_Locator_ID).getValue() : "0", MovementQty.subtract(QtyOnHand)
}));
this.M_Warehouse_ID = M_Warehouse_ID;
this.M_Product_ID = M_Product_ID;
this.M_AttributeSetInstance_ID = M_AttributeSetInstance_ID;
this.M_Locator_ID = M_Locator_ID;
this.QtyOnHand = QtyOnHand;
this.MovementQty = MovementQty;
}
public int getM_Warehouse_ID() {
return M_Warehouse_ID;
}
public int getM_Product_ID() {
return M_Product_ID;
}
public int getM_AttributeSetInstance_ID() {
return M_AttributeSetInstance_ID;
}
public int getM_Locator_ID() {
return M_Locator_ID;
}
public BigDecimal getQtyOnHand() {
return QtyOnHand;
}
public BigDecimal getMovementQty() {
return MovementQty;
}
}

View File

@ -26,6 +26,7 @@ import java.util.Properties;
import java.util.logging.Level;
import org.adempiere.exceptions.AdempiereException;
import org.adempiere.exceptions.NegativeInventoryDisallowedException;
import org.adempiere.exceptions.PeriodClosedException;
import org.compiere.print.MPrintFormat;
import org.compiere.print.ReportEngine;
@ -1286,6 +1287,7 @@ public class MInOut extends X_M_InOut implements DocAction
if (log.isLoggable(Level.INFO)) log.info(toString());
StringBuilder info = new StringBuilder();
StringBuilder errors = new StringBuilder();
// For all lines
MInOutLine[] lines = getLines(false);
for (int lineIndex = 0; lineIndex < lines.length; lineIndex++)
@ -1293,6 +1295,8 @@ public class MInOut extends X_M_InOut implements DocAction
MInOutLine sLine = lines[lineIndex];
MProduct product = sLine.getProduct();
try
{
// Qty & Type
String MovementType = getMovementType();
BigDecimal Qty = sLine.getMovementQty();
@ -1649,9 +1653,21 @@ public class MInOut extends X_M_InOut implements DocAction
}
} // No Order
} // PO Matching
}
catch (NegativeInventoryDisallowedException e)
{
log.severe(e.getMessage());
errors.append(Msg.getElement(getCtx(), "Line")).append(" ").append(sLine.getLine()).append(": ");
errors.append(e.getMessage()).append("\n");
}
} // for all lines
if (errors.toString().length() > 0)
{
m_processMsg = errors.toString();
return DocAction.STATUS_Invalid;
}
// Counter Documents
MInOut counter = createCounterDoc();
if (counter != null)

View File

@ -24,6 +24,7 @@ import java.util.List;
import java.util.Properties;
import java.util.logging.Level;
import org.adempiere.exceptions.NegativeInventoryDisallowedException;
import org.adempiere.exceptions.PeriodClosedException;
import org.compiere.process.DocAction;
import org.compiere.process.DocumentEngine;
@ -435,6 +436,7 @@ public class MInventory extends X_M_Inventory implements DocAction
approveIt();
if (log.isLoggable(Level.INFO)) log.info(toString());
StringBuilder errors = new StringBuilder();
MInventoryLine[] lines = getLines(false);
for (MInventoryLine line : lines)
{
@ -442,7 +444,8 @@ public class MInventory extends X_M_Inventory implements DocAction
continue;
MProduct product = line.getProduct();
try
{
BigDecimal qtyDiff = Env.ZERO;
if (MDocType.DOCSUBTYPEINV_InternalUseInventory.equals(docSubTypeInv))
qtyDiff = line.getQtyInternalUse().negate();
@ -619,9 +622,22 @@ public class MInventory extends X_M_Inventory implements DocAction
}
} // Fallback
} // stock movement
}
catch (NegativeInventoryDisallowedException e)
{
log.severe(e.getMessage());
errors.append(Msg.getElement(getCtx(), "Line")).append(" ").append(line.getLine()).append(": ");
errors.append(e.getMessage()).append("\n");
}
} // for all lines
if (errors.toString().length() > 0)
{
m_processMsg = errors.toString();
return DocAction.STATUS_Invalid;
}
// User Validation
String valid = ModelValidationEngine.get().fireDocValidate(this, ModelValidator.TIMING_AFTER_COMPLETE);
if (valid != null)

View File

@ -24,6 +24,7 @@ import java.util.List;
import java.util.Properties;
import java.util.logging.Level;
import org.adempiere.exceptions.NegativeInventoryDisallowedException;
import org.adempiere.exceptions.PeriodClosedException;
import org.compiere.process.DocAction;
import org.compiere.process.DocumentEngine;
@ -416,6 +417,7 @@ public class MMovement extends X_M_Movement implements DocAction
approveIt();
if (log.isLoggable(Level.INFO)) log.info(toString());
StringBuilder errors = new StringBuilder();
//
MMovementLine[] lines = getLines(false);
for (int i = 0; i < lines.length; i++)
@ -425,6 +427,8 @@ public class MMovement extends X_M_Movement implements DocAction
//Stock Movement - Counterpart MOrder.reserveStock
MProduct product = line.getProduct();
try
{
if (product != null
&& product.isStocked() )
{
@ -592,7 +596,21 @@ public class MMovement extends X_M_Movement implements DocAction
}
} // Fallback
} // product stock
}
catch (NegativeInventoryDisallowedException e)
{
log.severe(e.getMessage());
errors.append(Msg.getElement(getCtx(), "Line")).append(" ").append(line.getLine()).append(": ");
errors.append(e.getMessage()).append("\n");
}
} // for all lines
if (errors.toString().length() > 0)
{
m_processMsg = errors.toString();
return DocAction.STATUS_Invalid;
}
// User Validation
String valid = ModelValidationEngine.get().fireDocValidate(this, ModelValidator.TIMING_AFTER_COMPLETE);
if (valid != null)

View File

@ -22,8 +22,11 @@ import java.sql.Timestamp;
import java.util.Properties;
import java.util.logging.Level;
import org.adempiere.exceptions.AdempiereException;
import org.adempiere.exceptions.NegativeInventoryDisallowedException;
import org.compiere.util.DB;
import org.compiere.util.Env;
import org.compiere.util.Msg;
/**
* Project Issue Model
@ -172,6 +175,8 @@ public class MProjectIssue extends X_C_ProjectIssue
dateMPolicy = t;
}
try
{
if (MStorageOnHand.add(getCtx(), loc.getM_Warehouse_ID(), getM_Locator_ID(),
getM_Product_ID(), getM_AttributeSetInstance_ID(),
getMovementQty().negate(),dateMPolicy, get_TrxName()))
@ -189,6 +194,16 @@ public class MProjectIssue extends X_C_ProjectIssue
}
else
log.log(Level.SEVERE, "Storage not updated"); // OK
}
catch (NegativeInventoryDisallowedException e)
{
log.severe(e.getMessage());
StringBuilder error = new StringBuilder();
error.append(Msg.getElement(getCtx(), "Line")).append(" ").append(getLine()).append(": ");
error.append(e.getMessage()).append("\n");
throw new AdempiereException(error.toString());
}
//
return false;
} // process

View File

@ -27,11 +27,10 @@ import java.util.List;
import java.util.Properties;
import java.util.logging.Level;
import org.adempiere.exceptions.AdempiereException;
import org.adempiere.exceptions.NegativeInventoryDisallowedException;
import org.compiere.util.CLogger;
import org.compiere.util.DB;
import org.compiere.util.Env;
import org.compiere.util.Msg;
import org.compiere.util.Util;
/**
@ -735,7 +734,8 @@ public class MStorageOnHand extends X_M_StorageOnHand
if (getQtyOnHand().signum() == -1) {
MWarehouse wh = MWarehouse.get(Env.getCtx(), getM_Warehouse_ID());
if (wh.isDisallowNegativeInv()) {
throw new AdempiereException(Msg.getMsg(Env.getCtx(), "NegativeInventoryDisallowed"));
throw new NegativeInventoryDisallowedException(getCtx(), getM_Warehouse_ID(), getM_Product_ID(), getM_AttributeSetInstance_ID(), getM_Locator_ID(),
getQtyOnHand().subtract(addition), addition.negate());
}
}
}
@ -899,13 +899,15 @@ public class MStorageOnHand extends X_M_StorageOnHand
if (getQtyOnHand().compareTo(BigDecimal.ZERO) < 0 ||
QtyOnHand.compareTo(Env.ZERO) < 0)
{
log.saveError("Error", Msg.getMsg(getCtx(), "NegativeInventoryDisallowed"));
log.saveError("Error", new NegativeInventoryDisallowedException(getCtx(), getM_Warehouse_ID(), getM_Product_ID(),
getM_AttributeSetInstance_ID(), getM_Locator_ID(), QtyOnHand.subtract(getQtyOnHand()), getQtyOnHand().negate()));
return false;
}
if (getM_AttributeSetInstance_ID() > 0 && getQtyOnHand().signum() < 0)
{
log.saveError("Error", Msg.getMsg(getCtx(), "NegativeInventoryDisallowed"));
log.saveError("Error", new NegativeInventoryDisallowedException(getCtx(), getM_Warehouse_ID(), getM_Product_ID(),
getM_AttributeSetInstance_ID(), getM_Locator_ID(), QtyOnHand.subtract(getQtyOnHand()), getQtyOnHand().negate()));
return false;
}
}

View File

@ -27,6 +27,7 @@ import java.util.Properties;
import java.util.logging.Level;
import org.adempiere.exceptions.AdempiereException;
import org.adempiere.exceptions.NegativeInventoryDisallowedException;
import org.compiere.model.MBPartner;
import org.compiere.model.MBPartnerLocation;
import org.compiere.model.MDocType;
@ -847,6 +848,7 @@ public class MDDOrder extends X_DD_Order implements DocAction
BigDecimal Volume = Env.ZERO;
BigDecimal Weight = Env.ZERO;
StringBuilder errors = new StringBuilder();
// Always check and (un) Reserve Inventory
for (MDDOrderLine line : lines)
{
@ -873,6 +875,8 @@ public class MDDOrder extends X_DD_Order implements DocAction
// Check Product - Stocked and Item
MProduct product = line.getProduct();
if (product != null)
{
try
{
if (product.isStocked())
{
@ -900,9 +904,19 @@ public class MDDOrder extends X_DD_Order implements DocAction
//
Volume = Volume.add(product.getVolume().multiply(line.getQtyOrdered()));
Weight = Weight.add(product.getWeight().multiply(line.getQtyOrdered()));
}
catch (NegativeInventoryDisallowedException e)
{
log.severe(e.getMessage());
errors.append(Msg.getElement(getCtx(), "Line")).append(" ").append(line.getLine()).append(": ");
errors.append(e.getMessage()).append("\n");
}
} // product
} // reverse inventory
if (errors.toString().length() > 0)
throw new AdempiereException(errors.toString());
setVolume(Volume);
setWeight(Weight);
} // reserveStock