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 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,353 +1295,326 @@ public class MInOut extends X_M_InOut implements DocAction
|
|||
MInOutLine sLine = lines[lineIndex];
|
||||
MProduct product = sLine.getProduct();
|
||||
|
||||
// Qty & Type
|
||||
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)
|
||||
try
|
||||
{
|
||||
oLine = new MOrderLine (getCtx(), sLine.getC_OrderLine_ID(), get_TrxName());
|
||||
if (log.isLoggable(Level.FINE)) log.fine("OrderLine - Reserved=" + oLine.getQtyReserved()
|
||||
+ ", Delivered=" + oLine.getQtyDelivered());
|
||||
}
|
||||
|
||||
|
||||
// Load RMA Line
|
||||
MRMALine rmaLine = null;
|
||||
|
||||
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())
|
||||
// Qty & Type
|
||||
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)
|
||||
{
|
||||
BigDecimal movementQty = sLine.getMovementQty();
|
||||
BigDecimal qtyOnLineMA = MInOutLineMA.getManualQty(sLine.getM_InOutLine_ID(), get_TrxName());
|
||||
|
||||
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));
|
||||
oLine = new MOrderLine (getCtx(), sLine.getC_OrderLine_ID(), get_TrxName());
|
||||
if (log.isLoggable(Level.FINE)) log.fine("OrderLine - Reserved=" + oLine.getQtyReserved()
|
||||
+ ", Delivered=" + oLine.getQtyDelivered());
|
||||
}
|
||||
|
||||
log.fine("Material Transaction");
|
||||
MTransaction mtrx = null;
|
||||
|
||||
//
|
||||
BigDecimal overReceipt = BigDecimal.ZERO;
|
||||
if (!isReversal())
|
||||
|
||||
|
||||
// Load RMA Line
|
||||
MRMALine rmaLine = null;
|
||||
|
||||
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() )
|
||||
{
|
||||
if (oLine != null)
|
||||
//Ignore the Material Policy when is Reverse Correction
|
||||
if(!isReversal())
|
||||
{
|
||||
BigDecimal toDelivered = oLine.getQtyOrdered()
|
||||
.subtract(oLine.getQtyDelivered());
|
||||
if (toDelivered.signum() < 0) // IDEMPIERE-2889
|
||||
toDelivered = Env.ZERO;
|
||||
if (sLine.getMovementQty().compareTo(toDelivered) > 0)
|
||||
overReceipt = sLine.getMovementQty().subtract(
|
||||
toDelivered);
|
||||
if (overReceipt.signum() != 0)
|
||||
{
|
||||
sLine.setQtyOverReceipt(overReceipt);
|
||||
sLine.saveEx();
|
||||
BigDecimal movementQty = sLine.getMovementQty();
|
||||
BigDecimal qtyOnLineMA = MInOutLineMA.getManualQty(sLine.getM_InOutLine_ID(), get_TrxName());
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
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++)
|
||||
|
||||
log.fine("Material Transaction");
|
||||
MTransaction mtrx = null;
|
||||
|
||||
//
|
||||
BigDecimal overReceipt = BigDecimal.ZERO;
|
||||
if (!isReversal())
|
||||
{
|
||||
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 (oLine != null)
|
||||
{
|
||||
BigDecimal toDelivered = oLine.getQtyOrdered()
|
||||
.subtract(oLine.getQtyDelivered());
|
||||
if (toDelivered.signum() < 0) // IDEMPIERE-2889
|
||||
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(),
|
||||
sLine.getM_Locator_ID(),
|
||||
sLine.getM_Product_ID(),
|
||||
ma.getM_AttributeSetInstance_ID(),
|
||||
QtyMA,ma.getDateMaterialPolicy(),
|
||||
get_TrxName()))
|
||||
sLine.getM_AttributeSetInstance_ID(),
|
||||
Qty,dateMPolicy,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() + "]";
|
||||
m_processMsg = "Cannot correct Inventory OnHand [" + product.getValue() + "] - " + lastError;
|
||||
return DocAction.STATUS_Invalid;
|
||||
}
|
||||
}
|
||||
|
||||
if (oLine!=null && mtrx!=null && oLine.getQtyOrdered().signum() > 0)
|
||||
{
|
||||
if (sLine.getC_OrderLine_ID() != 0)
|
||||
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()))
|
||||
orderedQtyToUpdate.negate(), isSOTrx(), get_TrxName()))
|
||||
{
|
||||
String lastError = CLogger.retrieveErrorString("");
|
||||
m_processMsg = "Cannot correct Inventory " + (isSOTrx()? "Reserved" : "Ordered") + " (MA) - [" + product.getValue() + "] - " + lastError;
|
||||
m_processMsg = "Cannot correct Inventory Reserved " + (isSOTrx()? "Reserved [" :"Ordered [") + product.getValue() + "]";
|
||||
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(),
|
||||
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()))
|
||||
|
||||
// FallBack: Create Transaction
|
||||
mtrx = new MTransaction (getCtx(), sLine.getAD_Org_ID(),
|
||||
MovementType, sLine.getM_Locator_ID(),
|
||||
sLine.getM_Product_ID(), sLine.getM_AttributeSetInstance_ID(),
|
||||
Qty, getMovementDate(), get_TrxName());
|
||||
mtrx.setM_InOutLine_ID(sLine.getM_InOutLine_ID());
|
||||
if (!mtrx.save())
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// FallBack: Create Transaction
|
||||
mtrx = new MTransaction (getCtx(), sLine.getAD_Org_ID(),
|
||||
MovementType, sLine.getM_Locator_ID(),
|
||||
sLine.getM_Product_ID(), sLine.getM_AttributeSetInstance_ID(),
|
||||
Qty, getMovementDate(), get_TrxName());
|
||||
mtrx.setM_InOutLine_ID(sLine.getM_InOutLine_ID());
|
||||
if (!mtrx.save())
|
||||
} // 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
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
} // 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
|
||||
oLine.setQtyDelivered(oLine.getQtyDelivered().add(Qty));
|
||||
oLine.setDateDelivered(getMovementDate()); // overwrite=last
|
||||
if (log.isLoggable(Level.FINE)) log.fine("OrderLine -> Reserved=" + oLine.getQtyReserved()
|
||||
+ ", 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";
|
||||
return DocAction.STATUS_Invalid;
|
||||
}
|
||||
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;
|
||||
log.fine("Asset");
|
||||
info.append("@A_Asset_ID@: ");
|
||||
int noAssets = sLine.getMovementQty().intValue();
|
||||
if (!product.isOneAssetPerUOM())
|
||||
deliveryCount = 0;
|
||||
MAsset asset = new MAsset (this, sLine, deliveryCount);
|
||||
if (!asset.save(get_TrxName()))
|
||||
noAssets = 1;
|
||||
for (int i = 0; i < noAssets; i++)
|
||||
{
|
||||
m_processMsg = "Could not create Asset";
|
||||
return DocAction.STATUS_Invalid;
|
||||
}
|
||||
info.append(asset.getValue());
|
||||
}
|
||||
} // Asset
|
||||
|
||||
|
||||
// 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())
|
||||
if (i > 0)
|
||||
info.append(" - ");
|
||||
int deliveryCount = i+1;
|
||||
if (!product.isOneAssetPerUOM())
|
||||
deliveryCount = 0;
|
||||
MAsset asset = new MAsset (this, sLine, deliveryCount);
|
||||
if (!asset.save(get_TrxName()))
|
||||
{
|
||||
iLine.setM_AttributeSetInstance_ID(sLine.getM_AttributeSetInstance_ID());
|
||||
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");
|
||||
m_processMsg = "Could not create Asset";
|
||||
return DocAction.STATUS_Invalid;
|
||||
}
|
||||
addDocsPostProcess(inv);
|
||||
info.append(asset.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
// Link to Order
|
||||
if (sLine.getC_OrderLine_ID() != 0)
|
||||
} // Asset
|
||||
|
||||
|
||||
// Matching
|
||||
if (!isSOTrx()
|
||||
&& sLine.getM_Product_ID() != 0
|
||||
&& !isReversal())
|
||||
{
|
||||
log.fine("PO Matching");
|
||||
// Ship - PO
|
||||
MMatchPO po = MMatchPO.create (null, sLine, getMovementDate(), matchQty);
|
||||
if (po != null) {
|
||||
if (!po.save(get_TrxName()))
|
||||
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)
|
||||
{
|
||||
m_processMsg = "Could not create PO Matching";
|
||||
return DocAction.STATUS_Invalid;
|
||||
}
|
||||
if (!po.isPosted())
|
||||
addDocsPostProcess(po);
|
||||
MMatchInv matchInvCreated = po.getMatchInvCreated();
|
||||
if (matchInvCreated != null) {
|
||||
addDocsPostProcess(matchInvCreated);
|
||||
MMatchInv inv = new MMatchInv (iLine, getMovementDate(), matchQty);
|
||||
if (sLine.getM_AttributeSetInstance_ID() != iLine.getM_AttributeSetInstance_ID())
|
||||
{
|
||||
iLine.setM_AttributeSetInstance_ID(sLine.getM_AttributeSetInstance_ID());
|
||||
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;
|
||||
}
|
||||
addDocsPostProcess(inv);
|
||||
}
|
||||
}
|
||||
// Update PO with ASI
|
||||
if ( oLine != null && oLine.getM_AttributeSetInstance_ID() == 0
|
||||
&& sLine.getMovementQty().compareTo(oLine.getQtyOrdered()) == 0) // just if full match [ 1876965 ]
|
||||
|
||||
// Link to Order
|
||||
if (sLine.getC_OrderLine_ID() != 0)
|
||||
{
|
||||
oLine.setM_AttributeSetInstance_ID(sLine.getM_AttributeSetInstance_ID());
|
||||
oLine.saveEx(get_TrxName());
|
||||
}
|
||||
}
|
||||
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);
|
||||
log.fine("PO Matching");
|
||||
// Ship - PO
|
||||
MMatchPO po = MMatchPO.create (null, sLine, getMovementDate(), matchQty);
|
||||
if (po != null) {
|
||||
if (!po.save(get_TrxName()))
|
||||
{
|
||||
m_processMsg = "Could not create PO(Inv) Matching";
|
||||
m_processMsg = "Could not create PO Matching";
|
||||
return DocAction.STATUS_Invalid;
|
||||
}
|
||||
if (!po.isPosted())
|
||||
addDocsPostProcess(po);
|
||||
MMatchInv matchInvCreated = po.getMatchInvCreated();
|
||||
if (matchInvCreated != null) {
|
||||
addDocsPostProcess(matchInvCreated);
|
||||
}
|
||||
}
|
||||
|
||||
// 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 ]
|
||||
{
|
||||
|
@ -1647,11 +1622,52 @@ public class MInOut extends X_M_InOut implements DocAction
|
|||
oLine.saveEx(get_TrxName());
|
||||
}
|
||||
}
|
||||
} // No Order
|
||||
} // PO Matching
|
||||
|
||||
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.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
|
||||
|
||||
if (errors.toString().length() > 0)
|
||||
{
|
||||
m_processMsg = errors.toString();
|
||||
return DocAction.STATUS_Invalid;
|
||||
}
|
||||
|
||||
// Counter Documents
|
||||
MInOut counter = createCounterDoc();
|
||||
if (counter != null)
|
||||
|
|
|
@ -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,98 +444,159 @@ public class MInventory extends X_M_Inventory implements DocAction
|
|||
continue;
|
||||
|
||||
MProduct product = line.getProduct();
|
||||
|
||||
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))
|
||||
try
|
||||
{
|
||||
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();
|
||||
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())
|
||||
if (!isReversal())
|
||||
{
|
||||
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];
|
||||
if (a.getC_Currency_ID() == getC_Currency_ID())
|
||||
as = a ;
|
||||
for (int i = 0; i < ass.length ; i ++)
|
||||
{
|
||||
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 (qtyDiff.signum() == 0)
|
||||
continue;
|
||||
|
||||
//Ignore the Material Policy when is Reverse Correction
|
||||
if(!isReversal()){
|
||||
BigDecimal qtyOnLineMA = MInventoryLineMA.getManualQty(line.getM_InventoryLine_ID(), get_TrxName());
|
||||
|
||||
if(qtyDiff.signum()<0){
|
||||
if(qtyOnLineMA.compareTo(qtyDiff)<0){
|
||||
m_processMsg = "@Over_Qty_On_Attribute_Tab@ " + line.getLine();
|
||||
return DOCSTATUS_Invalid;
|
||||
}
|
||||
}else{
|
||||
if(qtyOnLineMA.compareTo(qtyDiff)>0){
|
||||
m_processMsg = "@Over_Qty_On_Attribute_Tab@ " + line.getLine();
|
||||
return DOCSTATUS_Invalid;
|
||||
|
||||
//If Quantity Count minus Quantity Book = Zero, then no change in Inventory
|
||||
if (qtyDiff.signum() == 0)
|
||||
continue;
|
||||
|
||||
//Ignore the Material Policy when is Reverse Correction
|
||||
if(!isReversal()){
|
||||
BigDecimal qtyOnLineMA = MInventoryLineMA.getManualQty(line.getM_InventoryLine_ID(), get_TrxName());
|
||||
|
||||
if(qtyDiff.signum()<0){
|
||||
if(qtyOnLineMA.compareTo(qtyDiff)<0){
|
||||
m_processMsg = "@Over_Qty_On_Attribute_Tab@ " + line.getLine();
|
||||
return DOCSTATUS_Invalid;
|
||||
}
|
||||
}else{
|
||||
if(qtyOnLineMA.compareTo(qtyDiff)>0){
|
||||
m_processMsg = "@Over_Qty_On_Attribute_Tab@ " + line.getLine();
|
||||
return DOCSTATUS_Invalid;
|
||||
}
|
||||
}
|
||||
checkMaterialPolicy(line, qtyDiff.subtract(qtyOnLineMA));
|
||||
}
|
||||
checkMaterialPolicy(line, qtyDiff.subtract(qtyOnLineMA));
|
||||
}
|
||||
// Stock Movement - Counterpart MOrder.reserveStock
|
||||
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)
|
||||
// Stock Movement - Counterpart MOrder.reserveStock
|
||||
if (product != null
|
||||
&& product.isStocked() )
|
||||
{
|
||||
MInventoryLineMA mas[] = MInventoryLineMA.get(getCtx(),
|
||||
line.getM_InventoryLine_ID(), get_TrxName());
|
||||
|
||||
for (int j = 0; j < mas.length; j++)
|
||||
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 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);
|
||||
|
||||
MInventoryLineMA mas[] = MInventoryLineMA.get(getCtx(),
|
||||
line.getM_InventoryLine_ID(), get_TrxName());
|
||||
|
||||
for (int j = 0; j < mas.length; j++)
|
||||
{
|
||||
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(),
|
||||
line.getM_Locator_ID(),
|
||||
line.getM_Product_ID(),
|
||||
ma.getM_AttributeSetInstance_ID(),
|
||||
QtyMA.negate(),ma.getDateMaterialPolicy(), get_TrxName()))
|
||||
line.getM_AttributeSetInstance_ID(),
|
||||
qtyDiff,dateMPolicy,get_TrxName()))
|
||||
{
|
||||
String lastError = CLogger.retrieveErrorString("");
|
||||
m_processMsg = "Cannot correct Inventory (MA) - " + lastError;
|
||||
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(), ma.getM_AttributeSetInstance_ID(),ma.getDateMaterialPolicy(),get_TrxName());
|
||||
line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(),dateMPolicy, get_TrxName());
|
||||
|
||||
storage.setDateLastInventory(getMovementDate());
|
||||
if (!storage.save(get_TrxName()))
|
||||
{
|
||||
|
@ -541,87 +604,40 @@ public class MInventory extends X_M_Inventory implements DocAction
|
|||
return DocAction.STATUS_Invalid;
|
||||
}
|
||||
}
|
||||
|
||||
String m_MovementType =null;
|
||||
if(QtyMA.negate().compareTo(Env.ZERO) > 0 )
|
||||
|
||||
String m_MovementType = null;
|
||||
if(qtyDiff.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(),
|
||||
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()))
|
||||
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 = "Storage not updated(2)";
|
||||
m_processMsg = "Transaction not inserted(2)";
|
||||
return DocAction.STATUS_Invalid;
|
||||
}
|
||||
}
|
||||
|
||||
String m_MovementType = null;
|
||||
if(qtyDiff.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(), 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
|
||||
}
|
||||
} // 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)
|
||||
|
|
|
@ -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,174 +427,190 @@ public class MMovement extends X_M_Movement implements DocAction
|
|||
|
||||
//Stock Movement - Counterpart MOrder.reserveStock
|
||||
MProduct product = line.getProduct();
|
||||
if (product != null
|
||||
&& product.isStocked() )
|
||||
try
|
||||
{
|
||||
//Ignore the Material Policy when is Reverse Correction
|
||||
if(!isReversal()){
|
||||
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)
|
||||
if (product != null
|
||||
&& product.isStocked() )
|
||||
{
|
||||
MMovementLineMA mas[] = MMovementLineMA.get(getCtx(),
|
||||
line.getM_MovementLine_ID(), get_TrxName());
|
||||
for (int j = 0; j < mas.length; j++)
|
||||
//Ignore the Material Policy when is Reverse Correction
|
||||
if(!isReversal()){
|
||||
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());
|
||||
//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(),
|
||||
ma.getM_AttributeSetInstance_ID(),
|
||||
ma.getMovementQty().negate(),ma.getDateMaterialPolicy(), get_TrxName()))
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
//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(),
|
||||
M_AttributeSetInstanceTo_ID,
|
||||
ma.getMovementQty(),ma.getDateMaterialPolicy(), get_TrxName()))
|
||||
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(), ma.getM_AttributeSetInstance_ID(),
|
||||
ma.getMovementQty().negate(), getMovementDate(), get_TrxName());
|
||||
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 (MA)";
|
||||
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(), M_AttributeSetInstanceTo_ID,
|
||||
ma.getMovementQty(), getMovementDate(), get_TrxName());
|
||||
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 (MA)";
|
||||
m_processMsg = "Transaction To not inserted";
|
||||
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());
|
||||
//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
|
||||
} // 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)
|
||||
|
|
|
@ -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,23 +175,35 @@ public class MProjectIssue extends X_C_ProjectIssue
|
|||
dateMPolicy = t;
|
||||
}
|
||||
|
||||
if (MStorageOnHand.add(getCtx(), loc.getM_Warehouse_ID(), getM_Locator_ID(),
|
||||
getM_Product_ID(), getM_AttributeSetInstance_ID(),
|
||||
getMovementQty().negate(),dateMPolicy, get_TrxName()))
|
||||
try
|
||||
{
|
||||
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 (save())
|
||||
return true;
|
||||
if (mTrx.save(get_TrxName()))
|
||||
{
|
||||
setProcessed (true);
|
||||
if (save())
|
||||
return true;
|
||||
else
|
||||
log.log(Level.SEVERE, "Issue not saved"); // requires trx !!
|
||||
}
|
||||
else
|
||||
log.log(Level.SEVERE, "Issue not saved"); // requires trx !!
|
||||
log.log(Level.SEVERE, "Transaction not saved"); // requires trx !!
|
||||
}
|
||||
else
|
||||
log.log(Level.SEVERE, "Transaction not saved"); // requires trx !!
|
||||
log.log(Level.SEVERE, "Storage not updated"); // OK
|
||||
}
|
||||
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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
@ -874,35 +876,47 @@ public class MDDOrder extends X_DD_Order implements DocAction
|
|||
MProduct product = line.getProduct();
|
||||
if (product != null)
|
||||
{
|
||||
if (product.isStocked())
|
||||
try
|
||||
{
|
||||
// Update Storage
|
||||
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()))
|
||||
if (product.isStocked())
|
||||
{
|
||||
throw new AdempiereException();
|
||||
}
|
||||
|
||||
if (!MStorageOnHand.add(getCtx(), locator_from.getM_Warehouse_ID(), locator_from.getM_Locator_ID(),
|
||||
line.getM_Product_ID(),
|
||||
line.getM_AttributeSetInstanceTo_ID(),
|
||||
Env.ZERO,null, get_TrxName()))
|
||||
{
|
||||
throw new AdempiereException();
|
||||
}
|
||||
|
||||
} // 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()));
|
||||
// Update Storage
|
||||
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();
|
||||
}
|
||||
|
||||
if (!MStorageOnHand.add(getCtx(), locator_from.getM_Warehouse_ID(), locator_from.getM_Locator_ID(),
|
||||
line.getM_Product_ID(),
|
||||
line.getM_AttributeSetInstanceTo_ID(),
|
||||
Env.ZERO,null, get_TrxName()))
|
||||
{
|
||||
throw new AdempiereException();
|
||||
}
|
||||
|
||||
} // 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
|
||||
} // reverse inventory
|
||||
|
||||
if (errors.toString().length() > 0)
|
||||
throw new AdempiereException(errors.toString());
|
||||
|
||||
setVolume(Volume);
|
||||
setWeight(Weight);
|
||||
} // reserveStock
|
||||
|
|
Loading…
Reference in New Issue