IDEMPIERE-5121 MStorageOnHand API enhancements (#1079)

This commit is contained in:
hengsin 2021-12-23 17:14:22 +08:00 committed by GitHub
parent a3872deb23
commit 93ebe43cbd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 301 additions and 45 deletions

View File

@ -191,7 +191,6 @@ public class CalloutInOut extends CalloutEngine
if (rs.next())
{
// Set Movement Type
String DocBaseType = rs.getString("DocBaseType");
// BF [2708789] Read IsSOTrx from C_DocType
String trxFlag = rs.getString("IsSOTrx");
Object isSOTrxValue = mTab.getValue("IsSOTrx");

View File

@ -1456,7 +1456,7 @@ public class MInOut extends X_M_InOut implements DocAction, IDocsPostProcess
}
// Update Storage - see also VMatch.createMatchRecord
if (!MStorageOnHand.add(getCtx(), getM_Warehouse_ID(),
if (!MStorageOnHand.add(getCtx(),
sLine.getM_Locator_ID(),
sLine.getM_Product_ID(),
ma.getM_AttributeSetInstance_ID(),
@ -1545,7 +1545,7 @@ public class MInOut extends X_M_InOut implements DocAction, IDocsPostProcess
} else if (storage.getQtyOnHand().signum() > 0) {
BigDecimal onHand = storage.getQtyOnHand();
// this locator has less qty than required, ship all qtyonhand and iterate to next locator
if (!MStorageOnHand.add(getCtx(), getM_Warehouse_ID(),
if (!MStorageOnHand.add(getCtx(),
sLine.getM_Locator_ID(),
sLine.getM_Product_ID(),
sLine.getM_AttributeSetInstance_ID(),
@ -1578,7 +1578,7 @@ public class MInOut extends X_M_InOut implements DocAction, IDocsPostProcess
// Fallback: Update Storage - see also VMatch.createMatchRecord
if (pendingQty.signum() != 0 &&
!MStorageOnHand.add(getCtx(), getM_Warehouse_ID(),
!MStorageOnHand.add(getCtx(),
sLine.getM_Locator_ID(),
sLine.getM_Product_ID(),
sLine.getM_AttributeSetInstance_ID(),
@ -2671,7 +2671,7 @@ public class MInOut extends X_M_InOut implements DocAction, IDocsPostProcess
return null;
if (reversal) {
if (!MStorageOnHand.add(getCtx(), getM_Warehouse_ID(), M_Locator_ID, product.getM_Product_ID(), 0, qty.negate(), dateMaterialPolicy, trxName)) {
if (!MStorageOnHand.add(getCtx(), M_Locator_ID, product.getM_Product_ID(), 0, qty.negate(), dateMaterialPolicy, trxName)) {
String lastError = CLogger.retrieveErrorString("");
m_processMsg = "Cannot move Inventory OnHand to Non ASI [" + product.getValue() + "] - " + lastError;
return DocAction.STATUS_Invalid;
@ -2683,7 +2683,7 @@ public class MInOut extends X_M_InOut implements DocAction, IDocsPostProcess
m_processMsg = "Transaction From not inserted (MA) [" + product.getValue() + "] - ";
return DocAction.STATUS_Invalid;
}
if (!MStorageOnHand.add(getCtx(), getM_Warehouse_ID(), M_Locator_ID, product.getM_Product_ID(), M_AttributeSetInstance_ID, qty, dateMaterialPolicy, trxName)) {
if (!MStorageOnHand.add(getCtx(), M_Locator_ID, product.getM_Product_ID(), M_AttributeSetInstance_ID, qty, dateMaterialPolicy, trxName)) {
String lastError = CLogger.retrieveErrorString("");
m_processMsg = "Cannot move Inventory OnHand to Shipment ASI [" + product.getValue() + "] - " + lastError;
return DocAction.STATUS_Invalid;
@ -2741,7 +2741,7 @@ public class MInOut extends X_M_InOut implements DocAction, IDocsPostProcess
if (!reversal && toMove.compareTo(onhand.getQtyOnHand()) >= 0) {
toMove = onhand.getQtyOnHand();
}
if (!MStorageOnHand.add(getCtx(), getM_Warehouse_ID(), M_Locator_ID, product.getM_Product_ID(), 0, toMove.negate(), onhand.getDateMaterialPolicy(), trxName)) {
if (!MStorageOnHand.add(getCtx(), M_Locator_ID, product.getM_Product_ID(), 0, toMove.negate(), onhand.getDateMaterialPolicy(), trxName)) {
String lastError = CLogger.retrieveErrorString("");
m_processMsg = "Cannot move Inventory OnHand to Non ASI [" + product.getValue() + "] - " + lastError;
return DocAction.STATUS_Invalid;
@ -2758,7 +2758,7 @@ public class MInOut extends X_M_InOut implements DocAction, IDocsPostProcess
if ((!reversal && totalToMove.signum() <= 0) || (reversal && totalToMove.signum() >= 0))
break;
}
if (!MStorageOnHand.add(getCtx(), getM_Warehouse_ID(), M_Locator_ID, product.getM_Product_ID(), M_AttributeSetInstance_ID, qty,
if (!MStorageOnHand.add(getCtx(), M_Locator_ID, product.getM_Product_ID(), M_AttributeSetInstance_ID, qty,
(dateMaterialPolicy != null ? dateMaterialPolicy : onHandDateMaterialPolicy), trxName)) {
String lastError = CLogger.retrieveErrorString("");
m_processMsg = "Cannot move Inventory OnHand to Shipment ASI [" + product.getValue() + "] - " + lastError;

View File

@ -559,7 +559,7 @@ public class MInventory extends X_M_Inventory implements DocAction
if (log.isLoggable(Level.FINE)) log.fine("Diff=" + qtyDiff
+ " - Instance OnHand=" + QtyMA + "->" + QtyNew);
if (!MStorageOnHand.add(getCtx(), getM_Warehouse_ID(),
if (!MStorageOnHand.add(getCtx(),
line.getM_Locator_ID(),
line.getM_Product_ID(),
ma.getM_AttributeSetInstance_ID(),
@ -617,7 +617,7 @@ public class MInventory extends X_M_Inventory implements DocAction
}
//Fallback: Update Storage - see also VMatch.createMatchRecord
if (!MStorageOnHand.add(getCtx(), getM_Warehouse_ID(),
if (!MStorageOnHand.add(getCtx(),
line.getM_Locator_ID(),
line.getM_Product_ID(),
line.getM_AttributeSetInstance_ID(),

View File

@ -444,9 +444,8 @@ public class MMovement extends X_M_Movement implements DocAction
{
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(),
if (!MStorageOnHand.add(getCtx(),
line.getM_Locator_ID(),
line.getM_Product_ID(),
ma.getM_AttributeSetInstance_ID(),
@ -464,8 +463,7 @@ public class MMovement extends X_M_Movement implements DocAction
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(),
if (!MStorageOnHand.add(getCtx(),
line.getM_LocatorTo_ID(),
line.getM_Product_ID(),
M_AttributeSetInstanceTo_ID,
@ -528,12 +526,11 @@ public class MMovement extends X_M_Movement implements DocAction
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(),
if (!MStorageOnHand.add(getCtx(),
line.getM_Locator_ID(),
line.getM_Product_ID(),
line.getM_AttributeSetInstance_ID(),
@ -548,8 +545,7 @@ public class MMovement extends X_M_Movement implements DocAction
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(),
if (!MStorageOnHand.add(getCtx(),
line.getM_LocatorTo_ID(),
line.getM_Product_ID(),
line.getM_AttributeSetInstanceTo_ID(),

View File

@ -178,8 +178,6 @@ public class MProjectIssue extends X_C_ProjectIssue implements DocAction, DocOpt
getMovementQty().negate(), getMovementDate(), get_TrxName());
mTrx.setC_ProjectIssue_ID(getC_ProjectIssue_ID());
//
MLocator loc = MLocator.get(getCtx(), getM_Locator_ID());
Timestamp dateMPolicy = getMovementDate();
if(getM_AttributeSetInstance_ID()>0){
@ -217,14 +215,14 @@ public class MProjectIssue extends X_C_ProjectIssue implements DocAction, DocOpt
}
if (qtyToIssue.signum() > 0)
{
ok = MStorageOnHand.add(getCtx(), loc.getM_Warehouse_ID(), getM_Locator_ID(),
ok = MStorageOnHand.add(getCtx(), getM_Locator_ID(),
getM_Product_ID(), getM_AttributeSetInstance_ID(),
qtyToIssue.negate(),dateMPolicy, get_TrxName());
}
}
else
{
ok = MStorageOnHand.add(getCtx(), loc.getM_Warehouse_ID(), getM_Locator_ID(),
ok = MStorageOnHand.add(getCtx(), getM_Locator_ID(),
getM_Product_ID(), getM_AttributeSetInstance_ID(),
getMovementQty().negate(),dateMPolicy, get_TrxName());
}

View File

@ -149,7 +149,7 @@ public class MStorageOnHand extends X_M_StorageOnHand
* Get all Storages for Product where QtyOnHand <> 0
* @param ctx context
* @param M_Product_ID product
* @param M_Locator_ID locator
* @param M_Locator_ID locator, 0 to match all locator
* @param trxName transaction
* @return existing or null
*/
@ -163,25 +163,68 @@ public class MStorageOnHand extends X_M_StorageOnHand
* Get all Storages for Product where QtyOnHand <> 0
* @param ctx context
* @param M_Product_ID product
* @param M_Locator_ID locator
* @param M_Locator_ID locator, 0 to match all locator
* @param trxName transaction
* @return existing or null
*/
public static MStorageOnHand[] getAll (Properties ctx,
int M_Product_ID, int M_Locator_ID, String trxName, boolean forUpdate, int timeout)
{
String sqlWhere = "M_Product_ID=? AND M_Locator_ID=? AND QtyOnHand <> 0";
Query query = new Query(ctx, MStorageOnHand.Table_Name, sqlWhere, trxName)
.setParameters(M_Product_ID, M_Locator_ID);
return getAll(ctx, M_Product_ID, M_Locator_ID, false, true, trxName, forUpdate, timeout);
}
/**
* Get all Storages for Product where QtyOnHand <> 0
* @param ctx context
* @param M_Product_ID product
* @param M_Locator_ID locator, 0 to match all locator
* @param locatorPriority If true, sort descending by locator Priority No
* @param fifo Sort ascending(fifo) or descending(lifo) by date material policy, m_attributesetinstance_id
* @param trxName transaction
* @param forUpdate If true, acquire db lock for update
* @param timeout timeout for the acquisition of db update lock
* @return existing or null
*/
public static MStorageOnHand[] getAll (Properties ctx,
int M_Product_ID, int M_Locator_ID, boolean locatorPriority, boolean fifo, String trxName, boolean forUpdate, int timeout)
{
String sqlWhere = "M_Product_ID=? AND QtyOnHand <> 0";
if (M_Locator_ID > 0)
sqlWhere = sqlWhere + " AND M_Locator_ID=? ";
Query query = new Query(ctx, MStorageOnHand.Table_Name, sqlWhere, trxName);
if (M_Locator_ID > 0)
query.setParameters(M_Product_ID, M_Locator_ID);
else
query.setParameters(M_Product_ID);
MProduct product = MProduct.get(ctx, M_Product_ID);
StringBuilder orderBy = new StringBuilder();
if (locatorPriority)
{
query.addJoinClause("JOIN M_Locator locator ON (M_StorageOnHand.M_Locator_ID=locator.M_Locator_ID) ");
orderBy.append("locator.PriorityNo DESC, ");
}
if (product.isUseGuaranteeDateForMPolicy())
{
query.addJoinClause(" LEFT OUTER JOIN M_AttributeSetInstance asi ON (M_StorageOnHand.M_AttributeSetInstance_ID=asi.M_AttributeSetInstance_ID) ")
.setOrderBy("asi."+I_M_AttributeSetInstance.COLUMNNAME_GuaranteeDate);
query.addJoinClause(" LEFT OUTER JOIN M_AttributeSetInstance asi ON (M_StorageOnHand.M_AttributeSetInstance_ID=asi.M_AttributeSetInstance_ID) ");
orderBy.append("asi.").append(I_M_AttributeSetInstance.COLUMNNAME_GuaranteeDate);
if (!fifo)
orderBy.append(" DESC");
orderBy.append(", ");
orderBy.append(MStorageOnHand.Table_Name).append(".").append(MStorageOnHand.COLUMNNAME_M_AttributeSetInstance_ID);
if (!fifo)
orderBy.append(" DESC");
query.setOrderBy(orderBy.toString());
}
else
{
query.setOrderBy(MStorageOnHand.COLUMNNAME_DateMaterialPolicy+","+ MStorageOnHand.COLUMNNAME_M_AttributeSetInstance_ID);
orderBy.append(MStorageOnHand.Table_Name).append(".").append(MStorageOnHand.COLUMNNAME_DateMaterialPolicy);
if (!fifo)
orderBy.append(" DESC");
orderBy.append(", ");
orderBy.append(MStorageOnHand.Table_Name).append(".").append(MStorageOnHand.COLUMNNAME_M_AttributeSetInstance_ID);
if (!fifo)
orderBy.append(" DESC");
query.setOrderBy(orderBy.toString());
}
if (forUpdate)
{
@ -680,7 +723,28 @@ public class MStorageOnHand extends X_M_StorageOnHand
* Update Storage Info add.
* Called from MProjectIssue
* @param ctx context
* @param M_Warehouse_ID warehouse
* @param M_Warehouse_ID warehouse, not use
* @param M_Locator_ID locator
* @param M_Product_ID product
* @param M_AttributeSetInstance_ID AS Instance
* @param reservationAttributeSetInstance_ID reservation AS Instance
* @param diffQtyOnHand add on hand
* @param dateMPolicy
* @param trxName transaction
* @return true if updated
* @deprecated
*/
public static boolean add (Properties ctx, int M_Warehouse_ID, int M_Locator_ID,
int M_Product_ID, int M_AttributeSetInstance_ID,
BigDecimal diffQtyOnHand,Timestamp dateMPolicy, String trxName)
{
return add(ctx, M_Locator_ID, M_Product_ID, M_AttributeSetInstance_ID, diffQtyOnHand, dateMPolicy, trxName);
}
/**
* Update Storage Info add.
* Called from MProjectIssue
* @param ctx context
* @param M_Locator_ID locator
* @param M_Product_ID product
* @param M_AttributeSetInstance_ID AS Instance
@ -690,7 +754,7 @@ public class MStorageOnHand extends X_M_StorageOnHand
* @param trxName transaction
* @return true if updated
*/
public static boolean add (Properties ctx, int M_Warehouse_ID, int M_Locator_ID,
public static boolean add (Properties ctx, int M_Locator_ID,
int M_Product_ID, int M_AttributeSetInstance_ID,
BigDecimal diffQtyOnHand,Timestamp dateMPolicy, String trxName)
{
@ -744,10 +808,10 @@ public class MStorageOnHand extends X_M_StorageOnHand
* Get Location with highest Locator Priority and a sufficient OnHand Qty
* @param M_Warehouse_ID warehouse
* @param M_Product_ID product
* @param M_AttributeSetInstance_ID asi
* @param M_AttributeSetInstance_ID asi id, use negative value (for e.g -1) to match all asi including 0
* @param Qty qty
* @param trxName transaction
* @return id
* @return locator id (0 if no match found)
*/
public static int getM_Locator_ID (int M_Warehouse_ID,
int M_Product_ID, int M_AttributeSetInstance_ID, BigDecimal Qty,
@ -758,12 +822,14 @@ public class MStorageOnHand extends X_M_StorageOnHand
String sql = "SELECT s.M_Locator_ID, s.QtyOnHand "
+ "FROM M_StorageOnHand s"
+ " INNER JOIN M_Locator l ON (s.M_Locator_ID=l.M_Locator_ID)"
+ " INNER JOIN M_Product p ON (s.M_Product_ID=p.M_Product_ID)"
+ " LEFT OUTER JOIN M_AttributeSet mas ON (p.M_AttributeSet_ID=mas.M_AttributeSet_ID) "
+ "WHERE l.M_Warehouse_ID=?"
+ " AND s.M_Product_ID=?"
+ " AND (mas.IsInstanceAttribute IS NULL OR mas.IsInstanceAttribute='N' OR s.M_AttributeSetInstance_ID=?)"
+ " AND l.IsActive='Y' "
+ " INNER JOIN M_Product p ON (s.M_Product_ID=p.M_Product_ID) ";
if (M_AttributeSetInstance_ID >= 0)
sql = sql + " LEFT OUTER JOIN M_AttributeSet mas ON (p.M_AttributeSet_ID=mas.M_AttributeSet_ID) ";
sql = sql + "WHERE l.M_Warehouse_ID=? "
+ " AND s.M_Product_ID=? ";
if (M_AttributeSetInstance_ID >= 0)
sql = sql + " AND (mas.IsInstanceAttribute IS NULL OR mas.IsInstanceAttribute='N' OR s.M_AttributeSetInstance_ID=?) ";
sql = sql + " AND l.IsActive='Y' "
+ "ORDER BY l.PriorityNo DESC, s.QtyOnHand DESC";
PreparedStatement pstmt = null;
@ -773,6 +839,7 @@ public class MStorageOnHand extends X_M_StorageOnHand
pstmt = DB.prepareStatement(sql, trxName);
pstmt.setInt(1, M_Warehouse_ID);
pstmt.setInt(2, M_Product_ID);
if (M_AttributeSetInstance_ID >= 0)
pstmt.setInt(3, M_AttributeSetInstance_ID);
rs = pstmt.executeQuery();
while (rs.next())

View File

@ -881,7 +881,7 @@ public class MDDOrder extends X_DD_Order implements DocAction
if (product.isStocked())
{
// Update Storage
if (!MStorageOnHand.add(getCtx(), locator_to.getM_Warehouse_ID(), locator_to.getM_Locator_ID(),
if (!MStorageOnHand.add(getCtx(), locator_to.getM_Locator_ID(),
line.getM_Product_ID(),
line.getM_AttributeSetInstance_ID(),
Env.ZERO,null, get_TrxName()))
@ -889,7 +889,7 @@ public class MDDOrder extends X_DD_Order implements DocAction
throw new AdempiereException();
}
if (!MStorageOnHand.add(getCtx(), locator_from.getM_Warehouse_ID(), locator_from.getM_Locator_ID(),
if (!MStorageOnHand.add(getCtx(), locator_from.getM_Locator_ID(),
line.getM_Product_ID(),
line.getM_AttributeSetInstanceTo_ID(),
Env.ZERO,null, get_TrxName()))

View File

@ -0,0 +1,196 @@
/***********************************************************************
* This file is part of iDempiere ERP Open Source *
* http://www.idempiere.org *
* *
* Copyright (C) Contributors *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* 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., 51 Franklin Street, Fifth Floor, Boston, *
* MA 02110-1301, USA. *
* *
* Contributors: *
* - hengsin *
**********************************************************************/
package org.idempiere.test.model;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import java.math.BigDecimal;
import java.sql.Timestamp;
import org.compiere.model.MAttributeSet;
import org.compiere.model.MAttributeSetInstance;
import org.compiere.model.MLocator;
import org.compiere.model.MProduct;
import org.compiere.model.MStorageOnHand;
import org.compiere.util.CacheMgt;
import org.compiere.util.DB;
import org.compiere.util.Env;
import org.compiere.util.TimeUtil;
import org.idempiere.test.AbstractTestCase;
import org.junit.jupiter.api.Test;
/**
*
* @author hengsin
*
*/
public class MStorageOnHandTest extends AbstractTestCase {
private final static int FERTILIZER_LOT_ATTRIBUTESET_ID = 101;
private final static int HQ_LOCATOR_ID = 101;
private final static int STORE_LOCATOR_ID = 102;
private static final int TAX_CATEGORY_STANDARD_ID = 107;
private static final int CHEMICALS_CATEGORY_ID = 109;
private static final int UOM_EACH_ID = 100;
public MStorageOnHandTest() {
}
@Test
public void testGetAll() {
//storageonhand api doesn't use trx to retrieve product
MProduct product = new MProduct(Env.getCtx(), 0, null);
product.setName("testGetAll");
product.setM_AttributeSet_ID(FERTILIZER_LOT_ATTRIBUTESET_ID);
product.setIsStocked(true);
product.setProductType(MProduct.PRODUCTTYPE_Item);
product.setC_UOM_ID(UOM_EACH_ID);
product.setM_Product_Category_ID(CHEMICALS_CATEGORY_ID);
product.setC_TaxCategory_ID(TAX_CATEGORY_STANDARD_ID);
product.saveEx();
try {
Timestamp today = TimeUtil.getDay(null);
Timestamp tomorrow = TimeUtil.addDays(today, 1);
MStorageOnHand.add(Env.getCtx(), HQ_LOCATOR_ID, product.get_ID(), 0, new BigDecimal("1"), today, getTrxName());
MStorageOnHand.add(Env.getCtx(), STORE_LOCATOR_ID, product.get_ID(), 0, new BigDecimal("2"), tomorrow, getTrxName());
MStorageOnHand[] onhands = MStorageOnHand.getAll(Env.getCtx(), product.get_ID(), HQ_LOCATOR_ID, getTrxName(), false, 0);
assertNotNull(onhands);
assertEquals(1, onhands.length);
assertEquals(HQ_LOCATOR_ID, onhands[0].getM_Locator_ID());
assertEquals(1, onhands[0].getQtyOnHand().intValue());
onhands = MStorageOnHand.getAll(Env.getCtx(), product.get_ID(), STORE_LOCATOR_ID, getTrxName(), false, 0);
assertNotNull(onhands);
assertEquals(1, onhands.length);
assertEquals(STORE_LOCATOR_ID, onhands[0].getM_Locator_ID());
assertEquals(2, onhands[0].getQtyOnHand().intValue());
onhands = MStorageOnHand.getAll(Env.getCtx(), product.get_ID(), 0, getTrxName(), false, 0);
assertNotNull(onhands);
assertEquals(2, onhands.length);
//test locator priority
MLocator locator = new MLocator(Env.getCtx(), STORE_LOCATOR_ID, getTrxName());
locator.setPriorityNo(Integer.MAX_VALUE);
locator.saveEx();
onhands = MStorageOnHand.getAll(Env.getCtx(), product.get_ID(), 0, true, true, getTrxName(), false, 0);
assertNotNull(onhands);
assertEquals(2, onhands.length);
assertEquals(STORE_LOCATOR_ID, onhands[0].getM_Locator_ID());
assertEquals(2, onhands[0].getQtyOnHand().intValue());
//test fifo
onhands = MStorageOnHand.getAll(Env.getCtx(), product.get_ID(), 0, false, true, getTrxName(), false, 0);
assertNotNull(onhands);
assertEquals(2, onhands.length);
assertEquals(HQ_LOCATOR_ID, onhands[0].getM_Locator_ID());
assertEquals(1, onhands[0].getQtyOnHand().intValue());
//test lifo
onhands = MStorageOnHand.getAll(Env.getCtx(), product.get_ID(), 0, false, false, getTrxName(), false, 0);
assertNotNull(onhands);
assertEquals(2, onhands.length);
assertEquals(STORE_LOCATOR_ID, onhands[0].getM_Locator_ID());
assertEquals(2, onhands[0].getQtyOnHand().intValue());
//test UseGuaranteeDateForMPolicy
onhands = MStorageOnHand.getAll(Env.getCtx(), product.get_ID(), 0, false, true, getTrxName(), false, 0);
assertEquals(HQ_LOCATOR_ID, onhands[0].getM_Locator_ID());
assertEquals(1, onhands[0].getQtyOnHand().intValue());
MAttributeSet as = new MAttributeSet(Env.getCtx(), FERTILIZER_LOT_ATTRIBUTESET_ID, null);
try {
as.setUseGuaranteeDateForMPolicy(true);
as.saveEx();
MAttributeSetInstance asi1 = new MAttributeSetInstance(Env.getCtx(), 0, getTrxName());
asi1.setM_AttributeSet_ID(FERTILIZER_LOT_ATTRIBUTESET_ID);
asi1.setGuaranteeDate(tomorrow);
asi1.saveEx();
DB.executeUpdateEx("UPDATE M_StorageOnHand SET M_AttributeSetInstance_ID=? WHERE M_StorageOnHand_UU=?", new Object[] {asi1.get_ID(), onhands[0].getM_StorageOnHand_UU()}, getTrxName());
MAttributeSetInstance asi2 = new MAttributeSetInstance(Env.getCtx(), 0, getTrxName());
asi2.setM_AttributeSet_ID(FERTILIZER_LOT_ATTRIBUTESET_ID);
asi2.setGuaranteeDate(today);
asi2.saveEx();
DB.executeUpdateEx("UPDATE M_StorageOnHand SET M_AttributeSetInstance_ID=? WHERE M_StorageOnHand_UU=?", new Object[] {asi2.get_ID(), onhands[1].getM_StorageOnHand_UU()}, getTrxName());
CacheMgt.get().reset(MProduct.Table_Name, product.get_ID());
onhands = MStorageOnHand.getAll(Env.getCtx(), product.get_ID(), 0, false, true, getTrxName(), false, 0);
assertEquals(asi2.get_ID(), onhands[0].getM_AttributeSetInstance_ID());
assertEquals(STORE_LOCATOR_ID, onhands[0].getM_Locator_ID());
assertEquals(2, onhands[0].getQtyOnHand().intValue());
} finally {
as.setUseGuaranteeDateForMPolicy(false);
as.saveEx();
}
} finally {
product.deleteEx(true);
}
}
@Test
public void testGetM_Locator_ID() {
MLocator hqLocator = new MLocator(Env.getCtx(), HQ_LOCATOR_ID, getTrxName());
MLocator hqLocator1 = new MLocator(Env.getCtx(), 0, getTrxName());
hqLocator1.setM_Warehouse_ID(hqLocator.getM_Warehouse_ID());
hqLocator1.setValue("HQ Locator 1");
hqLocator1.setPriorityNo(hqLocator.getPriorityNo());
hqLocator1.setX("x");
hqLocator1.setY("y");
hqLocator1.setZ("z");
hqLocator1.saveEx();
MProduct product = new MProduct(Env.getCtx(), 0, getTrxName());
product.setName("testGetM_Locator_ID");
product.setM_AttributeSet_ID(FERTILIZER_LOT_ATTRIBUTESET_ID);
product.setIsStocked(true);
product.setProductType(MProduct.PRODUCTTYPE_Item);
product.setC_UOM_ID(UOM_EACH_ID);
product.setM_Product_Category_ID(CHEMICALS_CATEGORY_ID);
product.setC_TaxCategory_ID(TAX_CATEGORY_STANDARD_ID);
product.saveEx();
Timestamp today = TimeUtil.getDay(null);
MStorageOnHand.add(Env.getCtx(), HQ_LOCATOR_ID, product.get_ID(), 0, new BigDecimal("2"), today, getTrxName());
MAttributeSetInstance asi1 = new MAttributeSetInstance(Env.getCtx(), 0, getTrxName());
asi1.setM_AttributeSet_ID(FERTILIZER_LOT_ATTRIBUTESET_ID);
asi1.setLot("Lot1");
asi1.saveEx();
MStorageOnHand.add(Env.getCtx(), hqLocator1.get_ID(), product.get_ID(), asi1.get_ID(), new BigDecimal("1"), today, getTrxName());
//get asi=0
int M_Locator_ID = MStorageOnHand.getM_Locator_ID(hqLocator.getM_Warehouse_ID(), product.get_ID(), 0, new BigDecimal("1"), getTrxName());
assertEquals(HQ_LOCATOR_ID, M_Locator_ID);
//get asi>0
M_Locator_ID = MStorageOnHand.getM_Locator_ID(hqLocator.getM_Warehouse_ID(), product.get_ID(), asi1.get_ID(), new BigDecimal("1"), getTrxName());
assertEquals(hqLocator1.get_ID(), M_Locator_ID);
//check all asi and get locator with highest onhand
M_Locator_ID = MStorageOnHand.getM_Locator_ID(hqLocator.getM_Warehouse_ID(), product.get_ID(), -1, new BigDecimal("1"), getTrxName());
assertEquals(HQ_LOCATOR_ID, M_Locator_ID);
MStorageOnHand.add(Env.getCtx(), hqLocator1.get_ID(), product.get_ID(), asi1.get_ID(), new BigDecimal("2"), today, getTrxName());
M_Locator_ID = MStorageOnHand.getM_Locator_ID(hqLocator.getM_Warehouse_ID(), product.get_ID(), -1, new BigDecimal("1"), getTrxName());
assertEquals(hqLocator1.get_ID(), M_Locator_ID);
}
}

View File

@ -698,8 +698,8 @@ public class SalesOrderTest extends AbstractTestCase {
asi.setLot("1010");
asi.saveEx();
MStorageOnHand.add(ctx, WAREHOUSE_FERTILIZER, LOCATOR_FERTILIZER, PRODUCT_FERT50, asi.getM_AttributeSetInstance_ID(), Env.ONE, past_month, trxName);
MStorageOnHand.add(ctx, WAREHOUSE_FERTILIZER, LOCATOR_FERTILIZER, PRODUCT_FERT50, asi.getM_AttributeSetInstance_ID(), Env.ONE, today, trxName);
MStorageOnHand.add(ctx, LOCATOR_FERTILIZER, PRODUCT_FERT50, asi.getM_AttributeSetInstance_ID(), Env.ONE, past_month, trxName);
MStorageOnHand.add(ctx, LOCATOR_FERTILIZER, PRODUCT_FERT50, asi.getM_AttributeSetInstance_ID(), Env.ONE, today, trxName);
// Expected to create two entries in storage because of the different dates
MStorageOnHand[] storages = MStorageOnHand.getWarehouse(ctx, WAREHOUSE_FERTILIZER,