Issuing of stock should ignore storage with onhand <= 0 - ID: 2545020

http://sourceforge.net/tracker2/index.php?func=detail&aid=2545020&group_id=176962&atid=879332
Merge change from 8234 revision
http://adempiere.svn.sourceforge.net/viewvc/adempiere?view=rev&revision=8234

[ 2545020 ] Issuing of stock should ignore storage with onhand <= 0
- Only process storage with qtyOnHand > 0 when fulfilling for customer shipment, inventory movement and physical inventory.
- Remove remarked code.
- Fixed javadoc in MStorage, restore the original behaviour of getAllASI. Refactor getWarehouse method as the primary method use to
  retrieve storage records for customer shipment, inventory movement and physical inventory transaction.
- Fixed MStorage.getWarehouse to behave as stated in the javadoc, i.e always respect the locator priority.
- Remove the linePerASI logic in InOutGenerate so that the actual allocation of storage only happens in MInOut. Ensure proper reset
  of storage cache.
This commit is contained in:
vpj-cd 2009-01-30 02:04:42 +00:00
parent ccb8dc48a5
commit 9003312769
5 changed files with 1684 additions and 1867 deletions

View File

@ -1654,7 +1654,6 @@ public class MInOut extends X_M_InOut implements DocAction
boolean needSave = false; boolean needSave = false;
BigDecimal qtyASI = Env.ZERO ;
MProduct product = line.getProduct(); MProduct product = line.getProduct();
@ -1694,65 +1693,12 @@ public class MInOut extends X_M_InOut implements DocAction
else if(getMovementType().compareTo(MInOut.MOVEMENTTYPE_VendorReturns) == 0 || getMovementType().compareTo(MInOut.MOVEMENTTYPE_CustomerShipment) == 0) else if(getMovementType().compareTo(MInOut.MOVEMENTTYPE_VendorReturns) == 0 || getMovementType().compareTo(MInOut.MOVEMENTTYPE_CustomerShipment) == 0)
{ {
String MMPolicy = product.getMMPolicy(); String MMPolicy = product.getMMPolicy();
MStorage[] storages = MStorage.getAllWithASI(getCtx(), Timestamp minGuaranteeDate = getMovementDate();
line.getM_Product_ID(), line.getM_Locator_ID(), MStorage[] storages = MStorage.getWarehouse(getCtx(), getM_Warehouse_ID(), line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(),
MClient.MMPOLICY_FiFo.equals(MMPolicy), get_TrxName()); minGuaranteeDate, MClient.MMPOLICY_FiFo.equals(MMPolicy), true, line.getM_Locator_ID(), get_TrxName());
BigDecimal qtyToDeliver = line.getMovementQty(); BigDecimal qtyToDeliver = line.getMovementQty();
/*for (int ii = 0; ii < storages.length; ii++)
{
MStorage storage = storages[ii];
if (ii == 0)
{
if (storage.getQtyOnHand().compareTo(qtyToDeliver) >= 0)
{
line.setM_AttributeSetInstance_ID(storage.getM_AttributeSetInstance_ID());
needSave = true;
log.config("Direct - " + line);
qtyToDeliver = Env.ZERO;
}
else
{
log.config("Split - " + line);
MInOutLineMA ma = new MInOutLineMA (line,
storage.getM_AttributeSetInstance_ID(),
storage.getQtyOnHand());
if (!ma.save())
;
qtyToDeliver = qtyToDeliver.subtract(storage.getQtyOnHand());
log.fine("#" + ii + ": " + ma + ", QtyToDeliver=" + qtyToDeliver);
}
}
else // create addl material allocation
{
MInOutLineMA ma = new MInOutLineMA (line,
storage.getM_AttributeSetInstance_ID(),
qtyToDeliver);
if (storage.getQtyOnHand().compareTo(qtyToDeliver) >= 0)
qtyToDeliver = Env.ZERO;
else
{
ma.setMovementQty(storage.getQtyOnHand());
qtyToDeliver = qtyToDeliver.subtract(storage.getQtyOnHand());
}
if (!ma.save())
;
log.fine("#" + ii + ": " + ma + ", QtyToDeliver=" + qtyToDeliver);
}
if (qtyToDeliver.signum() == 0)
break;
} // for all storages
*/
for (MStorage storage: storages) for (MStorage storage: storages)
{ {
//consume ASI Zero
if (storage.getM_AttributeSetInstance_ID() == 0)
{
qtyASI = qtyASI.add(storage.getQtyOnHand());
qtyToDeliver = qtyToDeliver.subtract(storage.getQtyOnHand());
continue;
}
if (storage.getQtyOnHand().compareTo(qtyToDeliver) >= 0) if (storage.getQtyOnHand().compareTo(qtyToDeliver) >= 0)
{ {
MInOutLineMA ma = new MInOutLineMA (line, MInOutLineMA ma = new MInOutLineMA (line,
@ -1779,11 +1725,11 @@ public class MInOut extends X_M_InOut implements DocAction
} }
// No AttributeSetInstance found for remainder // No AttributeSetInstance found for remainder
if (qtyToDeliver.signum() != 0 || qtyASI.signum() != 0) if (qtyToDeliver.signum() != 0)
{ {
MInOutLineMA ma = new MInOutLineMA (line, 0, qtyToDeliver.add(qtyASI)); MInOutLineMA ma = new MInOutLineMA (line, 0, qtyToDeliver);
if (!ma.save()) if (!ma.save())
; throw new IllegalStateException("Error try create ASI Reservation");
log.fine("##: " + ma); log.fine("##: " + ma);
} }
} // outgoing Trx } // outgoing Trx

View File

@ -27,7 +27,6 @@ import java.util.logging.Level;
import org.compiere.process.DocAction; import org.compiere.process.DocAction;
import org.compiere.process.DocumentEngine; import org.compiere.process.DocumentEngine;
import org.compiere.report.MReportTree;
import org.compiere.util.CCache; import org.compiere.util.CCache;
import org.compiere.util.DB; import org.compiere.util.DB;
import org.compiere.util.Env; import org.compiere.util.Env;
@ -38,10 +37,8 @@ import org.compiere.util.Msg;
* *
* @author Jorg Janke * @author Jorg Janke
* @version $Id: MInventory.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ * @version $Id: MInventory.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $
* @author victor.perez@e-evolution.com, e-Evolution http://www.e-evolution.com * @author victor.perez@e-evolution.com, e-Evolution
* <li>FR [ 1948157 ] Is necessary the reference for document reverse * <li>FR [ 1948157 ] Is necessary the reference for document reverse
* <li> FR [ 2520591 ] Support multiples calendar for Org
* @see http://sourceforge.net/tracker2/?func=detail&atid=879335&aid=2520591&group_id=176962
* @author Armen Rizal, Goodwill Consulting * @author Armen Rizal, Goodwill Consulting
* <li>BF [ 1745154 ] Cost in Reversing Material Related Docs * <li>BF [ 1745154 ] Cost in Reversing Material Related Docs
* @see http://sourceforge.net/tracker/?func=detail&atid=879335&aid=1948157&group_id=176962 * @see http://sourceforge.net/tracker/?func=detail&atid=879335&aid=1948157&group_id=176962
@ -329,7 +326,7 @@ public class MInventory extends X_M_Inventory implements DocAction
return DocAction.STATUS_Invalid; return DocAction.STATUS_Invalid;
// Std Period open? // Std Period open?
if (!MPeriod.isOpen(getCtx(), getMovementDate(), MDocType.DOCBASETYPE_MaterialPhysicalInventory, getAD_Org_ID())) if (!MPeriod.isOpen(getCtx(), getMovementDate(), MDocType.DOCBASETYPE_MaterialPhysicalInventory))
{ {
m_processMsg = "@PeriodClosed@"; m_processMsg = "@PeriodClosed@";
return DocAction.STATUS_Invalid; return DocAction.STATUS_Invalid;
@ -470,21 +467,13 @@ public class MInventory extends X_M_Inventory implements DocAction
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(), ma.getM_AttributeSetInstance_ID(),
QtyMA.negate(), getMovementDate(), get_TrxName()); QtyMA.negate(), 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)";
m_processMsg = "Transaction not inserted(2)"; return DocAction.STATUS_Invalid;
return DocAction.STATUS_Invalid; }
} qtyDiff = QtyNew;
if(QtyMA.signum() != 0)
{
String err = createCostDetail(line, ma.getM_AttributeSetInstance_ID() , QtyMA.negate());
if(err != null && err.length() > 0) return err;
}
qtyDiff = QtyNew;
} }
} }
@ -532,15 +521,10 @@ public class MInventory extends X_M_Inventory implements DocAction
m_processMsg = "Transaction not inserted(2)"; m_processMsg = "Transaction not inserted(2)";
return DocAction.STATUS_Invalid; return DocAction.STATUS_Invalid;
} }
if(qtyDiff.signum() != 0)
{
String err = createCostDetail(line, line.getM_AttributeSetInstance_ID(), qtyDiff);
if(err != null && err.length() > 0) return err;
}
} // Fallback } // Fallback
} // stock movement } // stock movement
} // for all lines } // for all lines
// User Validation // User Validation
@ -589,7 +573,6 @@ public class MInventory extends X_M_Inventory implements DocAction
// Check Line // Check Line
boolean needSave = false; boolean needSave = false;
BigDecimal qtyASI = Env.ZERO ;
// Attribute Set Instance // Attribute Set Instance
if (line.getM_AttributeSetInstance_ID() == 0) if (line.getM_AttributeSetInstance_ID() == 0)
{ {
@ -612,21 +595,12 @@ public class MInventory extends X_M_Inventory implements DocAction
else // Outgoing Trx else // Outgoing Trx
{ {
String MMPolicy = product.getMMPolicy(); String MMPolicy = product.getMMPolicy();
MStorage[] storages = MStorage.getAllWithASI(getCtx(), MStorage[] storages = MStorage.getWarehouse(getCtx(), getM_Warehouse_ID(), line.getM_Product_ID(), 0,
line.getM_Product_ID(), line.getM_Locator_ID(), null, MClient.MMPOLICY_FiFo.equals(MMPolicy), true, line.getM_Locator_ID(), get_TrxName());
MClient.MMPOLICY_FiFo.equals(MMPolicy), get_TrxName());
BigDecimal qtyToDeliver = qtyDiff.negate(); BigDecimal qtyToDeliver = qtyDiff.negate();
for (MStorage storage: storages) for (MStorage storage: storages)
{ {
//cosume ASI Zero
if (storage.getM_AttributeSetInstance_ID() == 0)
{
qtyASI = qtyASI.add(storage.getQtyOnHand());
qtyToDeliver = qtyToDeliver.subtract(storage.getQtyOnHand());
continue;
}
if (storage.getQtyOnHand().compareTo(qtyToDeliver) >= 0) if (storage.getQtyOnHand().compareTo(qtyToDeliver) >= 0)
{ {
MInventoryLineMA ma = new MInventoryLineMA (line, MInventoryLineMA ma = new MInventoryLineMA (line,
@ -655,12 +629,12 @@ public class MInventory extends X_M_Inventory implements DocAction
} }
// No AttributeSetInstance found for remainder // No AttributeSetInstance found for remainder
if (qtyToDeliver.signum() != 0 || qtyASI.signum() != 0) if (qtyToDeliver.signum() != 0)
{ {
MInventoryLineMA ma = new MInventoryLineMA (line, 0 , qtyToDeliver.add(qtyASI)); MInventoryLineMA ma = new MInventoryLineMA (line, 0 , qtyToDeliver);
if (!ma.save()) if (!ma.save())
; throw new IllegalStateException("Error try create ASI Reservation");
log.fine("##: " + ma); log.fine("##: " + ma);
} }
} // outgoing Trx } // outgoing Trx
@ -762,7 +736,7 @@ public class MInventory extends X_M_Inventory implements DocAction
return false; return false;
MDocType dt = MDocType.get(getCtx(), getC_DocType_ID()); MDocType dt = MDocType.get(getCtx(), getC_DocType_ID());
if (!MPeriod.isOpen(getCtx(), getMovementDate(), dt.getDocBaseType(), getAD_Org_ID())) if (!MPeriod.isOpen(getCtx(), getMovementDate(), dt.getDocBaseType()))
{ {
m_processMsg = "@PeriodClosed@"; m_processMsg = "@PeriodClosed@";
return false; return false;
@ -777,8 +751,6 @@ public class MInventory extends X_M_Inventory implements DocAction
reversal.setPosted(false); reversal.setPosted(false);
reversal.setProcessed(false); reversal.setProcessed(false);
reversal.addDescription("{->" + getDocumentNo() + ")"); reversal.addDescription("{->" + getDocumentNo() + ")");
//FR1948157
reversal.setReversal_ID(getM_Inventory_ID());
if (!reversal.save()) if (!reversal.save())
{ {
m_processMsg = "Could not create Inventory Reversal"; m_processMsg = "Could not create Inventory Reversal";
@ -795,10 +767,6 @@ public class MInventory extends X_M_Inventory implements DocAction
copyValues(oLine, rLine, oLine.getAD_Client_ID(), oLine.getAD_Org_ID()); copyValues(oLine, rLine, oLine.getAD_Client_ID(), oLine.getAD_Org_ID());
rLine.setM_Inventory_ID(reversal.getM_Inventory_ID()); rLine.setM_Inventory_ID(reversal.getM_Inventory_ID());
rLine.setParent(reversal); rLine.setParent(reversal);
//AZ Goodwill
// store original (voided/reversed) document line
rLine.setReversalLine_ID(oLine.getM_InventoryLine_ID());
//
rLine.setQtyBook (oLine.getQtyCount()); // switch rLine.setQtyBook (oLine.getQtyCount()); // switch
rLine.setQtyCount (oLine.getQtyBook()); rLine.setQtyCount (oLine.getQtyBook());
rLine.setQtyInternalUse (oLine.getQtyInternalUse().negate()); rLine.setQtyInternalUse (oLine.getQtyInternalUse().negate());
@ -820,7 +788,7 @@ public class MInventory extends X_M_Inventory implements DocAction
mas[j].getM_AttributeSetInstance_ID(), mas[j].getM_AttributeSetInstance_ID(),
mas[j].getMovementQty().negate()); mas[j].getMovementQty().negate());
if (!ma.save()) if (!ma.save())
; throw new IllegalStateException("Error try create ASI Reservation");
} }
} }
} }
@ -843,8 +811,6 @@ public class MInventory extends X_M_Inventory implements DocAction
if (m_processMsg != null) if (m_processMsg != null)
return false; return false;
setProcessed(true); setProcessed(true);
//FR1948157
setReversal_ID(reversal.getM_Inventory_ID());
setDocStatus(DOCSTATUS_Reversed); // may come from void setDocStatus(DOCSTATUS_Reversed); // may come from void
setDocAction(DOCACTION_None); setDocAction(DOCACTION_None);
@ -959,54 +925,5 @@ public class MInventory extends X_M_Inventory implements DocAction
return m_reversal; return m_reversal;
} // isReversal } // isReversal
/**
* Create Cost Detail
* @param line
* @param Qty
* @return
*/
private String createCostDetail(MInventoryLine line,int M_AttributeSetInstance_ID, BigDecimal qty)
{
// Get Account Schemas to create MCostDetail
MAcctSchema[] acctschemas = MAcctSchema.getClientAcctSchema(getCtx(), getAD_Client_ID());
for(int asn = 0; asn < acctschemas.length; asn++)
{
MAcctSchema as = acctschemas[asn];
boolean skip = false;
if (as.getAD_OrgOnly_ID() != 0)
{
if (as.getOnlyOrgs() == null)
as.setOnlyOrgs(MReportTree.getChildIDs(getCtx(),
0, MAcctSchemaElement.ELEMENTTYPE_Organization,
as.getAD_OrgOnly_ID()));
// Header Level Org
skip = as.isSkipOrg(getAD_Org_ID());
// Line Level Org
skip = as.isSkipOrg(line.getAD_Org_ID());
}
if (skip)
continue;
ProductCost pc = new ProductCost (Env.getCtx(),
line.getM_Product_ID(), M_AttributeSetInstance_ID, line.get_TrxName());
pc.setQty(qty);
BigDecimal costs = pc.getProductCosts(as, line.getAD_Org_ID(), as.getCostingMethod(),
0,false);
if (costs == null || costs.signum() == 0)
{
return "No Costs for " + line.getProduct().getName();
}
// Set Total Amount and Total Quantity from Inventory
MCostDetail.createInventory(as, line.getAD_Org_ID(),
line.getM_Product_ID(), M_AttributeSetInstance_ID,
line.getM_InventoryLine_ID(), 0, // no cost element
costs.multiply(qty), qty,
line.getDescription(), line.get_TrxName());
}
return "";
}
} // MInventory } // MInventory

View File

@ -658,81 +658,19 @@ public class MMovement extends X_M_Movement implements DocAction
//{ //{
// MMovementLine line = lines[i]; // MMovementLine line = lines[i];
boolean needSave = false; boolean needSave = false;
BigDecimal qtyASI = Env.ZERO ;
// Attribute Set Instance // Attribute Set Instance
if (line.getM_AttributeSetInstance_ID() == 0) if (line.getM_AttributeSetInstance_ID() == 0)
{ {
MProduct product = MProduct.get(getCtx(), line.getM_Product_ID()); MProduct product = MProduct.get(getCtx(), line.getM_Product_ID());
String MMPolicy = product.getMMPolicy(); String MMPolicy = product.getMMPolicy();
MStorage[] storages = MStorage.getAllWithASI(getCtx(), MStorage[] storages = MStorage.getWarehouse(getCtx(), 0, line.getM_Product_ID(), 0,
line.getM_Product_ID(), line.getM_Locator_ID(), null, MClient.MMPOLICY_FiFo.equals(MMPolicy), true, line.getM_Locator_ID(), get_TrxName());
MClient.MMPOLICY_FiFo.equals(MMPolicy), get_TrxName());
BigDecimal qtyToDeliver = line.getMovementQty(); BigDecimal qtyToDeliver = line.getMovementQty();
/*for (int ii = 0; ii < storages.length; ii++)
{
MStorage storage = storages[ii];
if (ii == 0)
{
if (storage.getQtyOnHand().compareTo(qtyToDeliver) >= 0)
{
line.setM_AttributeSetInstance_ID(storage.getM_AttributeSetInstance_ID());
needSave = true;
log.config("Direct - " + line);
qtyToDeliver = Env.ZERO;
}
else
{
log.config("Split - " + line);
MMovementLineMA ma = new MMovementLineMA (line,
storage.getM_AttributeSetInstance_ID(),
storage.getQtyOnHand());
if (!ma.save())
;
qtyToDeliver = qtyToDeliver.subtract(storage.getQtyOnHand());
log.fine("#" + ii + ": " + ma + ", QtyToDeliver=" + qtyToDeliver);
}
}
else // create addl material allocation
{
MMovementLineMA ma = new MMovementLineMA (line,
storage.getM_AttributeSetInstance_ID(),
qtyToDeliver);
if (storage.getQtyOnHand().compareTo(qtyToDeliver) >= 0)
qtyToDeliver = Env.ZERO;
else
{
ma.setMovementQty(storage.getQtyOnHand());
qtyToDeliver = qtyToDeliver.subtract(storage.getQtyOnHand());
}
if (!ma.save())
;
log.fine("#" + ii + ": " + ma + ", QtyToDeliver=" + qtyToDeliver);
}
if (qtyToDeliver.signum() == 0)
break;
} // for all storages
// No AttributeSetInstance found for remainder
if (qtyToDeliver.signum() != 0)
{
MMovementLineMA ma = new MMovementLineMA (line,
0, qtyToDeliver);
if (!ma.save())
;
log.fine("##: " + ma);
}*/
for (MStorage storage: storages) for (MStorage storage: storages)
{ {
//consume ASI Zero
if (storage.getM_AttributeSetInstance_ID() == 0)
{
qtyASI = qtyASI.add(storage.getQtyOnHand());
qtyToDeliver = qtyToDeliver.subtract(storage.getQtyOnHand());
continue;
}
if (storage.getQtyOnHand().compareTo(qtyToDeliver) >= 0) if (storage.getQtyOnHand().compareTo(qtyToDeliver) >= 0)
{ {
MMovementLineMA ma = new MMovementLineMA (line, MMovementLineMA ma = new MMovementLineMA (line,
@ -761,12 +699,12 @@ public class MMovement extends X_M_Movement implements DocAction
} }
// No AttributeSetInstance found for remainder // No AttributeSetInstance found for remainder
if (qtyToDeliver.signum() != 0 || qtyASI.signum() != 0) if (qtyToDeliver.signum() != 0)
{ {
MMovementLineMA ma = new MMovementLineMA (line, 0 , qtyToDeliver.add(qtyASI)); MMovementLineMA ma = new MMovementLineMA (line, 0 , qtyToDeliver);
if (!ma.save()) if (!ma.save())
; throw new IllegalStateException("Error try create ASI Reservation");
log.fine("##: " + ma); log.fine("##: " + ma);
} }
} // attributeSetInstance } // attributeSetInstance

View File

@ -78,7 +78,6 @@ public class MStorage extends X_M_Storage
DB.close(rs, pstmt); DB.close(rs, pstmt);
rs = null; pstmt = null; rs = null; pstmt = null;
} }
pstmt = null;
if (retValue == null) if (retValue == null)
s_log.fine("Not Found - M_Locator_ID=" + M_Locator_ID s_log.fine("Not Found - M_Locator_ID=" + M_Locator_ID
+ ", M_Product_ID=" + M_Product_ID + ", M_AttributeSetInstance_ID=" + M_AttributeSetInstance_ID); + ", M_Product_ID=" + M_Product_ID + ", M_AttributeSetInstance_ID=" + M_AttributeSetInstance_ID);
@ -89,7 +88,7 @@ public class MStorage extends X_M_Storage
} // get } // get
/** /**
* Get all Storages for Product with ASI and QtyOnHand > 0 * Get all Storages for Product with ASI and QtyOnHand <> 0
* @param ctx context * @param ctx context
* @param M_Product_ID product * @param M_Product_ID product
* @param M_Locator_ID locator * @param M_Locator_ID locator
@ -103,13 +102,9 @@ public class MStorage extends X_M_Storage
ArrayList<MStorage> list = new ArrayList<MStorage>(); ArrayList<MStorage> list = new ArrayList<MStorage>();
String sql = "SELECT * FROM M_Storage " String sql = "SELECT * FROM M_Storage "
+ "WHERE M_Product_ID=? AND M_Locator_ID=?" + "WHERE M_Product_ID=? AND M_Locator_ID=?"
// Remove for management rightly FIFO/LIFO now you can consume a layer with ASI ID = zero and Qty onhand in negative + " AND M_AttributeSetInstance_ID > 0 "
// + " AND M_AttributeSetInstance_ID > 0"
// + " AND QtyOnHand > 0 "
+ " AND QtyOnHand <> 0 " + " AND QtyOnHand <> 0 "
+ "ORDER BY M_AttributeSetInstance_ID"; + "ORDER BY M_AttributeSetInstance_ID";
if (!FiFo)
sql += " DESC";
PreparedStatement pstmt = null; PreparedStatement pstmt = null;
ResultSet rs = null; ResultSet rs = null;
try try
@ -130,14 +125,13 @@ public class MStorage extends X_M_Storage
DB.close(rs, pstmt); DB.close(rs, pstmt);
rs = null; pstmt = null; rs = null; pstmt = null;
} }
pstmt = null;
MStorage[] retValue = new MStorage[list.size()]; MStorage[] retValue = new MStorage[list.size()];
list.toArray(retValue); list.toArray(retValue);
return retValue; return retValue;
} // getAllWithASI } // getAllWithASI
/** /**
* Get all Storages for Product * Get all Storages for Product where QtyOnHand <> 0
* @param ctx context * @param ctx context
* @param M_Product_ID product * @param M_Product_ID product
* @param M_Locator_ID locator * @param M_Locator_ID locator
@ -172,7 +166,6 @@ public class MStorage extends X_M_Storage
DB.close(rs, pstmt); DB.close(rs, pstmt);
rs = null; pstmt = null; rs = null; pstmt = null;
} }
pstmt = null;
MStorage[] retValue = new MStorage[list.size()]; MStorage[] retValue = new MStorage[list.size()];
list.toArray(retValue); list.toArray(retValue);
return retValue; return retValue;
@ -227,23 +220,41 @@ public class MStorage extends X_M_Storage
* @param FiFo first in-first-out * @param FiFo first in-first-out
* @param trxName transaction * @param trxName transaction
* @return existing - ordered by location priority (desc) and/or guarantee date * @return existing - ordered by location priority (desc) and/or guarantee date
*
* @deprecated
*/ */
public static MStorage[] getWarehouse (Properties ctx, int M_Warehouse_ID, public static MStorage[] getWarehouse (Properties ctx, int M_Warehouse_ID,
int M_Product_ID, int M_AttributeSetInstance_ID, int M_AttributeSet_ID, int M_Product_ID, int M_AttributeSetInstance_ID, int M_AttributeSet_ID,
boolean allAttributeInstances, Timestamp minGuaranteeDate, boolean allAttributeInstances, Timestamp minGuaranteeDate,
boolean FiFo, String trxName) boolean FiFo, String trxName)
{ {
if (M_Warehouse_ID == 0 || M_Product_ID == 0) return getWarehouse(ctx, M_Warehouse_ID, M_Product_ID, M_AttributeSetInstance_ID,
minGuaranteeDate, FiFo, false, 0, trxName);
}
/**
* Get Storage Info for Warehouse or locator
* @param ctx context
* @param M_Warehouse_ID ignore if M_Locator_ID > 0
* @param M_Product_ID product
* @param M_AttributeSetInstance_ID instance id, 0 to retrieve all instance
* @param minGuaranteeDate optional minimum guarantee date if all attribute instances
* @param FiFo first in-first-out
* @param positiveOnly if true, only return storage records with qtyOnHand > 0
* @param M_Locator_ID optional locator id
* @param trxName transaction
* @return existing - ordered by location priority (desc) and/or guarantee date
*/
public static MStorage[] getWarehouse (Properties ctx, int M_Warehouse_ID,
int M_Product_ID, int M_AttributeSetInstance_ID, Timestamp minGuaranteeDate,
boolean FiFo, boolean positiveOnly, int M_Locator_ID, String trxName)
{
if ((M_Warehouse_ID == 0 && M_Locator_ID == 0) || M_Product_ID == 0)
return new MStorage[0]; return new MStorage[0];
if (M_AttributeSet_ID == 0) boolean allAttributeInstances = false;
if (M_AttributeSetInstance_ID == 0)
allAttributeInstances = true; allAttributeInstances = true;
else
{
MAttributeSet mas = MAttributeSet.get(ctx, M_AttributeSet_ID);
if (!mas.isInstanceAttribute())
allAttributeInstances = true;
}
ArrayList<MStorage> list = new ArrayList<MStorage>(); ArrayList<MStorage> list = new ArrayList<MStorage>();
// Specific Attribute Set Instance // Specific Attribute Set Instance
@ -251,11 +262,18 @@ public class MStorage extends X_M_Storage
+ "s.AD_Client_ID,s.AD_Org_ID,s.IsActive,s.Created,s.CreatedBy,s.Updated,s.UpdatedBy," + "s.AD_Client_ID,s.AD_Org_ID,s.IsActive,s.Created,s.CreatedBy,s.Updated,s.UpdatedBy,"
+ "s.QtyOnHand,s.QtyReserved,s.QtyOrdered,s.DateLastInventory " + "s.QtyOnHand,s.QtyReserved,s.QtyOrdered,s.DateLastInventory "
+ "FROM M_Storage s" + "FROM M_Storage s"
+ " INNER JOIN M_Locator l ON (l.M_Locator_ID=s.M_Locator_ID) " + " INNER JOIN M_Locator l ON (l.M_Locator_ID=s.M_Locator_ID) ";
+ "WHERE l.M_Warehouse_ID=?" if (M_Locator_ID > 0)
+ " AND s.M_Product_ID=?" sql += "WHERE l.M_Locator_ID = ?";
+ " AND COALESCE(s.M_AttributeSetInstance_ID,0)=? " else
+ "ORDER BY l.PriorityNo DESC, M_AttributeSetInstance_ID"; sql += "WHERE l.M_Warehouse_ID=?";
sql += " AND s.M_Product_ID=?"
+ " AND COALESCE(s.M_AttributeSetInstance_ID,0)=? ";
if (positiveOnly)
{
sql += " AND s.QtyOnHand > 0 ";
}
sql += "ORDER BY l.PriorityNo DESC, M_AttributeSetInstance_ID";
if (!FiFo) if (!FiFo)
sql += " DESC"; sql += " DESC";
// All Attribute Set Instances // All Attribute Set Instances
@ -266,19 +284,31 @@ public class MStorage extends X_M_Storage
+ "s.QtyOnHand,s.QtyReserved,s.QtyOrdered,s.DateLastInventory " + "s.QtyOnHand,s.QtyReserved,s.QtyOrdered,s.DateLastInventory "
+ "FROM M_Storage s" + "FROM M_Storage s"
+ " INNER JOIN M_Locator l ON (l.M_Locator_ID=s.M_Locator_ID)" + " INNER JOIN M_Locator l ON (l.M_Locator_ID=s.M_Locator_ID)"
+ " LEFT OUTER JOIN M_AttributeSetInstance asi ON (s.M_AttributeSetInstance_ID=asi.M_AttributeSetInstance_ID) " + " LEFT OUTER JOIN M_AttributeSetInstance asi ON (s.M_AttributeSetInstance_ID=asi.M_AttributeSetInstance_ID) ";
+ "WHERE l.M_Warehouse_ID=?" if (M_Locator_ID > 0)
+ " AND s.M_Product_ID=? "; sql += "WHERE l.M_Locator_ID = ?";
else
sql += "WHERE l.M_Warehouse_ID=?";
sql += " AND s.M_Product_ID=? ";
if (minGuaranteeDate != null) if (minGuaranteeDate != null)
{ {
sql += "AND (asi.GuaranteeDate IS NULL OR asi.GuaranteeDate>?) " sql += "AND (asi.GuaranteeDate IS NULL OR asi.GuaranteeDate>?) ";
+ "ORDER BY asi.GuaranteeDate, M_AttributeSetInstance_ID"; if (positiveOnly)
{
sql += " AND s.QtyOnHand > 0 ";
}
sql += "ORDER BY l.PriorityNo DESC, " +
"asi.GuaranteeDate, M_AttributeSetInstance_ID";
if (!FiFo) if (!FiFo)
sql += " DESC"; sql += " DESC";
sql += ", l.PriorityNo DESC, s.QtyOnHand DESC"; sql += ", s.QtyOnHand DESC";
} }
else else
{ {
if (positiveOnly)
{
sql += " AND s.QtyOnHand > 0 ";
}
sql += "ORDER BY l.PriorityNo DESC, l.M_Locator_ID, s.M_AttributeSetInstance_ID"; sql += "ORDER BY l.PriorityNo DESC, l.M_Locator_ID, s.M_AttributeSetInstance_ID";
if (!FiFo) if (!FiFo)
sql += " DESC"; sql += " DESC";
@ -290,12 +320,16 @@ public class MStorage extends X_M_Storage
try try
{ {
pstmt = DB.prepareStatement(sql, trxName); pstmt = DB.prepareStatement(sql, trxName);
pstmt.setInt(1, M_Warehouse_ID); pstmt.setInt(1, M_Locator_ID > 0 ? M_Locator_ID : M_Warehouse_ID);
pstmt.setInt(2, M_Product_ID); pstmt.setInt(2, M_Product_ID);
if (!allAttributeInstances) if (!allAttributeInstances)
{
pstmt.setInt(3, M_AttributeSetInstance_ID); pstmt.setInt(3, M_AttributeSetInstance_ID);
}
else if (minGuaranteeDate != null) else if (minGuaranteeDate != null)
{
pstmt.setTimestamp(3, minGuaranteeDate); pstmt.setTimestamp(3, minGuaranteeDate);
}
rs = pstmt.executeQuery(); rs = pstmt.executeQuery();
while (rs.next()) while (rs.next())
list.add (new MStorage (ctx, rs, trxName)); list.add (new MStorage (ctx, rs, trxName));

View File

@ -1,5 +1,5 @@
/****************************************************************************** /******************************************************************************
* Product: Adempiere ERP & CRM Smart Business Solution * * Product: Adempiere ERP & CRM Smart Business Solution *
* Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. * * Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. *
* This program is free software; you can redistribute it and/or modify it * * 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 * * under the terms version 2 of the GNU General Public License as published *
@ -16,25 +16,13 @@
*****************************************************************************/ *****************************************************************************/
package org.compiere.process; package org.compiere.process;
import java.math.BigDecimal; import java.math.*;
import java.sql.PreparedStatement; import java.sql.*;
import java.sql.ResultSet; import java.util.*;
import java.sql.Timestamp; import java.util.logging.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.logging.Level;
import org.compiere.model.MAttributeSet; import org.compiere.model.*;
import org.compiere.model.MClient; import org.compiere.util.*;
import org.compiere.model.MInOut;
import org.compiere.model.MInOutLine;
import org.compiere.model.MOrder;
import org.compiere.model.MOrderLine;
import org.compiere.model.MProduct;
import org.compiere.model.MStorage;
import org.compiere.util.AdempiereUserError;
import org.compiere.util.DB;
import org.compiere.util.Env;
/** /**
* Generate Shipments. * Generate Shipments.
@ -208,7 +196,6 @@ public class InOutGenerate extends SvrProcess
*/ */
private String generate (PreparedStatement pstmt) private String generate (PreparedStatement pstmt)
{ {
MClient client = MClient.get(getCtx());
try try
{ {
ResultSet rs = pstmt.executeQuery (); ResultSet rs = pstmt.executeQuery ();
@ -242,7 +229,7 @@ public class InOutGenerate extends SvrProcess
+ " INNER JOIN M_InOut io ON (iol.M_InOut_ID=io.M_InOut_ID) " + " INNER JOIN M_InOut io ON (iol.M_InOut_ID=io.M_InOut_ID) "
+ "WHERE iol.C_OrderLine_ID=C_OrderLine.C_OrderLine_ID AND io.DocStatus IN ('IP','WC'))"; + "WHERE iol.C_OrderLine_ID=C_OrderLine.C_OrderLine_ID AND io.DocStatus IN ('IP','WC'))";
// Deadlock Prevention - Order by M_Product_ID // Deadlock Prevention - Order by M_Product_ID
MOrderLine[] lines = order.getLines (where, "C_BPartner_Location_ID, M_Product_ID"); MOrderLine[] lines = order.getLines (where, "ORDER BY C_BPartner_Location_ID, M_Product_ID");
for (int i = 0; i < lines.length; i++) for (int i = 0; i < lines.length; i++)
{ {
MOrderLine line = lines[i]; MOrderLine line = lines[i];
@ -298,9 +285,7 @@ public class InOutGenerate extends SvrProcess
String MMPolicy = product.getMMPolicy(); String MMPolicy = product.getMMPolicy();
MStorage[] storages = getStorages(line.getM_Warehouse_ID(), MStorage[] storages = getStorages(line.getM_Warehouse_ID(),
line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(), line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(),
product.getM_AttributeSet_ID(), minGuaranteeDate, MClient.MMPOLICY_FiFo.equals(MMPolicy));
line.getM_AttributeSetInstance_ID()==0, minGuaranteeDate,
MClient.MMPOLICY_FiFo.equals(MMPolicy));
for (int j = 0; j < storages.length; j++) for (int j = 0; j < storages.length; j++)
{ {
@ -382,9 +367,7 @@ public class InOutGenerate extends SvrProcess
String MMPolicy = product.getMMPolicy(); String MMPolicy = product.getMMPolicy();
storages = getStorages(line.getM_Warehouse_ID(), storages = getStorages(line.getM_Warehouse_ID(),
line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(), line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(),
product.getM_AttributeSet_ID(), minGuaranteeDate, MClient.MMPOLICY_FiFo.equals(MMPolicy));
line.getM_AttributeSetInstance_ID()==0, minGuaranteeDate,
MClient.MMPOLICY_FiFo.equals(MMPolicy));
} }
// //
createLine (order, line, toDeliver, storages, false); createLine (order, line, toDeliver, storages, false);
@ -460,21 +443,13 @@ public class InOutGenerate extends SvrProcess
return; return;
} }
// Product
MProduct product = orderLine.getProduct();
boolean linePerASI = false;
if (product.getM_AttributeSet_ID() != 0)
{
MAttributeSet mas = MAttributeSet.get(getCtx(), product.getM_AttributeSet_ID());
linePerASI = mas.isInstanceAttribute();
}
// Inventory Lines // Inventory Lines
ArrayList<MInOutLine> list = new ArrayList<MInOutLine>(); ArrayList<MInOutLine> list = new ArrayList<MInOutLine>();
BigDecimal toDeliver = qty; BigDecimal toDeliver = qty;
for (int i = 0; i < storages.length; i++) for (int i = 0; i < storages.length; i++)
{ {
MStorage storage = storages[i]; MStorage storage = storages[i];
BigDecimal deliver = toDeliver; BigDecimal deliver = toDeliver;
// Not enough On Hand // Not enough On Hand
if (deliver.compareTo(storage.getQtyOnHand()) > 0 if (deliver.compareTo(storage.getQtyOnHand()) > 0
@ -489,12 +464,12 @@ public class InOutGenerate extends SvrProcess
int M_Locator_ID = storage.getM_Locator_ID(); int M_Locator_ID = storage.getM_Locator_ID();
// //
MInOutLine line = null; MInOutLine line = null;
if (!linePerASI) // find line with Locator if (orderLine.getM_AttributeSetInstance_ID() == 0) // find line with Locator
{ {
for (int ll = 0; ll < list.size(); ll++) for (int ll = 0; ll < list.size(); ll++)
{ {
MInOutLine test = (MInOutLine)list.get(ll); MInOutLine test = (MInOutLine)list.get(ll);
if (test.getM_Locator_ID() == M_Locator_ID) if (test.getM_Locator_ID() == M_Locator_ID && test.getM_AttributeSetInstance_ID() == 0)
{ {
line = test; line = test;
break; break;
@ -514,20 +489,33 @@ public class InOutGenerate extends SvrProcess
line.setQtyEntered(line.getMovementQty().multiply(orderLine.getQtyEntered()) line.setQtyEntered(line.getMovementQty().multiply(orderLine.getQtyEntered())
.divide(orderLine.getQtyOrdered(), 12, BigDecimal.ROUND_HALF_UP)); .divide(orderLine.getQtyOrdered(), 12, BigDecimal.ROUND_HALF_UP));
line.setLine(m_line + orderLine.getLine()); line.setLine(m_line + orderLine.getLine());
if (linePerASI)
line.setM_AttributeSetInstance_ID(storage.getM_AttributeSetInstance_ID());
if (!line.save()) if (!line.save())
throw new IllegalStateException("Could not create Shipment Line"); throw new IllegalStateException("Could not create Shipment Line");
log.fine("ToDeliver=" + qty + "/" + deliver + " - " + line); log.fine("ToDeliver=" + qty + "/" + deliver + " - " + line);
toDeliver = toDeliver.subtract(deliver); toDeliver = toDeliver.subtract(deliver);
// Temp adjustment // Temp adjustment, actual update happen in MInOut.completeIt
storage.setQtyOnHand(storage.getQtyOnHand().subtract(deliver)); storage.setQtyOnHand(storage.getQtyOnHand().subtract(deliver));
// //
if (toDeliver.signum() == 0) if (toDeliver.signum() == 0)
break; break;
} }
if (toDeliver.signum() != 0) if (toDeliver.signum() != 0 )
throw new IllegalStateException("Not All Delivered - Remainder=" + toDeliver); {
if (!force)
{
throw new IllegalStateException("Not All Delivered - Remainder=" + toDeliver);
}
else
{
MInOutLine line = new MInOutLine (m_shipment);
line.setOrderLine(orderLine, 0, order.isSOTrx() ? toDeliver : Env.ZERO);
line.setQty(toDeliver);
if (!line.save())
throw new IllegalStateException("Could not create Shipment Line");
}
}
} // createLine } // createLine
@ -536,20 +524,17 @@ public class InOutGenerate extends SvrProcess
* @param M_Warehouse_ID * @param M_Warehouse_ID
* @param M_Product_ID * @param M_Product_ID
* @param M_AttributeSetInstance_ID * @param M_AttributeSetInstance_ID
* @param M_AttributeSet_ID
* @param allAttributeInstances
* @param minGuaranteeDate * @param minGuaranteeDate
* @param FiFo * @param FiFo
* @return storages * @return storages
*/ */
private MStorage[] getStorages(int M_Warehouse_ID, private MStorage[] getStorages(int M_Warehouse_ID,
int M_Product_ID, int M_AttributeSetInstance_ID, int M_AttributeSet_ID, int M_Product_ID, int M_AttributeSetInstance_ID,
boolean allAttributeInstances, Timestamp minGuaranteeDate, Timestamp minGuaranteeDate, boolean FiFo)
boolean FiFo)
{ {
m_lastPP = new SParameter(M_Warehouse_ID, m_lastPP = new SParameter(M_Warehouse_ID,
M_Product_ID, M_AttributeSetInstance_ID, M_AttributeSet_ID, M_Product_ID, M_AttributeSetInstance_ID,
allAttributeInstances, minGuaranteeDate, FiFo); minGuaranteeDate, FiFo);
// //
m_lastStorages = m_map.get(m_lastPP); m_lastStorages = m_map.get(m_lastPP);
@ -557,8 +542,7 @@ public class InOutGenerate extends SvrProcess
{ {
m_lastStorages = MStorage.getWarehouse(getCtx(), m_lastStorages = MStorage.getWarehouse(getCtx(),
M_Warehouse_ID, M_Product_ID, M_AttributeSetInstance_ID, M_Warehouse_ID, M_Product_ID, M_AttributeSetInstance_ID,
M_AttributeSet_ID, allAttributeInstances, minGuaranteeDate, minGuaranteeDate, FiFo, true, 0 , get_TrxName());
FiFo, get_TrxName());
m_map.put(m_lastPP, m_lastStorages); m_map.put(m_lastPP, m_lastStorages);
} }
return m_lastStorages; return m_lastStorages;
@ -579,9 +563,11 @@ public class InOutGenerate extends SvrProcess
// //
addLog(m_shipment.getM_InOut_ID(), m_shipment.getMovementDate(), null, m_shipment.getDocumentNo()); addLog(m_shipment.getM_InOut_ID(), m_shipment.getMovementDate(), null, m_shipment.getDocumentNo());
m_created++; m_created++;
//reset storage cache as MInOut.completeIt will update m_storage
m_map = new HashMap<SParameter,MStorage[]>(); m_map = new HashMap<SParameter,MStorage[]>();
if (m_lastPP != null && m_lastStorages != null) m_lastPP = null;
m_map.put(m_lastPP, m_lastStorages); m_lastStorages = null;
} }
m_shipment = null; m_shipment = null;
m_line = 0; m_line = 0;
@ -597,21 +583,16 @@ public class InOutGenerate extends SvrProcess
* @param p_Warehouse_ID warehouse * @param p_Warehouse_ID warehouse
* @param p_Product_ID * @param p_Product_ID
* @param p_AttributeSetInstance_ID * @param p_AttributeSetInstance_ID
* @param p_AttributeSet_ID
* @param p_allAttributeInstances
* @param p_minGuaranteeDate * @param p_minGuaranteeDate
* @param p_FiFo * @param p_FiFo
*/ */
protected SParameter (int p_Warehouse_ID, protected SParameter (int p_Warehouse_ID,
int p_Product_ID, int p_AttributeSetInstance_ID, int p_AttributeSet_ID, int p_Product_ID, int p_AttributeSetInstance_ID,
boolean p_allAttributeInstances, Timestamp p_minGuaranteeDate, Timestamp p_minGuaranteeDate, boolean p_FiFo)
boolean p_FiFo)
{ {
this.M_Warehouse_ID = p_Warehouse_ID; this.M_Warehouse_ID = p_Warehouse_ID;
this.M_Product_ID = p_Product_ID; this.M_Product_ID = p_Product_ID;
this.M_AttributeSetInstance_ID = p_AttributeSetInstance_ID; this.M_AttributeSetInstance_ID = p_AttributeSetInstance_ID;
this.M_AttributeSet_ID = p_AttributeSet_ID;
this.allAttributeInstances = p_allAttributeInstances;
this.minGuaranteeDate = p_minGuaranteeDate; this.minGuaranteeDate = p_minGuaranteeDate;
this.FiFo = p_FiFo; this.FiFo = p_FiFo;
} }
@ -694,3 +675,4 @@ public class InOutGenerate extends SvrProcess
} // Parameter } // Parameter
} // InOutGenerate } // InOutGenerate