IDEMPIERE-3488 Improvement to Error Message for Negative Inventory Disallow exception
This commit is contained in:
parent
8f0c185141
commit
e3961c7d61
|
@ -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
|
||||||
|
;
|
||||||
|
|
|
@ -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
|
||||||
|
;
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -26,6 +26,7 @@ import java.util.Properties;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
import org.adempiere.exceptions.AdempiereException;
|
import org.adempiere.exceptions.AdempiereException;
|
||||||
|
import org.adempiere.exceptions.NegativeInventoryDisallowedException;
|
||||||
import org.adempiere.exceptions.PeriodClosedException;
|
import org.adempiere.exceptions.PeriodClosedException;
|
||||||
import org.compiere.print.MPrintFormat;
|
import org.compiere.print.MPrintFormat;
|
||||||
import org.compiere.print.ReportEngine;
|
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());
|
if (log.isLoggable(Level.INFO)) log.info(toString());
|
||||||
StringBuilder info = new StringBuilder();
|
StringBuilder info = new StringBuilder();
|
||||||
|
|
||||||
|
StringBuilder errors = new StringBuilder();
|
||||||
// For all lines
|
// For all lines
|
||||||
MInOutLine[] lines = getLines(false);
|
MInOutLine[] lines = getLines(false);
|
||||||
for (int lineIndex = 0; lineIndex < lines.length; lineIndex++)
|
for (int lineIndex = 0; lineIndex < lines.length; lineIndex++)
|
||||||
|
@ -1293,353 +1295,326 @@ public class MInOut extends X_M_InOut implements DocAction
|
||||||
MInOutLine sLine = lines[lineIndex];
|
MInOutLine sLine = lines[lineIndex];
|
||||||
MProduct product = sLine.getProduct();
|
MProduct product = sLine.getProduct();
|
||||||
|
|
||||||
// Qty & Type
|
try
|
||||||
String MovementType = getMovementType();
|
|
||||||
BigDecimal Qty = sLine.getMovementQty();
|
|
||||||
if (MovementType.charAt(1) == '-') // C- Customer Shipment - V- Vendor Return
|
|
||||||
Qty = Qty.negate();
|
|
||||||
|
|
||||||
// Update Order Line
|
|
||||||
MOrderLine oLine = null;
|
|
||||||
if (sLine.getC_OrderLine_ID() != 0)
|
|
||||||
{
|
{
|
||||||
oLine = new MOrderLine (getCtx(), sLine.getC_OrderLine_ID(), get_TrxName());
|
// Qty & Type
|
||||||
if (log.isLoggable(Level.FINE)) log.fine("OrderLine - Reserved=" + oLine.getQtyReserved()
|
String MovementType = getMovementType();
|
||||||
+ ", Delivered=" + oLine.getQtyDelivered());
|
BigDecimal Qty = sLine.getMovementQty();
|
||||||
}
|
if (MovementType.charAt(1) == '-') // C- Customer Shipment - V- Vendor Return
|
||||||
|
Qty = Qty.negate();
|
||||||
|
|
||||||
// Load RMA Line
|
// Update Order Line
|
||||||
MRMALine rmaLine = null;
|
MOrderLine oLine = null;
|
||||||
|
if (sLine.getC_OrderLine_ID() != 0)
|
||||||
if (sLine.getM_RMALine_ID() != 0)
|
|
||||||
{
|
|
||||||
rmaLine = new MRMALine(getCtx(), sLine.getM_RMALine_ID(), get_TrxName());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (log.isLoggable(Level.INFO)) log.info("Line=" + sLine.getLine() + " - Qty=" + sLine.getMovementQty());
|
|
||||||
|
|
||||||
// Stock Movement - Counterpart MOrder.reserveStock
|
|
||||||
if (product != null
|
|
||||||
&& product.isStocked() )
|
|
||||||
{
|
|
||||||
//Ignore the Material Policy when is Reverse Correction
|
|
||||||
if(!isReversal())
|
|
||||||
{
|
{
|
||||||
BigDecimal movementQty = sLine.getMovementQty();
|
oLine = new MOrderLine (getCtx(), sLine.getC_OrderLine_ID(), get_TrxName());
|
||||||
BigDecimal qtyOnLineMA = MInOutLineMA.getManualQty(sLine.getM_InOutLine_ID(), get_TrxName());
|
if (log.isLoggable(Level.FINE)) log.fine("OrderLine - Reserved=" + oLine.getQtyReserved()
|
||||||
|
+ ", Delivered=" + oLine.getQtyDelivered());
|
||||||
if ( (movementQty.signum() != 0 && qtyOnLineMA.signum() != 0 && movementQty.signum() != qtyOnLineMA.signum()) // must have same sign
|
|
||||||
|| (qtyOnLineMA.abs().compareTo(movementQty.abs())>0)) { // compare absolute values
|
|
||||||
// More then line qty on attribute tab for line 10
|
|
||||||
m_processMsg = "@Over_Qty_On_Attribute_Tab@ " + sLine.getLine();
|
|
||||||
return DOCSTATUS_Invalid;
|
|
||||||
}
|
|
||||||
|
|
||||||
checkMaterialPolicy(sLine,movementQty.subtract(qtyOnLineMA));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
log.fine("Material Transaction");
|
|
||||||
MTransaction mtrx = null;
|
// Load RMA Line
|
||||||
|
MRMALine rmaLine = null;
|
||||||
//
|
|
||||||
BigDecimal overReceipt = BigDecimal.ZERO;
|
if (sLine.getM_RMALine_ID() != 0)
|
||||||
if (!isReversal())
|
{
|
||||||
|
rmaLine = new MRMALine(getCtx(), sLine.getM_RMALine_ID(), get_TrxName());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (log.isLoggable(Level.INFO)) log.info("Line=" + sLine.getLine() + " - Qty=" + sLine.getMovementQty());
|
||||||
|
|
||||||
|
// Stock Movement - Counterpart MOrder.reserveStock
|
||||||
|
if (product != null
|
||||||
|
&& product.isStocked() )
|
||||||
{
|
{
|
||||||
if (oLine != null)
|
//Ignore the Material Policy when is Reverse Correction
|
||||||
|
if(!isReversal())
|
||||||
{
|
{
|
||||||
BigDecimal toDelivered = oLine.getQtyOrdered()
|
BigDecimal movementQty = sLine.getMovementQty();
|
||||||
.subtract(oLine.getQtyDelivered());
|
BigDecimal qtyOnLineMA = MInOutLineMA.getManualQty(sLine.getM_InOutLine_ID(), get_TrxName());
|
||||||
if (toDelivered.signum() < 0) // IDEMPIERE-2889
|
|
||||||
toDelivered = Env.ZERO;
|
if ( (movementQty.signum() != 0 && qtyOnLineMA.signum() != 0 && movementQty.signum() != qtyOnLineMA.signum()) // must have same sign
|
||||||
if (sLine.getMovementQty().compareTo(toDelivered) > 0)
|
|| (qtyOnLineMA.abs().compareTo(movementQty.abs())>0)) { // compare absolute values
|
||||||
overReceipt = sLine.getMovementQty().subtract(
|
// More then line qty on attribute tab for line 10
|
||||||
toDelivered);
|
m_processMsg = "@Over_Qty_On_Attribute_Tab@ " + sLine.getLine();
|
||||||
if (overReceipt.signum() != 0)
|
return DOCSTATUS_Invalid;
|
||||||
{
|
|
||||||
sLine.setQtyOverReceipt(overReceipt);
|
|
||||||
sLine.saveEx();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkMaterialPolicy(sLine,movementQty.subtract(qtyOnLineMA));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
log.fine("Material Transaction");
|
||||||
{
|
MTransaction mtrx = null;
|
||||||
overReceipt = sLine.getQtyOverReceipt();
|
|
||||||
}
|
//
|
||||||
BigDecimal orderedQtyToUpdate = sLine.getMovementQty().subtract(overReceipt);
|
BigDecimal overReceipt = BigDecimal.ZERO;
|
||||||
//
|
if (!isReversal())
|
||||||
if (sLine.getM_AttributeSetInstance_ID() == 0)
|
|
||||||
{
|
|
||||||
MInOutLineMA mas[] = MInOutLineMA.get(getCtx(),
|
|
||||||
sLine.getM_InOutLine_ID(), get_TrxName());
|
|
||||||
for (int j = 0; j < mas.length; j++)
|
|
||||||
{
|
{
|
||||||
MInOutLineMA ma = mas[j];
|
if (oLine != null)
|
||||||
BigDecimal QtyMA = ma.getMovementQty();
|
{
|
||||||
if (MovementType.charAt(1) == '-') // C- Customer Shipment - V- Vendor Return
|
BigDecimal toDelivered = oLine.getQtyOrdered()
|
||||||
QtyMA = QtyMA.negate();
|
.subtract(oLine.getQtyDelivered());
|
||||||
|
if (toDelivered.signum() < 0) // IDEMPIERE-2889
|
||||||
// Update Storage - see also VMatch.createMatchRecord
|
toDelivered = Env.ZERO;
|
||||||
|
if (sLine.getMovementQty().compareTo(toDelivered) > 0)
|
||||||
|
overReceipt = sLine.getMovementQty().subtract(
|
||||||
|
toDelivered);
|
||||||
|
if (overReceipt.signum() != 0)
|
||||||
|
{
|
||||||
|
sLine.setQtyOverReceipt(overReceipt);
|
||||||
|
sLine.saveEx();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
overReceipt = sLine.getQtyOverReceipt();
|
||||||
|
}
|
||||||
|
BigDecimal orderedQtyToUpdate = sLine.getMovementQty().subtract(overReceipt);
|
||||||
|
//
|
||||||
|
if (sLine.getM_AttributeSetInstance_ID() == 0)
|
||||||
|
{
|
||||||
|
MInOutLineMA mas[] = MInOutLineMA.get(getCtx(),
|
||||||
|
sLine.getM_InOutLine_ID(), get_TrxName());
|
||||||
|
for (int j = 0; j < mas.length; j++)
|
||||||
|
{
|
||||||
|
MInOutLineMA ma = mas[j];
|
||||||
|
BigDecimal QtyMA = ma.getMovementQty();
|
||||||
|
if (MovementType.charAt(1) == '-') // C- Customer Shipment - V- Vendor Return
|
||||||
|
QtyMA = QtyMA.negate();
|
||||||
|
|
||||||
|
// Update Storage - see also VMatch.createMatchRecord
|
||||||
|
if (!MStorageOnHand.add(getCtx(), getM_Warehouse_ID(),
|
||||||
|
sLine.getM_Locator_ID(),
|
||||||
|
sLine.getM_Product_ID(),
|
||||||
|
ma.getM_AttributeSetInstance_ID(),
|
||||||
|
QtyMA,ma.getDateMaterialPolicy(),
|
||||||
|
get_TrxName()))
|
||||||
|
{
|
||||||
|
String lastError = CLogger.retrieveErrorString("");
|
||||||
|
m_processMsg = "Cannot correct Inventory OnHand (MA) [" + product.getValue() + "] - " + lastError;
|
||||||
|
return DocAction.STATUS_Invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create Transaction
|
||||||
|
mtrx = new MTransaction (getCtx(), sLine.getAD_Org_ID(),
|
||||||
|
MovementType, sLine.getM_Locator_ID(),
|
||||||
|
sLine.getM_Product_ID(), ma.getM_AttributeSetInstance_ID(),
|
||||||
|
QtyMA, getMovementDate(), get_TrxName());
|
||||||
|
mtrx.setM_InOutLine_ID(sLine.getM_InOutLine_ID());
|
||||||
|
if (!mtrx.save())
|
||||||
|
{
|
||||||
|
m_processMsg = "Could not create Material Transaction (MA) [" + product.getValue() + "]";
|
||||||
|
return DocAction.STATUS_Invalid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (oLine!=null && mtrx!=null && oLine.getQtyOrdered().signum() > 0)
|
||||||
|
{
|
||||||
|
if (sLine.getC_OrderLine_ID() != 0)
|
||||||
|
{
|
||||||
|
if (!MStorageReservation.add(getCtx(), oLine.getM_Warehouse_ID(),
|
||||||
|
sLine.getM_Product_ID(),
|
||||||
|
oLine.getM_AttributeSetInstance_ID(),
|
||||||
|
orderedQtyToUpdate.negate(),
|
||||||
|
isSOTrx(),
|
||||||
|
get_TrxName()))
|
||||||
|
{
|
||||||
|
String lastError = CLogger.retrieveErrorString("");
|
||||||
|
m_processMsg = "Cannot correct Inventory " + (isSOTrx()? "Reserved" : "Ordered") + " (MA) - [" + product.getValue() + "] - " + lastError;
|
||||||
|
return DocAction.STATUS_Invalid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
// sLine.getM_AttributeSetInstance_ID() != 0
|
||||||
|
if (mtrx == null)
|
||||||
|
{
|
||||||
|
Timestamp dateMPolicy= null;
|
||||||
|
MStorageOnHand[] storages = MStorageOnHand.getWarehouse(getCtx(), 0,
|
||||||
|
sLine.getM_Product_ID(), sLine.getM_AttributeSetInstance_ID(), null,
|
||||||
|
MClient.MMPOLICY_FiFo.equals(product.getMMPolicy()), false,
|
||||||
|
sLine.getM_Locator_ID(), get_TrxName());
|
||||||
|
for (MStorageOnHand storage : storages) {
|
||||||
|
if (storage.getQtyOnHand().compareTo(sLine.getMovementQty()) >= 0) {
|
||||||
|
dateMPolicy = storage.getDateMaterialPolicy();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dateMPolicy == null && storages.length > 0)
|
||||||
|
dateMPolicy = storages[0].getDateMaterialPolicy();
|
||||||
|
|
||||||
|
if(dateMPolicy==null)
|
||||||
|
dateMPolicy = getMovementDate();
|
||||||
|
|
||||||
|
// Fallback: Update Storage - see also VMatch.createMatchRecord
|
||||||
if (!MStorageOnHand.add(getCtx(), getM_Warehouse_ID(),
|
if (!MStorageOnHand.add(getCtx(), getM_Warehouse_ID(),
|
||||||
sLine.getM_Locator_ID(),
|
sLine.getM_Locator_ID(),
|
||||||
sLine.getM_Product_ID(),
|
sLine.getM_Product_ID(),
|
||||||
ma.getM_AttributeSetInstance_ID(),
|
sLine.getM_AttributeSetInstance_ID(),
|
||||||
QtyMA,ma.getDateMaterialPolicy(),
|
Qty,dateMPolicy,get_TrxName()))
|
||||||
get_TrxName()))
|
|
||||||
{
|
{
|
||||||
String lastError = CLogger.retrieveErrorString("");
|
String lastError = CLogger.retrieveErrorString("");
|
||||||
m_processMsg = "Cannot correct Inventory OnHand (MA) [" + product.getValue() + "] - " + lastError;
|
m_processMsg = "Cannot correct Inventory OnHand [" + product.getValue() + "] - " + lastError;
|
||||||
return DocAction.STATUS_Invalid;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create Transaction
|
|
||||||
mtrx = new MTransaction (getCtx(), sLine.getAD_Org_ID(),
|
|
||||||
MovementType, sLine.getM_Locator_ID(),
|
|
||||||
sLine.getM_Product_ID(), ma.getM_AttributeSetInstance_ID(),
|
|
||||||
QtyMA, getMovementDate(), get_TrxName());
|
|
||||||
mtrx.setM_InOutLine_ID(sLine.getM_InOutLine_ID());
|
|
||||||
if (!mtrx.save())
|
|
||||||
{
|
|
||||||
m_processMsg = "Could not create Material Transaction (MA) [" + product.getValue() + "]";
|
|
||||||
return DocAction.STATUS_Invalid;
|
return DocAction.STATUS_Invalid;
|
||||||
}
|
}
|
||||||
}
|
if (oLine!=null && oLine.getQtyOrdered().signum() > 0)
|
||||||
|
|
||||||
if (oLine!=null && mtrx!=null && oLine.getQtyOrdered().signum() > 0)
|
|
||||||
{
|
|
||||||
if (sLine.getC_OrderLine_ID() != 0)
|
|
||||||
{
|
{
|
||||||
if (!MStorageReservation.add(getCtx(), oLine.getM_Warehouse_ID(),
|
if (!MStorageReservation.add(getCtx(), oLine.getM_Warehouse_ID(),
|
||||||
sLine.getM_Product_ID(),
|
sLine.getM_Product_ID(),
|
||||||
oLine.getM_AttributeSetInstance_ID(),
|
oLine.getM_AttributeSetInstance_ID(),
|
||||||
orderedQtyToUpdate.negate(),
|
orderedQtyToUpdate.negate(), isSOTrx(), get_TrxName()))
|
||||||
isSOTrx(),
|
|
||||||
get_TrxName()))
|
|
||||||
{
|
{
|
||||||
String lastError = CLogger.retrieveErrorString("");
|
m_processMsg = "Cannot correct Inventory Reserved " + (isSOTrx()? "Reserved [" :"Ordered [") + product.getValue() + "]";
|
||||||
m_processMsg = "Cannot correct Inventory " + (isSOTrx()? "Reserved" : "Ordered") + " (MA) - [" + product.getValue() + "] - " + lastError;
|
|
||||||
return DocAction.STATUS_Invalid;
|
return DocAction.STATUS_Invalid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
// FallBack: Create Transaction
|
||||||
}
|
mtrx = new MTransaction (getCtx(), sLine.getAD_Org_ID(),
|
||||||
// sLine.getM_AttributeSetInstance_ID() != 0
|
MovementType, sLine.getM_Locator_ID(),
|
||||||
if (mtrx == null)
|
sLine.getM_Product_ID(), sLine.getM_AttributeSetInstance_ID(),
|
||||||
{
|
Qty, getMovementDate(), get_TrxName());
|
||||||
Timestamp dateMPolicy= null;
|
mtrx.setM_InOutLine_ID(sLine.getM_InOutLine_ID());
|
||||||
MStorageOnHand[] storages = MStorageOnHand.getWarehouse(getCtx(), 0,
|
if (!mtrx.save())
|
||||||
sLine.getM_Product_ID(), sLine.getM_AttributeSetInstance_ID(), null,
|
|
||||||
MClient.MMPOLICY_FiFo.equals(product.getMMPolicy()), false,
|
|
||||||
sLine.getM_Locator_ID(), get_TrxName());
|
|
||||||
for (MStorageOnHand storage : storages) {
|
|
||||||
if (storage.getQtyOnHand().compareTo(sLine.getMovementQty()) >= 0) {
|
|
||||||
dateMPolicy = storage.getDateMaterialPolicy();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dateMPolicy == null && storages.length > 0)
|
|
||||||
dateMPolicy = storages[0].getDateMaterialPolicy();
|
|
||||||
|
|
||||||
if(dateMPolicy==null)
|
|
||||||
dateMPolicy = getMovementDate();
|
|
||||||
|
|
||||||
// Fallback: Update Storage - see also VMatch.createMatchRecord
|
|
||||||
if (!MStorageOnHand.add(getCtx(), getM_Warehouse_ID(),
|
|
||||||
sLine.getM_Locator_ID(),
|
|
||||||
sLine.getM_Product_ID(),
|
|
||||||
sLine.getM_AttributeSetInstance_ID(),
|
|
||||||
Qty,dateMPolicy,get_TrxName()))
|
|
||||||
{
|
|
||||||
String lastError = CLogger.retrieveErrorString("");
|
|
||||||
m_processMsg = "Cannot correct Inventory OnHand [" + product.getValue() + "] - " + lastError;
|
|
||||||
return DocAction.STATUS_Invalid;
|
|
||||||
}
|
|
||||||
if (oLine!=null && oLine.getQtyOrdered().signum() > 0)
|
|
||||||
{
|
|
||||||
if (!MStorageReservation.add(getCtx(), oLine.getM_Warehouse_ID(),
|
|
||||||
sLine.getM_Product_ID(),
|
|
||||||
oLine.getM_AttributeSetInstance_ID(),
|
|
||||||
orderedQtyToUpdate.negate(), isSOTrx(), get_TrxName()))
|
|
||||||
{
|
{
|
||||||
m_processMsg = "Cannot correct Inventory Reserved " + (isSOTrx()? "Reserved [" :"Ordered [") + product.getValue() + "]";
|
m_processMsg = CLogger.retrieveErrorString("Could not create Material Transaction [" + product.getValue() + "]");
|
||||||
return DocAction.STATUS_Invalid;
|
return DocAction.STATUS_Invalid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} // stock movement
|
||||||
// FallBack: Create Transaction
|
|
||||||
mtrx = new MTransaction (getCtx(), sLine.getAD_Org_ID(),
|
// Correct Order Line
|
||||||
MovementType, sLine.getM_Locator_ID(),
|
if (product != null && oLine != null) // other in VMatch.createMatchRecord
|
||||||
sLine.getM_Product_ID(), sLine.getM_AttributeSetInstance_ID(),
|
{
|
||||||
Qty, getMovementDate(), get_TrxName());
|
oLine.setQtyReserved(oLine.getQtyReserved().subtract(sLine.getMovementQty().subtract(sLine.getQtyOverReceipt())));
|
||||||
mtrx.setM_InOutLine_ID(sLine.getM_InOutLine_ID());
|
}
|
||||||
if (!mtrx.save())
|
|
||||||
|
// Update Sales Order Line
|
||||||
|
if (oLine != null)
|
||||||
|
{
|
||||||
|
if (isSOTrx() // PO is done by Matching
|
||||||
|
|| sLine.getM_Product_ID() == 0) // PO Charges, empty lines
|
||||||
{
|
{
|
||||||
m_processMsg = CLogger.retrieveErrorString("Could not create Material Transaction [" + product.getValue() + "]");
|
if (isSOTrx())
|
||||||
|
oLine.setQtyDelivered(oLine.getQtyDelivered().subtract(Qty));
|
||||||
|
else
|
||||||
|
oLine.setQtyDelivered(oLine.getQtyDelivered().add(Qty));
|
||||||
|
oLine.setDateDelivered(getMovementDate()); // overwrite=last
|
||||||
|
}
|
||||||
|
if (!oLine.save())
|
||||||
|
{
|
||||||
|
m_processMsg = "Could not update Order Line";
|
||||||
return DocAction.STATUS_Invalid;
|
return DocAction.STATUS_Invalid;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} // stock movement
|
|
||||||
|
|
||||||
// Correct Order Line
|
|
||||||
if (product != null && oLine != null) // other in VMatch.createMatchRecord
|
|
||||||
{
|
|
||||||
oLine.setQtyReserved(oLine.getQtyReserved().subtract(sLine.getMovementQty().subtract(sLine.getQtyOverReceipt())));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update Sales Order Line
|
|
||||||
if (oLine != null)
|
|
||||||
{
|
|
||||||
if (isSOTrx() // PO is done by Matching
|
|
||||||
|| sLine.getM_Product_ID() == 0) // PO Charges, empty lines
|
|
||||||
{
|
|
||||||
if (isSOTrx())
|
|
||||||
oLine.setQtyDelivered(oLine.getQtyDelivered().subtract(Qty));
|
|
||||||
else
|
else
|
||||||
oLine.setQtyDelivered(oLine.getQtyDelivered().add(Qty));
|
if (log.isLoggable(Level.FINE)) log.fine("OrderLine -> Reserved=" + oLine.getQtyReserved()
|
||||||
oLine.setDateDelivered(getMovementDate()); // overwrite=last
|
+ ", Delivered=" + oLine.getQtyReserved());
|
||||||
}
|
}
|
||||||
if (!oLine.save())
|
// Update RMA Line Qty Delivered
|
||||||
|
else if (rmaLine != null)
|
||||||
|
{
|
||||||
|
if (isSOTrx())
|
||||||
|
{
|
||||||
|
rmaLine.setQtyDelivered(rmaLine.getQtyDelivered().add(Qty));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rmaLine.setQtyDelivered(rmaLine.getQtyDelivered().subtract(Qty));
|
||||||
|
}
|
||||||
|
if (!rmaLine.save())
|
||||||
|
{
|
||||||
|
m_processMsg = "Could not update RMA Line";
|
||||||
|
return DocAction.STATUS_Invalid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create Asset for SO
|
||||||
|
if (product != null
|
||||||
|
&& isSOTrx()
|
||||||
|
&& product.isCreateAsset()
|
||||||
|
&& !product.getM_Product_Category().getA_Asset_Group().isFixedAsset()
|
||||||
|
&& sLine.getMovementQty().signum() > 0
|
||||||
|
&& !isReversal())
|
||||||
{
|
{
|
||||||
m_processMsg = "Could not update Order Line";
|
log.fine("Asset");
|
||||||
return DocAction.STATUS_Invalid;
|
info.append("@A_Asset_ID@: ");
|
||||||
}
|
int noAssets = sLine.getMovementQty().intValue();
|
||||||
else
|
|
||||||
if (log.isLoggable(Level.FINE)) log.fine("OrderLine -> Reserved=" + oLine.getQtyReserved()
|
|
||||||
+ ", Delivered=" + oLine.getQtyReserved());
|
|
||||||
}
|
|
||||||
// Update RMA Line Qty Delivered
|
|
||||||
else if (rmaLine != null)
|
|
||||||
{
|
|
||||||
if (isSOTrx())
|
|
||||||
{
|
|
||||||
rmaLine.setQtyDelivered(rmaLine.getQtyDelivered().add(Qty));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rmaLine.setQtyDelivered(rmaLine.getQtyDelivered().subtract(Qty));
|
|
||||||
}
|
|
||||||
if (!rmaLine.save())
|
|
||||||
{
|
|
||||||
m_processMsg = "Could not update RMA Line";
|
|
||||||
return DocAction.STATUS_Invalid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create Asset for SO
|
|
||||||
if (product != null
|
|
||||||
&& isSOTrx()
|
|
||||||
&& product.isCreateAsset()
|
|
||||||
&& !product.getM_Product_Category().getA_Asset_Group().isFixedAsset()
|
|
||||||
&& sLine.getMovementQty().signum() > 0
|
|
||||||
&& !isReversal())
|
|
||||||
{
|
|
||||||
log.fine("Asset");
|
|
||||||
info.append("@A_Asset_ID@: ");
|
|
||||||
int noAssets = sLine.getMovementQty().intValue();
|
|
||||||
if (!product.isOneAssetPerUOM())
|
|
||||||
noAssets = 1;
|
|
||||||
for (int i = 0; i < noAssets; i++)
|
|
||||||
{
|
|
||||||
if (i > 0)
|
|
||||||
info.append(" - ");
|
|
||||||
int deliveryCount = i+1;
|
|
||||||
if (!product.isOneAssetPerUOM())
|
if (!product.isOneAssetPerUOM())
|
||||||
deliveryCount = 0;
|
noAssets = 1;
|
||||||
MAsset asset = new MAsset (this, sLine, deliveryCount);
|
for (int i = 0; i < noAssets; i++)
|
||||||
if (!asset.save(get_TrxName()))
|
|
||||||
{
|
{
|
||||||
m_processMsg = "Could not create Asset";
|
if (i > 0)
|
||||||
return DocAction.STATUS_Invalid;
|
info.append(" - ");
|
||||||
}
|
int deliveryCount = i+1;
|
||||||
info.append(asset.getValue());
|
if (!product.isOneAssetPerUOM())
|
||||||
}
|
deliveryCount = 0;
|
||||||
} // Asset
|
MAsset asset = new MAsset (this, sLine, deliveryCount);
|
||||||
|
if (!asset.save(get_TrxName()))
|
||||||
|
|
||||||
// Matching
|
|
||||||
if (!isSOTrx()
|
|
||||||
&& sLine.getM_Product_ID() != 0
|
|
||||||
&& !isReversal())
|
|
||||||
{
|
|
||||||
BigDecimal matchQty = sLine.getMovementQty();
|
|
||||||
// Invoice - Receipt Match (requires Product)
|
|
||||||
MInvoiceLine iLine = MInvoiceLine.getOfInOutLine (sLine);
|
|
||||||
if (iLine != null && iLine.getM_Product_ID() != 0)
|
|
||||||
{
|
|
||||||
if (matchQty.compareTo(iLine.getQtyInvoiced())>0)
|
|
||||||
matchQty = iLine.getQtyInvoiced();
|
|
||||||
|
|
||||||
MMatchInv[] matches = MMatchInv.get(getCtx(),
|
|
||||||
sLine.getM_InOutLine_ID(), iLine.getC_InvoiceLine_ID(), get_TrxName());
|
|
||||||
if (matches == null || matches.length == 0)
|
|
||||||
{
|
|
||||||
MMatchInv inv = new MMatchInv (iLine, getMovementDate(), matchQty);
|
|
||||||
if (sLine.getM_AttributeSetInstance_ID() != iLine.getM_AttributeSetInstance_ID())
|
|
||||||
{
|
{
|
||||||
iLine.setM_AttributeSetInstance_ID(sLine.getM_AttributeSetInstance_ID());
|
m_processMsg = "Could not create Asset";
|
||||||
iLine.saveEx(); // update matched invoice with ASI
|
|
||||||
inv.setM_AttributeSetInstance_ID(sLine.getM_AttributeSetInstance_ID());
|
|
||||||
}
|
|
||||||
if (!inv.save(get_TrxName()))
|
|
||||||
{
|
|
||||||
m_processMsg = CLogger.retrieveErrorString("Could not create Inv Matching");
|
|
||||||
return DocAction.STATUS_Invalid;
|
return DocAction.STATUS_Invalid;
|
||||||
}
|
}
|
||||||
addDocsPostProcess(inv);
|
info.append(asset.getValue());
|
||||||
}
|
}
|
||||||
}
|
} // Asset
|
||||||
|
|
||||||
// Link to Order
|
|
||||||
if (sLine.getC_OrderLine_ID() != 0)
|
// Matching
|
||||||
|
if (!isSOTrx()
|
||||||
|
&& sLine.getM_Product_ID() != 0
|
||||||
|
&& !isReversal())
|
||||||
{
|
{
|
||||||
log.fine("PO Matching");
|
BigDecimal matchQty = sLine.getMovementQty();
|
||||||
// Ship - PO
|
// Invoice - Receipt Match (requires Product)
|
||||||
MMatchPO po = MMatchPO.create (null, sLine, getMovementDate(), matchQty);
|
MInvoiceLine iLine = MInvoiceLine.getOfInOutLine (sLine);
|
||||||
if (po != null) {
|
if (iLine != null && iLine.getM_Product_ID() != 0)
|
||||||
if (!po.save(get_TrxName()))
|
{
|
||||||
|
if (matchQty.compareTo(iLine.getQtyInvoiced())>0)
|
||||||
|
matchQty = iLine.getQtyInvoiced();
|
||||||
|
|
||||||
|
MMatchInv[] matches = MMatchInv.get(getCtx(),
|
||||||
|
sLine.getM_InOutLine_ID(), iLine.getC_InvoiceLine_ID(), get_TrxName());
|
||||||
|
if (matches == null || matches.length == 0)
|
||||||
{
|
{
|
||||||
m_processMsg = "Could not create PO Matching";
|
MMatchInv inv = new MMatchInv (iLine, getMovementDate(), matchQty);
|
||||||
return DocAction.STATUS_Invalid;
|
if (sLine.getM_AttributeSetInstance_ID() != iLine.getM_AttributeSetInstance_ID())
|
||||||
}
|
{
|
||||||
if (!po.isPosted())
|
iLine.setM_AttributeSetInstance_ID(sLine.getM_AttributeSetInstance_ID());
|
||||||
addDocsPostProcess(po);
|
iLine.saveEx(); // update matched invoice with ASI
|
||||||
MMatchInv matchInvCreated = po.getMatchInvCreated();
|
inv.setM_AttributeSetInstance_ID(sLine.getM_AttributeSetInstance_ID());
|
||||||
if (matchInvCreated != null) {
|
}
|
||||||
addDocsPostProcess(matchInvCreated);
|
if (!inv.save(get_TrxName()))
|
||||||
|
{
|
||||||
|
m_processMsg = CLogger.retrieveErrorString("Could not create Inv Matching");
|
||||||
|
return DocAction.STATUS_Invalid;
|
||||||
|
}
|
||||||
|
addDocsPostProcess(inv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Update PO with ASI
|
|
||||||
if ( oLine != null && oLine.getM_AttributeSetInstance_ID() == 0
|
// Link to Order
|
||||||
&& sLine.getMovementQty().compareTo(oLine.getQtyOrdered()) == 0) // just if full match [ 1876965 ]
|
if (sLine.getC_OrderLine_ID() != 0)
|
||||||
{
|
{
|
||||||
oLine.setM_AttributeSetInstance_ID(sLine.getM_AttributeSetInstance_ID());
|
log.fine("PO Matching");
|
||||||
oLine.saveEx(get_TrxName());
|
// Ship - PO
|
||||||
}
|
MMatchPO po = MMatchPO.create (null, sLine, getMovementDate(), matchQty);
|
||||||
}
|
|
||||||
else // No Order - Try finding links via Invoice
|
|
||||||
{
|
|
||||||
// Invoice has an Order Link
|
|
||||||
if (iLine != null && iLine.getC_OrderLine_ID() != 0)
|
|
||||||
{
|
|
||||||
// Invoice is created before Shipment
|
|
||||||
log.fine("PO(Inv) Matching");
|
|
||||||
// Ship - Invoice
|
|
||||||
MMatchPO po = MMatchPO.create (iLine, sLine,
|
|
||||||
getMovementDate(), matchQty);
|
|
||||||
if (po != null) {
|
if (po != null) {
|
||||||
if (!po.save(get_TrxName()))
|
if (!po.save(get_TrxName()))
|
||||||
{
|
{
|
||||||
m_processMsg = "Could not create PO(Inv) Matching";
|
m_processMsg = "Could not create PO Matching";
|
||||||
return DocAction.STATUS_Invalid;
|
return DocAction.STATUS_Invalid;
|
||||||
}
|
}
|
||||||
if (!po.isPosted())
|
if (!po.isPosted())
|
||||||
addDocsPostProcess(po);
|
addDocsPostProcess(po);
|
||||||
|
MMatchInv matchInvCreated = po.getMatchInvCreated();
|
||||||
|
if (matchInvCreated != null) {
|
||||||
|
addDocsPostProcess(matchInvCreated);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update PO with ASI
|
// Update PO with ASI
|
||||||
oLine = new MOrderLine (getCtx(), iLine.getC_OrderLine_ID(), get_TrxName());
|
|
||||||
if ( oLine != null && oLine.getM_AttributeSetInstance_ID() == 0
|
if ( oLine != null && oLine.getM_AttributeSetInstance_ID() == 0
|
||||||
&& sLine.getMovementQty().compareTo(oLine.getQtyOrdered()) == 0) // just if full match [ 1876965 ]
|
&& sLine.getMovementQty().compareTo(oLine.getQtyOrdered()) == 0) // just if full match [ 1876965 ]
|
||||||
{
|
{
|
||||||
|
@ -1647,11 +1622,52 @@ public class MInOut extends X_M_InOut implements DocAction
|
||||||
oLine.saveEx(get_TrxName());
|
oLine.saveEx(get_TrxName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // No Order
|
else // No Order - Try finding links via Invoice
|
||||||
} // PO Matching
|
{
|
||||||
|
// Invoice has an Order Link
|
||||||
|
if (iLine != null && iLine.getC_OrderLine_ID() != 0)
|
||||||
|
{
|
||||||
|
// Invoice is created before Shipment
|
||||||
|
log.fine("PO(Inv) Matching");
|
||||||
|
// Ship - Invoice
|
||||||
|
MMatchPO po = MMatchPO.create (iLine, sLine,
|
||||||
|
getMovementDate(), matchQty);
|
||||||
|
if (po != null) {
|
||||||
|
if (!po.save(get_TrxName()))
|
||||||
|
{
|
||||||
|
m_processMsg = "Could not create PO(Inv) Matching";
|
||||||
|
return DocAction.STATUS_Invalid;
|
||||||
|
}
|
||||||
|
if (!po.isPosted())
|
||||||
|
addDocsPostProcess(po);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update PO with ASI
|
||||||
|
oLine = new MOrderLine (getCtx(), iLine.getC_OrderLine_ID(), get_TrxName());
|
||||||
|
if ( oLine != null && oLine.getM_AttributeSetInstance_ID() == 0
|
||||||
|
&& sLine.getMovementQty().compareTo(oLine.getQtyOrdered()) == 0) // just if full match [ 1876965 ]
|
||||||
|
{
|
||||||
|
oLine.setM_AttributeSetInstance_ID(sLine.getM_AttributeSetInstance_ID());
|
||||||
|
oLine.saveEx(get_TrxName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // 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
|
} // for all lines
|
||||||
|
|
||||||
|
if (errors.toString().length() > 0)
|
||||||
|
{
|
||||||
|
m_processMsg = errors.toString();
|
||||||
|
return DocAction.STATUS_Invalid;
|
||||||
|
}
|
||||||
|
|
||||||
// Counter Documents
|
// Counter Documents
|
||||||
MInOut counter = createCounterDoc();
|
MInOut counter = createCounterDoc();
|
||||||
if (counter != null)
|
if (counter != null)
|
||||||
|
|
|
@ -24,6 +24,7 @@ import java.util.List;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
|
import org.adempiere.exceptions.NegativeInventoryDisallowedException;
|
||||||
import org.adempiere.exceptions.PeriodClosedException;
|
import org.adempiere.exceptions.PeriodClosedException;
|
||||||
import org.compiere.process.DocAction;
|
import org.compiere.process.DocAction;
|
||||||
import org.compiere.process.DocumentEngine;
|
import org.compiere.process.DocumentEngine;
|
||||||
|
@ -435,6 +436,7 @@ public class MInventory extends X_M_Inventory implements DocAction
|
||||||
approveIt();
|
approveIt();
|
||||||
if (log.isLoggable(Level.INFO)) log.info(toString());
|
if (log.isLoggable(Level.INFO)) log.info(toString());
|
||||||
|
|
||||||
|
StringBuilder errors = new StringBuilder();
|
||||||
MInventoryLine[] lines = getLines(false);
|
MInventoryLine[] lines = getLines(false);
|
||||||
for (MInventoryLine line : lines)
|
for (MInventoryLine line : lines)
|
||||||
{
|
{
|
||||||
|
@ -442,98 +444,159 @@ public class MInventory extends X_M_Inventory implements DocAction
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
MProduct product = line.getProduct();
|
MProduct product = line.getProduct();
|
||||||
|
try
|
||||||
BigDecimal qtyDiff = Env.ZERO;
|
|
||||||
if (MDocType.DOCSUBTYPEINV_InternalUseInventory.equals(docSubTypeInv))
|
|
||||||
qtyDiff = line.getQtyInternalUse().negate();
|
|
||||||
else if (MDocType.DOCSUBTYPEINV_PhysicalInventory.equals(docSubTypeInv))
|
|
||||||
qtyDiff = line.getQtyCount().subtract(line.getQtyBook());
|
|
||||||
else if (MDocType.DOCSUBTYPEINV_CostAdjustment.equals(docSubTypeInv))
|
|
||||||
{
|
{
|
||||||
if (!isReversal())
|
BigDecimal qtyDiff = Env.ZERO;
|
||||||
|
if (MDocType.DOCSUBTYPEINV_InternalUseInventory.equals(docSubTypeInv))
|
||||||
|
qtyDiff = line.getQtyInternalUse().negate();
|
||||||
|
else if (MDocType.DOCSUBTYPEINV_PhysicalInventory.equals(docSubTypeInv))
|
||||||
|
qtyDiff = line.getQtyCount().subtract(line.getQtyBook());
|
||||||
|
else if (MDocType.DOCSUBTYPEINV_CostAdjustment.equals(docSubTypeInv))
|
||||||
{
|
{
|
||||||
BigDecimal currentCost = line.getCurrentCostPrice();
|
if (!isReversal())
|
||||||
MClient client = MClient.get(getCtx(), getAD_Client_ID());
|
|
||||||
MAcctSchema as = client.getAcctSchema();
|
|
||||||
MAcctSchema[] ass = MAcctSchema.getClientAcctSchema(getCtx(), client.get_ID());
|
|
||||||
|
|
||||||
if (as.getC_Currency_ID() != getC_Currency_ID())
|
|
||||||
{
|
{
|
||||||
for (int i = 0; i < ass.length ; i ++)
|
BigDecimal currentCost = line.getCurrentCostPrice();
|
||||||
|
MClient client = MClient.get(getCtx(), getAD_Client_ID());
|
||||||
|
MAcctSchema as = client.getAcctSchema();
|
||||||
|
MAcctSchema[] ass = MAcctSchema.getClientAcctSchema(getCtx(), client.get_ID());
|
||||||
|
|
||||||
|
if (as.getC_Currency_ID() != getC_Currency_ID())
|
||||||
{
|
{
|
||||||
MAcctSchema a = ass[i];
|
for (int i = 0; i < ass.length ; i ++)
|
||||||
if (a.getC_Currency_ID() == getC_Currency_ID())
|
{
|
||||||
as = a ;
|
MAcctSchema a = ass[i];
|
||||||
|
if (a.getC_Currency_ID() == getC_Currency_ID())
|
||||||
|
as = a ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MCost cost = product.getCostingRecord(as, getAD_Org_ID(), line.getM_AttributeSetInstance_ID(), getCostingMethod());
|
||||||
|
if (cost != null && cost.getCurrentCostPrice().compareTo(currentCost) != 0)
|
||||||
|
{
|
||||||
|
m_processMsg = "Current Cost for Line " + line.getLine() + " have changed.";
|
||||||
|
return DocAction.STATUS_Invalid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MCost cost = product.getCostingRecord(as, getAD_Org_ID(), line.getM_AttributeSetInstance_ID(), getCostingMethod());
|
|
||||||
if (cost != null && cost.getCurrentCostPrice().compareTo(currentCost) != 0)
|
|
||||||
{
|
|
||||||
m_processMsg = "Current Cost for Line " + line.getLine() + " have changed.";
|
|
||||||
return DocAction.STATUS_Invalid;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
//If Quantity Count minus Quantity Book = Zero, then no change in Inventory
|
||||||
//If Quantity Count minus Quantity Book = Zero, then no change in Inventory
|
if (qtyDiff.signum() == 0)
|
||||||
if (qtyDiff.signum() == 0)
|
continue;
|
||||||
continue;
|
|
||||||
|
//Ignore the Material Policy when is Reverse Correction
|
||||||
//Ignore the Material Policy when is Reverse Correction
|
if(!isReversal()){
|
||||||
if(!isReversal()){
|
BigDecimal qtyOnLineMA = MInventoryLineMA.getManualQty(line.getM_InventoryLine_ID(), get_TrxName());
|
||||||
BigDecimal qtyOnLineMA = MInventoryLineMA.getManualQty(line.getM_InventoryLine_ID(), get_TrxName());
|
|
||||||
|
if(qtyDiff.signum()<0){
|
||||||
if(qtyDiff.signum()<0){
|
if(qtyOnLineMA.compareTo(qtyDiff)<0){
|
||||||
if(qtyOnLineMA.compareTo(qtyDiff)<0){
|
m_processMsg = "@Over_Qty_On_Attribute_Tab@ " + line.getLine();
|
||||||
m_processMsg = "@Over_Qty_On_Attribute_Tab@ " + line.getLine();
|
return DOCSTATUS_Invalid;
|
||||||
return DOCSTATUS_Invalid;
|
}
|
||||||
}
|
}else{
|
||||||
}else{
|
if(qtyOnLineMA.compareTo(qtyDiff)>0){
|
||||||
if(qtyOnLineMA.compareTo(qtyDiff)>0){
|
m_processMsg = "@Over_Qty_On_Attribute_Tab@ " + line.getLine();
|
||||||
m_processMsg = "@Over_Qty_On_Attribute_Tab@ " + line.getLine();
|
return DOCSTATUS_Invalid;
|
||||||
return DOCSTATUS_Invalid;
|
}
|
||||||
}
|
}
|
||||||
|
checkMaterialPolicy(line, qtyDiff.subtract(qtyOnLineMA));
|
||||||
}
|
}
|
||||||
checkMaterialPolicy(line, qtyDiff.subtract(qtyOnLineMA));
|
// Stock Movement - Counterpart MOrder.reserveStock
|
||||||
}
|
if (product != null
|
||||||
// Stock Movement - Counterpart MOrder.reserveStock
|
&& product.isStocked() )
|
||||||
if (product != null
|
|
||||||
&& product.isStocked() )
|
|
||||||
{
|
|
||||||
log.fine("Material Transaction");
|
|
||||||
MTransaction mtrx = null;
|
|
||||||
|
|
||||||
//If AttributeSetInstance = Zero then create new AttributeSetInstance use Inventory Line MA else use current AttributeSetInstance
|
|
||||||
if (line.getM_AttributeSetInstance_ID() == 0 || qtyDiff.compareTo(Env.ZERO) == 0)
|
|
||||||
{
|
{
|
||||||
MInventoryLineMA mas[] = MInventoryLineMA.get(getCtx(),
|
log.fine("Material Transaction");
|
||||||
line.getM_InventoryLine_ID(), get_TrxName());
|
MTransaction mtrx = null;
|
||||||
|
|
||||||
for (int j = 0; j < mas.length; j++)
|
//If AttributeSetInstance = Zero then create new AttributeSetInstance use Inventory Line MA else use current AttributeSetInstance
|
||||||
|
if (line.getM_AttributeSetInstance_ID() == 0 || qtyDiff.compareTo(Env.ZERO) == 0)
|
||||||
{
|
{
|
||||||
MInventoryLineMA ma = mas[j];
|
MInventoryLineMA mas[] = MInventoryLineMA.get(getCtx(),
|
||||||
BigDecimal QtyMA = ma.getMovementQty();
|
line.getM_InventoryLine_ID(), get_TrxName());
|
||||||
BigDecimal QtyNew = QtyMA.add(qtyDiff);
|
|
||||||
if (log.isLoggable(Level.FINE)) log.fine("Diff=" + qtyDiff
|
for (int j = 0; j < mas.length; j++)
|
||||||
+ " - Instance OnHand=" + QtyMA + "->" + QtyNew);
|
{
|
||||||
|
MInventoryLineMA ma = mas[j];
|
||||||
|
BigDecimal QtyMA = ma.getMovementQty();
|
||||||
|
BigDecimal QtyNew = QtyMA.add(qtyDiff);
|
||||||
|
if (log.isLoggable(Level.FINE)) log.fine("Diff=" + qtyDiff
|
||||||
|
+ " - Instance OnHand=" + QtyMA + "->" + QtyNew);
|
||||||
|
|
||||||
|
if (!MStorageOnHand.add(getCtx(), getM_Warehouse_ID(),
|
||||||
|
line.getM_Locator_ID(),
|
||||||
|
line.getM_Product_ID(),
|
||||||
|
ma.getM_AttributeSetInstance_ID(),
|
||||||
|
QtyMA.negate(),ma.getDateMaterialPolicy(), get_TrxName()))
|
||||||
|
{
|
||||||
|
String lastError = CLogger.retrieveErrorString("");
|
||||||
|
m_processMsg = "Cannot correct Inventory (MA) - " + lastError;
|
||||||
|
return DocAction.STATUS_Invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only Update Date Last Inventory if is a Physical Inventory
|
||||||
|
if (MDocType.DOCSUBTYPEINV_PhysicalInventory.equals(docSubTypeInv))
|
||||||
|
{
|
||||||
|
MStorageOnHand storage = MStorageOnHand.get(getCtx(), line.getM_Locator_ID(),
|
||||||
|
line.getM_Product_ID(), ma.getM_AttributeSetInstance_ID(),ma.getDateMaterialPolicy(),get_TrxName());
|
||||||
|
storage.setDateLastInventory(getMovementDate());
|
||||||
|
if (!storage.save(get_TrxName()))
|
||||||
|
{
|
||||||
|
m_processMsg = "Storage not updated(2)";
|
||||||
|
return DocAction.STATUS_Invalid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String m_MovementType =null;
|
||||||
|
if(QtyMA.negate().compareTo(Env.ZERO) > 0 )
|
||||||
|
m_MovementType = MTransaction.MOVEMENTTYPE_InventoryIn;
|
||||||
|
else
|
||||||
|
m_MovementType = MTransaction.MOVEMENTTYPE_InventoryOut;
|
||||||
|
// Transaction
|
||||||
|
mtrx = new MTransaction (getCtx(), line.getAD_Org_ID(), m_MovementType,
|
||||||
|
line.getM_Locator_ID(), line.getM_Product_ID(), ma.getM_AttributeSetInstance_ID(),
|
||||||
|
QtyMA.negate(), getMovementDate(), get_TrxName());
|
||||||
|
|
||||||
|
mtrx.setM_InventoryLine_ID(line.getM_InventoryLine_ID());
|
||||||
|
if (!mtrx.save())
|
||||||
|
{
|
||||||
|
m_processMsg = "Transaction not inserted(2)";
|
||||||
|
return DocAction.STATUS_Invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
qtyDiff = QtyNew;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//sLine.getM_AttributeSetInstance_ID() != 0
|
||||||
|
// Fallback
|
||||||
|
if (mtrx == null)
|
||||||
|
{
|
||||||
|
Timestamp dateMPolicy= qtyDiff.signum() > 0 ? getMovementDate() : null;
|
||||||
|
if (line.getM_AttributeSetInstance_ID() > 0)
|
||||||
|
{
|
||||||
|
Timestamp t = MStorageOnHand.getDateMaterialPolicy(line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(), line.get_TrxName());
|
||||||
|
if (t != null)
|
||||||
|
dateMPolicy = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Fallback: Update Storage - see also VMatch.createMatchRecord
|
||||||
if (!MStorageOnHand.add(getCtx(), getM_Warehouse_ID(),
|
if (!MStorageOnHand.add(getCtx(), getM_Warehouse_ID(),
|
||||||
line.getM_Locator_ID(),
|
line.getM_Locator_ID(),
|
||||||
line.getM_Product_ID(),
|
line.getM_Product_ID(),
|
||||||
ma.getM_AttributeSetInstance_ID(),
|
line.getM_AttributeSetInstance_ID(),
|
||||||
QtyMA.negate(),ma.getDateMaterialPolicy(), get_TrxName()))
|
qtyDiff,dateMPolicy,get_TrxName()))
|
||||||
{
|
{
|
||||||
String lastError = CLogger.retrieveErrorString("");
|
String lastError = CLogger.retrieveErrorString("");
|
||||||
m_processMsg = "Cannot correct Inventory (MA) - " + lastError;
|
m_processMsg = "Cannot correct Inventory OnHand (MA) - " + lastError;
|
||||||
return DocAction.STATUS_Invalid;
|
return DocAction.STATUS_Invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only Update Date Last Inventory if is a Physical Inventory
|
// Only Update Date Last Inventory if is a Physical Inventory
|
||||||
if (MDocType.DOCSUBTYPEINV_PhysicalInventory.equals(docSubTypeInv))
|
if (MDocType.DOCSUBTYPEINV_PhysicalInventory.equals(docSubTypeInv))
|
||||||
{
|
{
|
||||||
MStorageOnHand storage = MStorageOnHand.get(getCtx(), line.getM_Locator_ID(),
|
MStorageOnHand storage = MStorageOnHand.get(getCtx(), line.getM_Locator_ID(),
|
||||||
line.getM_Product_ID(), ma.getM_AttributeSetInstance_ID(),ma.getDateMaterialPolicy(),get_TrxName());
|
line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(),dateMPolicy, get_TrxName());
|
||||||
|
|
||||||
storage.setDateLastInventory(getMovementDate());
|
storage.setDateLastInventory(getMovementDate());
|
||||||
if (!storage.save(get_TrxName()))
|
if (!storage.save(get_TrxName()))
|
||||||
{
|
{
|
||||||
|
@ -541,87 +604,40 @@ public class MInventory extends X_M_Inventory implements DocAction
|
||||||
return DocAction.STATUS_Invalid;
|
return DocAction.STATUS_Invalid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String m_MovementType =null;
|
String m_MovementType = null;
|
||||||
if(QtyMA.negate().compareTo(Env.ZERO) > 0 )
|
if(qtyDiff.compareTo(Env.ZERO) > 0 )
|
||||||
m_MovementType = MTransaction.MOVEMENTTYPE_InventoryIn;
|
m_MovementType = MTransaction.MOVEMENTTYPE_InventoryIn;
|
||||||
else
|
else
|
||||||
m_MovementType = MTransaction.MOVEMENTTYPE_InventoryOut;
|
m_MovementType = MTransaction.MOVEMENTTYPE_InventoryOut;
|
||||||
// Transaction
|
// Transaction
|
||||||
mtrx = new MTransaction (getCtx(), line.getAD_Org_ID(), m_MovementType,
|
mtrx = new MTransaction (getCtx(), line.getAD_Org_ID(), m_MovementType,
|
||||||
line.getM_Locator_ID(), line.getM_Product_ID(), ma.getM_AttributeSetInstance_ID(),
|
line.getM_Locator_ID(), line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(),
|
||||||
QtyMA.negate(), getMovementDate(), get_TrxName());
|
qtyDiff, getMovementDate(), get_TrxName());
|
||||||
|
mtrx.setM_InventoryLine_ID(line.getM_InventoryLine_ID());
|
||||||
mtrx.setM_InventoryLine_ID(line.getM_InventoryLine_ID());
|
if (!mtrx.save())
|
||||||
if (!mtrx.save())
|
|
||||||
{
|
|
||||||
m_processMsg = "Transaction not inserted(2)";
|
|
||||||
return DocAction.STATUS_Invalid;
|
|
||||||
}
|
|
||||||
|
|
||||||
qtyDiff = QtyNew;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//sLine.getM_AttributeSetInstance_ID() != 0
|
|
||||||
// Fallback
|
|
||||||
if (mtrx == null)
|
|
||||||
{
|
|
||||||
Timestamp dateMPolicy= qtyDiff.signum() > 0 ? getMovementDate() : null;
|
|
||||||
if (line.getM_AttributeSetInstance_ID() > 0)
|
|
||||||
{
|
|
||||||
Timestamp t = MStorageOnHand.getDateMaterialPolicy(line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(), line.get_TrxName());
|
|
||||||
if (t != null)
|
|
||||||
dateMPolicy = t;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Fallback: Update Storage - see also VMatch.createMatchRecord
|
|
||||||
if (!MStorageOnHand.add(getCtx(), getM_Warehouse_ID(),
|
|
||||||
line.getM_Locator_ID(),
|
|
||||||
line.getM_Product_ID(),
|
|
||||||
line.getM_AttributeSetInstance_ID(),
|
|
||||||
qtyDiff,dateMPolicy,get_TrxName()))
|
|
||||||
{
|
|
||||||
String lastError = CLogger.retrieveErrorString("");
|
|
||||||
m_processMsg = "Cannot correct Inventory OnHand (MA) - " + lastError;
|
|
||||||
return DocAction.STATUS_Invalid;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only Update Date Last Inventory if is a Physical Inventory
|
|
||||||
if (MDocType.DOCSUBTYPEINV_PhysicalInventory.equals(docSubTypeInv))
|
|
||||||
{
|
|
||||||
MStorageOnHand storage = MStorageOnHand.get(getCtx(), line.getM_Locator_ID(),
|
|
||||||
line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(),dateMPolicy, get_TrxName());
|
|
||||||
|
|
||||||
storage.setDateLastInventory(getMovementDate());
|
|
||||||
if (!storage.save(get_TrxName()))
|
|
||||||
{
|
{
|
||||||
m_processMsg = "Storage not updated(2)";
|
m_processMsg = "Transaction not inserted(2)";
|
||||||
return DocAction.STATUS_Invalid;
|
return DocAction.STATUS_Invalid;
|
||||||
}
|
}
|
||||||
}
|
} // Fallback
|
||||||
|
} // stock movement
|
||||||
String m_MovementType = null;
|
}
|
||||||
if(qtyDiff.compareTo(Env.ZERO) > 0 )
|
catch (NegativeInventoryDisallowedException e)
|
||||||
m_MovementType = MTransaction.MOVEMENTTYPE_InventoryIn;
|
{
|
||||||
else
|
log.severe(e.getMessage());
|
||||||
m_MovementType = MTransaction.MOVEMENTTYPE_InventoryOut;
|
errors.append(Msg.getElement(getCtx(), "Line")).append(" ").append(line.getLine()).append(": ");
|
||||||
// Transaction
|
errors.append(e.getMessage()).append("\n");
|
||||||
mtrx = new MTransaction (getCtx(), line.getAD_Org_ID(), m_MovementType,
|
}
|
||||||
line.getM_Locator_ID(), line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(),
|
|
||||||
qtyDiff, getMovementDate(), get_TrxName());
|
|
||||||
mtrx.setM_InventoryLine_ID(line.getM_InventoryLine_ID());
|
|
||||||
if (!mtrx.save())
|
|
||||||
{
|
|
||||||
m_processMsg = "Transaction not inserted(2)";
|
|
||||||
return DocAction.STATUS_Invalid;
|
|
||||||
}
|
|
||||||
} // Fallback
|
|
||||||
} // stock movement
|
|
||||||
|
|
||||||
} // for all lines
|
} // for all lines
|
||||||
|
|
||||||
|
if (errors.toString().length() > 0)
|
||||||
|
{
|
||||||
|
m_processMsg = errors.toString();
|
||||||
|
return DocAction.STATUS_Invalid;
|
||||||
|
}
|
||||||
|
|
||||||
// User Validation
|
// User Validation
|
||||||
String valid = ModelValidationEngine.get().fireDocValidate(this, ModelValidator.TIMING_AFTER_COMPLETE);
|
String valid = ModelValidationEngine.get().fireDocValidate(this, ModelValidator.TIMING_AFTER_COMPLETE);
|
||||||
if (valid != null)
|
if (valid != null)
|
||||||
|
|
|
@ -24,6 +24,7 @@ import java.util.List;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
|
import org.adempiere.exceptions.NegativeInventoryDisallowedException;
|
||||||
import org.adempiere.exceptions.PeriodClosedException;
|
import org.adempiere.exceptions.PeriodClosedException;
|
||||||
import org.compiere.process.DocAction;
|
import org.compiere.process.DocAction;
|
||||||
import org.compiere.process.DocumentEngine;
|
import org.compiere.process.DocumentEngine;
|
||||||
|
@ -416,6 +417,7 @@ public class MMovement extends X_M_Movement implements DocAction
|
||||||
approveIt();
|
approveIt();
|
||||||
if (log.isLoggable(Level.INFO)) log.info(toString());
|
if (log.isLoggable(Level.INFO)) log.info(toString());
|
||||||
|
|
||||||
|
StringBuilder errors = new StringBuilder();
|
||||||
//
|
//
|
||||||
MMovementLine[] lines = getLines(false);
|
MMovementLine[] lines = getLines(false);
|
||||||
for (int i = 0; i < lines.length; i++)
|
for (int i = 0; i < lines.length; i++)
|
||||||
|
@ -425,174 +427,190 @@ public class MMovement extends X_M_Movement implements DocAction
|
||||||
|
|
||||||
//Stock Movement - Counterpart MOrder.reserveStock
|
//Stock Movement - Counterpart MOrder.reserveStock
|
||||||
MProduct product = line.getProduct();
|
MProduct product = line.getProduct();
|
||||||
if (product != null
|
try
|
||||||
&& product.isStocked() )
|
|
||||||
{
|
{
|
||||||
//Ignore the Material Policy when is Reverse Correction
|
if (product != null
|
||||||
if(!isReversal()){
|
&& product.isStocked() )
|
||||||
BigDecimal qtyOnLineMA = MMovementLineMA.getManualQty(line.getM_MovementLine_ID(), get_TrxName());
|
|
||||||
BigDecimal movementQty = line.getMovementQty();
|
|
||||||
|
|
||||||
if(qtyOnLineMA.compareTo(movementQty)>0)
|
|
||||||
{
|
|
||||||
// More then line qty on attribute tab for line 10
|
|
||||||
m_processMsg = "@Over_Qty_On_Attribute_Tab@ " + line.getLine();
|
|
||||||
return DOCSTATUS_Invalid;
|
|
||||||
}
|
|
||||||
|
|
||||||
checkMaterialPolicy(line,movementQty.subtract(qtyOnLineMA));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (line.getM_AttributeSetInstance_ID() == 0)
|
|
||||||
{
|
{
|
||||||
MMovementLineMA mas[] = MMovementLineMA.get(getCtx(),
|
//Ignore the Material Policy when is Reverse Correction
|
||||||
line.getM_MovementLine_ID(), get_TrxName());
|
if(!isReversal()){
|
||||||
for (int j = 0; j < mas.length; j++)
|
BigDecimal qtyOnLineMA = MMovementLineMA.getManualQty(line.getM_MovementLine_ID(), get_TrxName());
|
||||||
|
BigDecimal movementQty = line.getMovementQty();
|
||||||
|
|
||||||
|
if(qtyOnLineMA.compareTo(movementQty)>0)
|
||||||
|
{
|
||||||
|
// More then line qty on attribute tab for line 10
|
||||||
|
m_processMsg = "@Over_Qty_On_Attribute_Tab@ " + line.getLine();
|
||||||
|
return DOCSTATUS_Invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkMaterialPolicy(line,movementQty.subtract(qtyOnLineMA));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (line.getM_AttributeSetInstance_ID() == 0)
|
||||||
{
|
{
|
||||||
MMovementLineMA ma = mas[j];
|
MMovementLineMA mas[] = MMovementLineMA.get(getCtx(),
|
||||||
//
|
line.getM_MovementLine_ID(), get_TrxName());
|
||||||
|
for (int j = 0; j < mas.length; j++)
|
||||||
|
{
|
||||||
|
MMovementLineMA ma = mas[j];
|
||||||
|
//
|
||||||
|
MLocator locator = new MLocator (getCtx(), line.getM_Locator_ID(), get_TrxName());
|
||||||
|
//Update Storage
|
||||||
|
if (!MStorageOnHand.add(getCtx(),locator.getM_Warehouse_ID(),
|
||||||
|
line.getM_Locator_ID(),
|
||||||
|
line.getM_Product_ID(),
|
||||||
|
ma.getM_AttributeSetInstance_ID(),
|
||||||
|
ma.getMovementQty().negate(),ma.getDateMaterialPolicy(), get_TrxName()))
|
||||||
|
{
|
||||||
|
String lastError = CLogger.retrieveErrorString("");
|
||||||
|
m_processMsg = "Cannot correct Inventory OnHand (MA) - " + lastError;
|
||||||
|
return DocAction.STATUS_Invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
int M_AttributeSetInstanceTo_ID = line.getM_AttributeSetInstanceTo_ID();
|
||||||
|
//only can be same asi if locator is different
|
||||||
|
if (M_AttributeSetInstanceTo_ID == 0 && line.getM_Locator_ID() != line.getM_LocatorTo_ID())
|
||||||
|
{
|
||||||
|
M_AttributeSetInstanceTo_ID = ma.getM_AttributeSetInstance_ID();
|
||||||
|
}
|
||||||
|
//Update Storage
|
||||||
|
MLocator locatorTo = new MLocator (getCtx(), line.getM_LocatorTo_ID(), get_TrxName());
|
||||||
|
if (!MStorageOnHand.add(getCtx(),locatorTo.getM_Warehouse_ID(),
|
||||||
|
line.getM_LocatorTo_ID(),
|
||||||
|
line.getM_Product_ID(),
|
||||||
|
M_AttributeSetInstanceTo_ID,
|
||||||
|
ma.getMovementQty(),ma.getDateMaterialPolicy(), get_TrxName()))
|
||||||
|
{
|
||||||
|
String lastError = CLogger.retrieveErrorString("");
|
||||||
|
m_processMsg = "Cannot correct Inventory OnHand (MA) - " + lastError;
|
||||||
|
return DocAction.STATUS_Invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
trxFrom = new MTransaction (getCtx(), line.getAD_Org_ID(),
|
||||||
|
MTransaction.MOVEMENTTYPE_MovementFrom,
|
||||||
|
line.getM_Locator_ID(), line.getM_Product_ID(), ma.getM_AttributeSetInstance_ID(),
|
||||||
|
ma.getMovementQty().negate(), getMovementDate(), get_TrxName());
|
||||||
|
trxFrom.setM_MovementLine_ID(line.getM_MovementLine_ID());
|
||||||
|
if (!trxFrom.save())
|
||||||
|
{
|
||||||
|
m_processMsg = "Transaction From not inserted (MA)";
|
||||||
|
return DocAction.STATUS_Invalid;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
MTransaction trxTo = new MTransaction (getCtx(), line.getAD_Org_ID(),
|
||||||
|
MTransaction.MOVEMENTTYPE_MovementTo,
|
||||||
|
line.getM_LocatorTo_ID(), line.getM_Product_ID(), M_AttributeSetInstanceTo_ID,
|
||||||
|
ma.getMovementQty(), getMovementDate(), get_TrxName());
|
||||||
|
trxTo.setM_MovementLine_ID(line.getM_MovementLine_ID());
|
||||||
|
if (!trxTo.save())
|
||||||
|
{
|
||||||
|
m_processMsg = "Transaction To not inserted (MA)";
|
||||||
|
return DocAction.STATUS_Invalid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Fallback - We have ASI
|
||||||
|
if (trxFrom == null)
|
||||||
|
{
|
||||||
|
Timestamp dateMPolicy= null;
|
||||||
|
MStorageOnHand[] storages = null;
|
||||||
|
if (line.getMovementQty().compareTo(Env.ZERO) > 0) {
|
||||||
|
// Find Date Material Policy bases on ASI
|
||||||
|
storages = MStorageOnHand.getWarehouse(getCtx(), 0,
|
||||||
|
line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(), null,
|
||||||
|
MClient.MMPOLICY_FiFo.equals(product.getMMPolicy()), false,
|
||||||
|
line.getM_Locator_ID(), get_TrxName());
|
||||||
|
} else {
|
||||||
|
//Case of reversal
|
||||||
|
storages = MStorageOnHand.getWarehouse(getCtx(), 0,
|
||||||
|
line.getM_Product_ID(), line.getM_AttributeSetInstanceTo_ID(), null,
|
||||||
|
MClient.MMPOLICY_FiFo.equals(product.getMMPolicy()), false,
|
||||||
|
line.getM_LocatorTo_ID(), get_TrxName());
|
||||||
|
}
|
||||||
|
for (MStorageOnHand storage : storages) {
|
||||||
|
if (storage.getQtyOnHand().compareTo(line.getMovementQty()) >= 0) {
|
||||||
|
dateMPolicy = storage.getDateMaterialPolicy();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dateMPolicy == null && storages.length > 0)
|
||||||
|
dateMPolicy = storages[0].getDateMaterialPolicy();
|
||||||
|
|
||||||
MLocator locator = new MLocator (getCtx(), line.getM_Locator_ID(), get_TrxName());
|
MLocator locator = new MLocator (getCtx(), line.getM_Locator_ID(), get_TrxName());
|
||||||
//Update Storage
|
//Update Storage
|
||||||
|
Timestamp effDateMPolicy = dateMPolicy;
|
||||||
|
if (dateMPolicy == null && line.getMovementQty().negate().signum() > 0)
|
||||||
|
effDateMPolicy = getMovementDate();
|
||||||
if (!MStorageOnHand.add(getCtx(),locator.getM_Warehouse_ID(),
|
if (!MStorageOnHand.add(getCtx(),locator.getM_Warehouse_ID(),
|
||||||
line.getM_Locator_ID(),
|
line.getM_Locator_ID(),
|
||||||
line.getM_Product_ID(),
|
line.getM_Product_ID(),
|
||||||
ma.getM_AttributeSetInstance_ID(),
|
line.getM_AttributeSetInstance_ID(),
|
||||||
ma.getMovementQty().negate(),ma.getDateMaterialPolicy(), get_TrxName()))
|
line.getMovementQty().negate(),effDateMPolicy, get_TrxName()))
|
||||||
{
|
{
|
||||||
String lastError = CLogger.retrieveErrorString("");
|
String lastError = CLogger.retrieveErrorString("");
|
||||||
m_processMsg = "Cannot correct Inventory OnHand (MA) - " + lastError;
|
m_processMsg = "Cannot correct Inventory OnHand (MA) - " + lastError;
|
||||||
return DocAction.STATUS_Invalid;
|
return DocAction.STATUS_Invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
int M_AttributeSetInstanceTo_ID = line.getM_AttributeSetInstanceTo_ID();
|
//Update Storage
|
||||||
//only can be same asi if locator is different
|
effDateMPolicy = dateMPolicy;
|
||||||
if (M_AttributeSetInstanceTo_ID == 0 && line.getM_Locator_ID() != line.getM_LocatorTo_ID())
|
if (dateMPolicy == null && line.getMovementQty().signum() > 0)
|
||||||
{
|
effDateMPolicy = getMovementDate();
|
||||||
M_AttributeSetInstanceTo_ID = ma.getM_AttributeSetInstance_ID();
|
|
||||||
}
|
|
||||||
//Update Storage
|
|
||||||
MLocator locatorTo = new MLocator (getCtx(), line.getM_LocatorTo_ID(), get_TrxName());
|
MLocator locatorTo = new MLocator (getCtx(), line.getM_LocatorTo_ID(), get_TrxName());
|
||||||
if (!MStorageOnHand.add(getCtx(),locatorTo.getM_Warehouse_ID(),
|
if (!MStorageOnHand.add(getCtx(),locatorTo.getM_Warehouse_ID(),
|
||||||
line.getM_LocatorTo_ID(),
|
line.getM_LocatorTo_ID(),
|
||||||
line.getM_Product_ID(),
|
line.getM_Product_ID(),
|
||||||
M_AttributeSetInstanceTo_ID,
|
line.getM_AttributeSetInstanceTo_ID(),
|
||||||
ma.getMovementQty(),ma.getDateMaterialPolicy(), get_TrxName()))
|
line.getMovementQty(),effDateMPolicy, get_TrxName()))
|
||||||
{
|
{
|
||||||
String lastError = CLogger.retrieveErrorString("");
|
String lastError = CLogger.retrieveErrorString("");
|
||||||
m_processMsg = "Cannot correct Inventory OnHand (MA) - " + lastError;
|
m_processMsg = "Cannot correct Inventory OnHand (MA) - " + lastError;
|
||||||
return DocAction.STATUS_Invalid;
|
return DocAction.STATUS_Invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
trxFrom = new MTransaction (getCtx(), line.getAD_Org_ID(),
|
trxFrom = new MTransaction (getCtx(), line.getAD_Org_ID(),
|
||||||
MTransaction.MOVEMENTTYPE_MovementFrom,
|
MTransaction.MOVEMENTTYPE_MovementFrom,
|
||||||
line.getM_Locator_ID(), line.getM_Product_ID(), ma.getM_AttributeSetInstance_ID(),
|
line.getM_Locator_ID(), line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(),
|
||||||
ma.getMovementQty().negate(), getMovementDate(), get_TrxName());
|
line.getMovementQty().negate(), getMovementDate(), get_TrxName());
|
||||||
trxFrom.setM_MovementLine_ID(line.getM_MovementLine_ID());
|
trxFrom.setM_MovementLine_ID(line.getM_MovementLine_ID());
|
||||||
if (!trxFrom.save())
|
if (!trxFrom.save())
|
||||||
{
|
{
|
||||||
m_processMsg = "Transaction From not inserted (MA)";
|
m_processMsg = "Transaction From not inserted";
|
||||||
return DocAction.STATUS_Invalid;
|
return DocAction.STATUS_Invalid;
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
MTransaction trxTo = new MTransaction (getCtx(), line.getAD_Org_ID(),
|
MTransaction trxTo = new MTransaction (getCtx(), line.getAD_Org_ID(),
|
||||||
MTransaction.MOVEMENTTYPE_MovementTo,
|
MTransaction.MOVEMENTTYPE_MovementTo,
|
||||||
line.getM_LocatorTo_ID(), line.getM_Product_ID(), M_AttributeSetInstanceTo_ID,
|
line.getM_LocatorTo_ID(), line.getM_Product_ID(), line.getM_AttributeSetInstanceTo_ID(),
|
||||||
ma.getMovementQty(), getMovementDate(), get_TrxName());
|
line.getMovementQty(), getMovementDate(), get_TrxName());
|
||||||
trxTo.setM_MovementLine_ID(line.getM_MovementLine_ID());
|
trxTo.setM_MovementLine_ID(line.getM_MovementLine_ID());
|
||||||
if (!trxTo.save())
|
if (!trxTo.save())
|
||||||
{
|
{
|
||||||
m_processMsg = "Transaction To not inserted (MA)";
|
m_processMsg = "Transaction To not inserted";
|
||||||
return DocAction.STATUS_Invalid;
|
return DocAction.STATUS_Invalid;
|
||||||
}
|
}
|
||||||
}
|
} // Fallback
|
||||||
}
|
} // product stock
|
||||||
// Fallback - We have ASI
|
}
|
||||||
if (trxFrom == null)
|
catch (NegativeInventoryDisallowedException e)
|
||||||
{
|
{
|
||||||
Timestamp dateMPolicy= null;
|
log.severe(e.getMessage());
|
||||||
MStorageOnHand[] storages = null;
|
errors.append(Msg.getElement(getCtx(), "Line")).append(" ").append(line.getLine()).append(": ");
|
||||||
if (line.getMovementQty().compareTo(Env.ZERO) > 0) {
|
errors.append(e.getMessage()).append("\n");
|
||||||
// Find Date Material Policy bases on ASI
|
}
|
||||||
storages = MStorageOnHand.getWarehouse(getCtx(), 0,
|
|
||||||
line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(), null,
|
|
||||||
MClient.MMPOLICY_FiFo.equals(product.getMMPolicy()), false,
|
|
||||||
line.getM_Locator_ID(), get_TrxName());
|
|
||||||
} else {
|
|
||||||
//Case of reversal
|
|
||||||
storages = MStorageOnHand.getWarehouse(getCtx(), 0,
|
|
||||||
line.getM_Product_ID(), line.getM_AttributeSetInstanceTo_ID(), null,
|
|
||||||
MClient.MMPOLICY_FiFo.equals(product.getMMPolicy()), false,
|
|
||||||
line.getM_LocatorTo_ID(), get_TrxName());
|
|
||||||
}
|
|
||||||
for (MStorageOnHand storage : storages) {
|
|
||||||
if (storage.getQtyOnHand().compareTo(line.getMovementQty()) >= 0) {
|
|
||||||
dateMPolicy = storage.getDateMaterialPolicy();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dateMPolicy == null && storages.length > 0)
|
|
||||||
dateMPolicy = storages[0].getDateMaterialPolicy();
|
|
||||||
|
|
||||||
MLocator locator = new MLocator (getCtx(), line.getM_Locator_ID(), get_TrxName());
|
|
||||||
//Update Storage
|
|
||||||
Timestamp effDateMPolicy = dateMPolicy;
|
|
||||||
if (dateMPolicy == null && line.getMovementQty().negate().signum() > 0)
|
|
||||||
effDateMPolicy = getMovementDate();
|
|
||||||
if (!MStorageOnHand.add(getCtx(),locator.getM_Warehouse_ID(),
|
|
||||||
line.getM_Locator_ID(),
|
|
||||||
line.getM_Product_ID(),
|
|
||||||
line.getM_AttributeSetInstance_ID(),
|
|
||||||
line.getMovementQty().negate(),effDateMPolicy, get_TrxName()))
|
|
||||||
{
|
|
||||||
String lastError = CLogger.retrieveErrorString("");
|
|
||||||
m_processMsg = "Cannot correct Inventory OnHand (MA) - " + lastError;
|
|
||||||
return DocAction.STATUS_Invalid;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Update Storage
|
|
||||||
effDateMPolicy = dateMPolicy;
|
|
||||||
if (dateMPolicy == null && line.getMovementQty().signum() > 0)
|
|
||||||
effDateMPolicy = getMovementDate();
|
|
||||||
MLocator locatorTo = new MLocator (getCtx(), line.getM_LocatorTo_ID(), get_TrxName());
|
|
||||||
if (!MStorageOnHand.add(getCtx(),locatorTo.getM_Warehouse_ID(),
|
|
||||||
line.getM_LocatorTo_ID(),
|
|
||||||
line.getM_Product_ID(),
|
|
||||||
line.getM_AttributeSetInstanceTo_ID(),
|
|
||||||
line.getMovementQty(),effDateMPolicy, get_TrxName()))
|
|
||||||
{
|
|
||||||
String lastError = CLogger.retrieveErrorString("");
|
|
||||||
m_processMsg = "Cannot correct Inventory OnHand (MA) - " + lastError;
|
|
||||||
return DocAction.STATUS_Invalid;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
trxFrom = new MTransaction (getCtx(), line.getAD_Org_ID(),
|
|
||||||
MTransaction.MOVEMENTTYPE_MovementFrom,
|
|
||||||
line.getM_Locator_ID(), line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(),
|
|
||||||
line.getMovementQty().negate(), getMovementDate(), get_TrxName());
|
|
||||||
trxFrom.setM_MovementLine_ID(line.getM_MovementLine_ID());
|
|
||||||
if (!trxFrom.save())
|
|
||||||
{
|
|
||||||
m_processMsg = "Transaction From not inserted";
|
|
||||||
return DocAction.STATUS_Invalid;
|
|
||||||
}
|
|
||||||
//
|
|
||||||
MTransaction trxTo = new MTransaction (getCtx(), line.getAD_Org_ID(),
|
|
||||||
MTransaction.MOVEMENTTYPE_MovementTo,
|
|
||||||
line.getM_LocatorTo_ID(), line.getM_Product_ID(), line.getM_AttributeSetInstanceTo_ID(),
|
|
||||||
line.getMovementQty(), getMovementDate(), get_TrxName());
|
|
||||||
trxTo.setM_MovementLine_ID(line.getM_MovementLine_ID());
|
|
||||||
if (!trxTo.save())
|
|
||||||
{
|
|
||||||
m_processMsg = "Transaction To not inserted";
|
|
||||||
return DocAction.STATUS_Invalid;
|
|
||||||
}
|
|
||||||
} // Fallback
|
|
||||||
} // product stock
|
|
||||||
} // for all lines
|
} // for all lines
|
||||||
|
|
||||||
|
if (errors.toString().length() > 0)
|
||||||
|
{
|
||||||
|
m_processMsg = errors.toString();
|
||||||
|
return DocAction.STATUS_Invalid;
|
||||||
|
}
|
||||||
|
|
||||||
// User Validation
|
// User Validation
|
||||||
String valid = ModelValidationEngine.get().fireDocValidate(this, ModelValidator.TIMING_AFTER_COMPLETE);
|
String valid = ModelValidationEngine.get().fireDocValidate(this, ModelValidator.TIMING_AFTER_COMPLETE);
|
||||||
if (valid != null)
|
if (valid != null)
|
||||||
|
|
|
@ -22,8 +22,11 @@ import java.sql.Timestamp;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
|
import org.adempiere.exceptions.AdempiereException;
|
||||||
|
import org.adempiere.exceptions.NegativeInventoryDisallowedException;
|
||||||
import org.compiere.util.DB;
|
import org.compiere.util.DB;
|
||||||
import org.compiere.util.Env;
|
import org.compiere.util.Env;
|
||||||
|
import org.compiere.util.Msg;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Project Issue Model
|
* Project Issue Model
|
||||||
|
@ -172,23 +175,35 @@ public class MProjectIssue extends X_C_ProjectIssue
|
||||||
dateMPolicy = t;
|
dateMPolicy = t;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MStorageOnHand.add(getCtx(), loc.getM_Warehouse_ID(), getM_Locator_ID(),
|
try
|
||||||
getM_Product_ID(), getM_AttributeSetInstance_ID(),
|
|
||||||
getMovementQty().negate(),dateMPolicy, get_TrxName()))
|
|
||||||
{
|
{
|
||||||
if (mTrx.save(get_TrxName()))
|
if (MStorageOnHand.add(getCtx(), loc.getM_Warehouse_ID(), getM_Locator_ID(),
|
||||||
|
getM_Product_ID(), getM_AttributeSetInstance_ID(),
|
||||||
|
getMovementQty().negate(),dateMPolicy, get_TrxName()))
|
||||||
{
|
{
|
||||||
setProcessed (true);
|
if (mTrx.save(get_TrxName()))
|
||||||
if (save())
|
{
|
||||||
return true;
|
setProcessed (true);
|
||||||
|
if (save())
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
log.log(Level.SEVERE, "Issue not saved"); // requires trx !!
|
||||||
|
}
|
||||||
else
|
else
|
||||||
log.log(Level.SEVERE, "Issue not saved"); // requires trx !!
|
log.log(Level.SEVERE, "Transaction not saved"); // requires trx !!
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
log.log(Level.SEVERE, "Transaction not saved"); // requires trx !!
|
log.log(Level.SEVERE, "Storage not updated"); // OK
|
||||||
}
|
}
|
||||||
else
|
catch (NegativeInventoryDisallowedException e)
|
||||||
log.log(Level.SEVERE, "Storage not updated"); // OK
|
{
|
||||||
|
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;
|
return false;
|
||||||
} // process
|
} // process
|
||||||
|
|
|
@ -27,11 +27,10 @@ import java.util.List;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
import org.adempiere.exceptions.AdempiereException;
|
import org.adempiere.exceptions.NegativeInventoryDisallowedException;
|
||||||
import org.compiere.util.CLogger;
|
import org.compiere.util.CLogger;
|
||||||
import org.compiere.util.DB;
|
import org.compiere.util.DB;
|
||||||
import org.compiere.util.Env;
|
import org.compiere.util.Env;
|
||||||
import org.compiere.util.Msg;
|
|
||||||
import org.compiere.util.Util;
|
import org.compiere.util.Util;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -735,7 +734,8 @@ public class MStorageOnHand extends X_M_StorageOnHand
|
||||||
if (getQtyOnHand().signum() == -1) {
|
if (getQtyOnHand().signum() == -1) {
|
||||||
MWarehouse wh = MWarehouse.get(Env.getCtx(), getM_Warehouse_ID());
|
MWarehouse wh = MWarehouse.get(Env.getCtx(), getM_Warehouse_ID());
|
||||||
if (wh.isDisallowNegativeInv()) {
|
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 ||
|
if (getQtyOnHand().compareTo(BigDecimal.ZERO) < 0 ||
|
||||||
QtyOnHand.compareTo(Env.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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getM_AttributeSetInstance_ID() > 0 && getQtyOnHand().signum() < 0)
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@ import java.util.Properties;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
import org.adempiere.exceptions.AdempiereException;
|
import org.adempiere.exceptions.AdempiereException;
|
||||||
|
import org.adempiere.exceptions.NegativeInventoryDisallowedException;
|
||||||
import org.compiere.model.MBPartner;
|
import org.compiere.model.MBPartner;
|
||||||
import org.compiere.model.MBPartnerLocation;
|
import org.compiere.model.MBPartnerLocation;
|
||||||
import org.compiere.model.MDocType;
|
import org.compiere.model.MDocType;
|
||||||
|
@ -847,6 +848,7 @@ public class MDDOrder extends X_DD_Order implements DocAction
|
||||||
BigDecimal Volume = Env.ZERO;
|
BigDecimal Volume = Env.ZERO;
|
||||||
BigDecimal Weight = Env.ZERO;
|
BigDecimal Weight = Env.ZERO;
|
||||||
|
|
||||||
|
StringBuilder errors = new StringBuilder();
|
||||||
// Always check and (un) Reserve Inventory
|
// Always check and (un) Reserve Inventory
|
||||||
for (MDDOrderLine line : lines)
|
for (MDDOrderLine line : lines)
|
||||||
{
|
{
|
||||||
|
@ -874,35 +876,47 @@ public class MDDOrder extends X_DD_Order implements DocAction
|
||||||
MProduct product = line.getProduct();
|
MProduct product = line.getProduct();
|
||||||
if (product != null)
|
if (product != null)
|
||||||
{
|
{
|
||||||
if (product.isStocked())
|
try
|
||||||
{
|
{
|
||||||
// Update Storage
|
if (product.isStocked())
|
||||||
if (!MStorageOnHand.add(getCtx(), locator_to.getM_Warehouse_ID(), locator_to.getM_Locator_ID(),
|
|
||||||
line.getM_Product_ID(),
|
|
||||||
line.getM_AttributeSetInstance_ID(),
|
|
||||||
Env.ZERO,null, get_TrxName()))
|
|
||||||
{
|
{
|
||||||
throw new AdempiereException();
|
// Update Storage
|
||||||
}
|
if (!MStorageOnHand.add(getCtx(), locator_to.getM_Warehouse_ID(), locator_to.getM_Locator_ID(),
|
||||||
|
line.getM_Product_ID(),
|
||||||
if (!MStorageOnHand.add(getCtx(), locator_from.getM_Warehouse_ID(), locator_from.getM_Locator_ID(),
|
line.getM_AttributeSetInstance_ID(),
|
||||||
line.getM_Product_ID(),
|
Env.ZERO,null, get_TrxName()))
|
||||||
line.getM_AttributeSetInstanceTo_ID(),
|
{
|
||||||
Env.ZERO,null, get_TrxName()))
|
throw new AdempiereException();
|
||||||
{
|
}
|
||||||
throw new AdempiereException();
|
|
||||||
}
|
if (!MStorageOnHand.add(getCtx(), locator_from.getM_Warehouse_ID(), locator_from.getM_Locator_ID(),
|
||||||
|
line.getM_Product_ID(),
|
||||||
} // stockec
|
line.getM_AttributeSetInstanceTo_ID(),
|
||||||
// update line
|
Env.ZERO,null, get_TrxName()))
|
||||||
line.setQtyReserved(line.getQtyReserved().add(reserved_ordered));
|
{
|
||||||
line.saveEx();
|
throw new AdempiereException();
|
||||||
//
|
}
|
||||||
Volume = Volume.add(product.getVolume().multiply(line.getQtyOrdered()));
|
|
||||||
Weight = Weight.add(product.getWeight().multiply(line.getQtyOrdered()));
|
} // stockec
|
||||||
|
// update line
|
||||||
|
line.setQtyReserved(line.getQtyReserved().add(reserved_ordered));
|
||||||
|
line.saveEx();
|
||||||
|
//
|
||||||
|
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
|
} // product
|
||||||
} // reverse inventory
|
} // reverse inventory
|
||||||
|
|
||||||
|
if (errors.toString().length() > 0)
|
||||||
|
throw new AdempiereException(errors.toString());
|
||||||
|
|
||||||
setVolume(Volume);
|
setVolume(Volume);
|
||||||
setWeight(Weight);
|
setWeight(Weight);
|
||||||
} // reserveStock
|
} // reserveStock
|
||||||
|
|
Loading…
Reference in New Issue