IDEMPIERE-2172 Attribute set with mandatory type = When Shipping not … (#1040)

* IDEMPIERE-2172 Attribute set with mandatory type = When Shipping not working

Fix reversal and add more unit test

* IDEMPIERE-2172 Attribute set with mandatory type = When Shipping not working

Use constant for movement type checking
This commit is contained in:
hengsin 2021-12-08 23:18:44 +08:00 committed by GitHub
parent 5c675536cd
commit 3530351601
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 270 additions and 78 deletions

View File

@ -1421,7 +1421,7 @@ public class MInOut extends X_M_InOut implements DocAction, IDocsPostProcess
if (MovementType.charAt(1) == '-') // C- Customer Shipment - V- Vendor Return
QtyMA = QtyMA.negate();
if (product != null && QtyMA.signum() < 0 && MovementType.equals("C-") && ma.getM_AttributeSetInstance_ID() > 0
if (product != null && QtyMA.signum() < 0 && MovementType.equals(MOVEMENTTYPE_CustomerShipment) && ma.getM_AttributeSetInstance_ID() > 0
&& oLine != null && oLine.getM_AttributeSetInstance_ID()==0 && !ma.isAutoGenerated() && !isReversal())
{
String status = moveOnHandToShipmentASI(product, sLine.getM_Locator_ID(), ma.getM_AttributeSetInstance_ID(), QtyMA.negate(), ma.getDateMaterialPolicy(),
@ -1455,7 +1455,7 @@ public class MInOut extends X_M_InOut implements DocAction, IDocsPostProcess
return DocAction.STATUS_Invalid;
}
if (product != null && QtyMA.signum() > 0 && MovementType.equals("C-") && ma.getM_AttributeSetInstance_ID() > 0
if (product != null && QtyMA.signum() > 0 && MovementType.equals(MOVEMENTTYPE_CustomerShipment) && ma.getM_AttributeSetInstance_ID() > 0
&& oLine != null && oLine.getM_AttributeSetInstance_ID()==0 && !ma.isAutoGenerated() && isReversal())
{
String status = moveOnHandToShipmentASI(product, sLine.getM_Locator_ID(), ma.getM_AttributeSetInstance_ID(), QtyMA.negate(), ma.getDateMaterialPolicy(),
@ -1496,7 +1496,7 @@ public class MInOut extends X_M_InOut implements DocAction, IDocsPostProcess
if (mtrx == null)
{
if (product != null && MovementType.equals("C-") && sLine.getM_AttributeSetInstance_ID() > 0 && Qty.signum() < 0
if (product != null && MovementType.equals(MOVEMENTTYPE_CustomerShipment) && sLine.getM_AttributeSetInstance_ID() > 0 && Qty.signum() < 0
&& oLine != null && oLine.getM_AttributeSetInstance_ID()==0 && !isReversal())
{
String status = moveOnHandToShipmentASI(product, sLine.getM_Locator_ID(), sLine.getM_AttributeSetInstance_ID(), Qty.negate(), null, sLine.get_ID(), false, get_TrxName());
@ -1596,10 +1596,10 @@ public class MInOut extends X_M_InOut implements DocAction, IDocsPostProcess
return DocAction.STATUS_Invalid;
}
if (product != null && MovementType.equals("C-") && sLine.getM_AttributeSetInstance_ID() > 0 && Qty.signum() > 0
if (product != null && MovementType.equals(MOVEMENTTYPE_CustomerShipment) && sLine.getM_AttributeSetInstance_ID() > 0 && Qty.signum() > 0
&& oLine != null && oLine.getM_AttributeSetInstance_ID()==0 && isReversal())
{
String status = moveOnHandToShipmentASI(product, sLine.getM_Locator_ID(), sLine.getM_AttributeSetInstance_ID(), Qty.negate(), null, sLine.get_ID(), true, get_TrxName());
String status = moveOnHandToShipmentASI(product, sLine.getM_Locator_ID(), sLine.getM_AttributeSetInstance_ID(), Qty.negate(), getMovementDate(), sLine.get_ID(), true, get_TrxName());
if (status != null)
return status;
}
@ -2392,7 +2392,7 @@ public class MInOut extends X_M_InOut implements DocAction, IDocsPostProcess
{
MInOutLineMA ma = new MInOutLineMA (rLine,
mas[j].getM_AttributeSetInstance_ID(),
mas[j].getMovementQty().negate(),mas[j].getDateMaterialPolicy(),true);
mas[j].getMovementQty().negate(),mas[j].getDateMaterialPolicy(),mas[j].isAutoGenerated());
ma.saveEx();
}
}
@ -2625,7 +2625,7 @@ public class MInOut extends X_M_InOut implements DocAction, IDocsPostProcess
/**
* For product with mix of No ASI and ASI inventory, this move Non ASI on hand to the new ASI created at shipment line or shipment line ma
* @param product
* @param M_Locator_ID
* @param M_Locator_ID shipment line locator id
* @param M_AttributeSetInstance_ID
* @param qty
* @param dateMaterialPolicy
@ -2642,14 +2642,13 @@ public class MInOut extends X_M_InOut implements DocAction, IDocsPostProcess
return null;
if (dateMaterialPolicy != null) {
MStorageOnHand asi = MStorageOnHand.get(getCtx(), M_Locator_ID, product.getM_Product_ID(), M_AttributeSetInstance_ID, dateMaterialPolicy, trxName);
if (asi != null && asi.getQtyOnHand().signum() != 0)
if (asi != null && asi.getQtyOnHand().signum() != 0 && !reversal)
return null;
MStorageOnHand noasi = MStorageOnHand.get(getCtx(), M_Locator_ID, product.getM_Product_ID(), 0, dateMaterialPolicy, trxName);
if (noasi != null && noasi.getM_AttributeSetInstance_ID()==0 && (noasi.getQtyOnHand().compareTo(qty) >= 0 || reversal)) {
if (!(MStorageOnHand.add(getCtx(), getM_Warehouse_ID(), M_Locator_ID, product.getM_Product_ID(), 0, qty.negate(), dateMaterialPolicy, trxName))) {
if (reversal) {
if (!MStorageOnHand.add(getCtx(), getM_Warehouse_ID(), M_Locator_ID, product.getM_Product_ID(), 0, qty.negate(), dateMaterialPolicy, trxName)) {
String lastError = CLogger.retrieveErrorString("");
m_processMsg = "Cannot move Inventory OnHand (MA) to Shipment ASI [" + product.getValue() + "] - " + lastError;
m_processMsg = "Cannot move Inventory OnHand to Non ASI [" + product.getValue() + "] - " + lastError;
return DocAction.STATUS_Invalid;
}
MTransaction trxFrom = new MTransaction (Env.getCtx(), getAD_Org_ID(), getMovementType(), M_Locator_ID, product.getM_Product_ID(), 0,
@ -2659,70 +2658,6 @@ 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))) {
String lastError = CLogger.retrieveErrorString("");
m_processMsg = "Cannot move Inventory OnHand (MA) to Shipment ASI [" + product.getValue() + "] - " + lastError;
return DocAction.STATUS_Invalid;
}
MTransaction trxTo = new MTransaction (Env.getCtx(), getAD_Org_ID(), getMovementType(), M_Locator_ID, product.getM_Product_ID(), M_AttributeSetInstance_ID,
qty, getMovementDate(), trxName);
trxTo.setM_InOutLine_ID(M_InOutLine_ID);
if (!trxTo.save()) {
m_processMsg = "Transaction To not inserted (MA) [" + product.getValue() + "] - ";
return DocAction.STATUS_Invalid;
}
}
} else {
BigDecimal totalASI = BigDecimal.ZERO;
BigDecimal totalOnHand = BigDecimal.ZERO;
MStorageOnHand[] storages = MStorageOnHand.getWarehouse(getCtx(), 0,
product.getM_Product_ID(), M_AttributeSetInstance_ID, null,
MClient.MMPOLICY_FiFo.equals(product.getMMPolicy()), false,
M_Locator_ID, get_TrxName());
for (MStorageOnHand onhand : storages) {
totalASI = totalASI.add(onhand.getQtyOnHand());
}
if (!reversal && totalASI.signum() != 0)
return null;
else if (reversal && (totalASI.compareTo(qty) < 0))
return null;
storages = MStorageOnHand.getWarehouse(getCtx(), 0,
product.getM_Product_ID(), 0, null,
MClient.MMPOLICY_FiFo.equals(product.getMMPolicy()), true,
M_Locator_ID, get_TrxName());
List<MStorageOnHand> nonASIList = new ArrayList<>();
for (MStorageOnHand storage : storages) {
if (storage.getM_AttributeSetInstance_ID() == 0) {
totalOnHand = totalOnHand.add(storage.getQtyOnHand());
nonASIList.add(storage);
}
}
if (totalOnHand.compareTo(qty) >= 0 || reversal) {
BigDecimal totalToMove = qty;
for (MStorageOnHand onhand : nonASIList) {
BigDecimal toMove = totalToMove;
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)) {
String lastError = CLogger.retrieveErrorString("");
m_processMsg = "Cannot move Inventory OnHand to Shipment ASI [" + product.getValue() + "] - " + lastError;
return DocAction.STATUS_Invalid;
}
MTransaction trxFrom = new MTransaction (Env.getCtx(), getAD_Org_ID(), getMovementType(), M_Locator_ID, product.getM_Product_ID(), 0,
toMove.negate(), getMovementDate(), trxName);
trxFrom.setM_InOutLine_ID(M_InOutLine_ID);
if (!trxFrom.save()) {
m_processMsg = "Transaction From not inserted (MA) [" + product.getValue() + "] - ";
return DocAction.STATUS_Invalid;
}
dateMaterialPolicy = onhand.getDateMaterialPolicy();
totalToMove = totalToMove.subtract(toMove);
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, dateMaterialPolicy, trxName)) {
String lastError = CLogger.retrieveErrorString("");
m_processMsg = "Cannot move Inventory OnHand to Shipment ASI [" + product.getValue() + "] - " + lastError;
@ -2735,9 +2670,83 @@ public class MInOut extends X_M_InOut implements DocAction, IDocsPostProcess
m_processMsg = "Transaction To not inserted (MA) [" + product.getValue() + "] - ";
return DocAction.STATUS_Invalid;
}
} else {
return doMove(product, M_Locator_ID, M_AttributeSetInstance_ID, dateMaterialPolicy, qty, M_InOutLine_ID, reversal, trxName);
}
} else {
BigDecimal totalASI = BigDecimal.ZERO;
MStorageOnHand[] storages = MStorageOnHand.getWarehouse(getCtx(), 0,
product.getM_Product_ID(), M_AttributeSetInstance_ID, null,
MClient.MMPOLICY_FiFo.equals(product.getMMPolicy()), false,
M_Locator_ID, get_TrxName());
for (MStorageOnHand onhand : storages) {
totalASI = totalASI.add(onhand.getQtyOnHand());
}
if (!reversal && totalASI.signum() != 0)
return null;
else if (reversal && (totalASI.compareTo(qty) < 0))
return null;
return doMove(product, M_Locator_ID, M_AttributeSetInstance_ID, dateMaterialPolicy, qty, M_InOutLine_ID, reversal, trxName);
}
return null;
}
private String doMove(MProduct product, int M_Locator_ID, int M_AttributeSetInstance_ID, Timestamp dateMaterialPolicy, BigDecimal qty,
int M_InOutLine_ID, boolean reversal, String trxName) {
MStorageOnHand[] storages;
BigDecimal totalOnHand = BigDecimal.ZERO;
Timestamp onHandDateMaterialPolicy = null;
storages = MStorageOnHand.getWarehouse(getCtx(), 0,
product.getM_Product_ID(), 0, null,
MClient.MMPOLICY_FiFo.equals(product.getMMPolicy()), true,
M_Locator_ID, get_TrxName());
List<MStorageOnHand> nonASIList = new ArrayList<>();
for (MStorageOnHand storage : storages) {
if (storage.getM_AttributeSetInstance_ID() == 0) {
totalOnHand = totalOnHand.add(storage.getQtyOnHand());
nonASIList.add(storage);
}
}
if (totalOnHand.compareTo(qty) >= 0 || reversal) {
BigDecimal totalToMove = qty;
for (MStorageOnHand onhand : nonASIList) {
BigDecimal toMove = totalToMove;
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)) {
String lastError = CLogger.retrieveErrorString("");
m_processMsg = "Cannot move Inventory OnHand to Non ASI [" + product.getValue() + "] - " + lastError;
return DocAction.STATUS_Invalid;
}
MTransaction trxFrom = new MTransaction (Env.getCtx(), getAD_Org_ID(), getMovementType(), M_Locator_ID, product.getM_Product_ID(), 0,
toMove.negate(), getMovementDate(), trxName);
trxFrom.setM_InOutLine_ID(M_InOutLine_ID);
if (!trxFrom.save()) {
m_processMsg = "Transaction From not inserted (MA) [" + product.getValue() + "] - ";
return DocAction.STATUS_Invalid;
}
onHandDateMaterialPolicy = onhand.getDateMaterialPolicy();
totalToMove = totalToMove.subtract(toMove);
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,
(dateMaterialPolicy != null ? dateMaterialPolicy : onHandDateMaterialPolicy), trxName)) {
String lastError = CLogger.retrieveErrorString("");
m_processMsg = "Cannot move Inventory OnHand to Shipment ASI [" + product.getValue() + "] - " + lastError;
return DocAction.STATUS_Invalid;
}
MTransaction trxTo = new MTransaction (Env.getCtx(), getAD_Org_ID(), getMovementType(), M_Locator_ID, product.getM_Product_ID(), M_AttributeSetInstance_ID,
qty, getMovementDate(), trxName);
trxTo.setM_InOutLine_ID(M_InOutLine_ID);
if (!trxTo.save()) {
m_processMsg = "Transaction To not inserted (MA) [" + product.getValue() + "] - ";
return DocAction.STATUS_Invalid;
}
}
return null;
}
} // MInOut

View File

@ -25,7 +25,6 @@
package org.idempiere.test.model;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.compiere.model.MPayment;

View File

@ -41,6 +41,7 @@ import org.compiere.model.MBPartner;
import org.compiere.model.MClient;
import org.compiere.model.MInOut;
import org.compiere.model.MInOutLine;
import org.compiere.model.MInOutLineMA;
import org.compiere.model.MInvoice;
import org.compiere.model.MOrder;
import org.compiere.model.MOrderLine;
@ -1090,6 +1091,8 @@ public class SalesOrderTest extends AbstractTestCase {
assertEquals(-1, asiTrxs.get(1).getMovementQty().intValue(), "Unexpected movement qty for second ASI MTransaction record");
//reverse the MR
Timestamp tomorrow = TimeUtil.addDays(today, 1);
Env.setContext(Env.getCtx(), Env.DATE, tomorrow);
shipment.load(getTrxName());
info = MWorkflow.runDocumentActionWorkflow(shipment, DocAction.ACTION_Reverse_Accrual);
assertFalse(info.isError(), info.getSummary());
@ -1099,6 +1102,14 @@ public class SalesOrderTest extends AbstractTestCase {
assertEquals(originalOnHand, newOnHand, "Unexpected on hand quantity no ASI");
asiOnHand = MStorageOnHand.getQtyOnHand(PRODUCT_PCHAIR, getM_Warehouse_ID(), asi.get_ID(), getTrxName()).intValue();
assertEquals(0, asiOnHand, "Unexpected on hand quantity for Serial ASI");
storages = MStorageOnHand.getOfProduct(Env.getCtx(), PRODUCT_PCHAIR, getTrxName());
for (MStorageOnHand storage : storages) {
if (storage.getM_Warehouse_ID() == getM_Warehouse_ID()) {
if (storage.getM_AttributeSetInstance_ID() == asi.get_ID()) {
assertEquals(0, storage.getQtyOnHand().intValue(), "Unexpected qty on hand for asi: " + storage.toString());
}
}
}
MInOut reversal = new MInOut(Env.getCtx(), shipment.getReversal_ID(), getTrxName());
MInOutLine[] reversalLines = reversal.getLines();
@ -1107,7 +1118,7 @@ public class SalesOrderTest extends AbstractTestCase {
.setOrderBy("M_Transaction_ID")
.list();
assertEquals(1, noASITrxs.size(), "Unexpected number of records for reversal no ASI MTransaction");
assertEquals(1, asiTrxs.get(0).getMovementQty().intValue(), "Unexpected reversal movement qty for no ASI MTransaction record");
assertEquals(1, noASITrxs.get(0).getMovementQty().intValue(), "Unexpected reversal movement qty for no ASI MTransaction record");
query = new Query(Env.getCtx(), MTransaction.Table_Name, "M_InOutLine_ID=? AND M_Product_ID=? AND M_AttributeSetInstance_ID=?", getTrxName());
asiTrxs = query.setParameters(reversalLines[0].get_ID(), reversalLines[0].getM_Product_ID(), reversalLines[0].getM_AttributeSetInstance_ID())
@ -1117,4 +1128,177 @@ public class SalesOrderTest extends AbstractTestCase {
assertEquals(1, asiTrxs.get(0).getMovementQty().intValue(), "Unexpected reversal movement qty for first ASI MTransaction record");
assertEquals(-1, asiTrxs.get(1).getMovementQty().intValue(), "Unexpected reversal movement qty for second ASI MTransaction record");
}
@Test
public void testSetASIWhenShipping2() {
MOrder order = new MOrder(Env.getCtx(), 0, getTrxName());
order.setBPartner(MBPartner.get(Env.getCtx(), BP_JOE_BLOCK));
order.setC_DocTypeTarget_ID(MOrder.DocSubTypeSO_Standard);
order.setDeliveryRule(MOrder.DELIVERYRULE_CompleteOrder);
order.setDocStatus(DocAction.STATUS_Drafted);
order.setDocAction(DocAction.ACTION_Complete);
Timestamp today = TimeUtil.getDay(System.currentTimeMillis());
order.setDateOrdered(today);
order.setDatePromised(today);
order.saveEx();
MOrderLine line1 = new MOrderLine(order);
line1.setLine(10);
line1.setProduct(MProduct.get(Env.getCtx(), PRODUCT_PCHAIR));
line1.setQty(new BigDecimal("2"));
line1.setDatePromised(today);
line1.saveEx();
ProcessInfo info = MWorkflow.runDocumentActionWorkflow(order, DocAction.ACTION_Complete);
assertFalse(info.isError(), info.getSummary());
order.load(getTrxName());
assertEquals(DocAction.STATUS_Completed, order.getDocStatus(), "Unexpected Order document status");
line1.load(getTrxName());
assertEquals(2, line1.getQtyReserved().intValue(), "Unexpected order line qty reserved value");
int originalOnHand = MStorageOnHand.getQtyOnHandWithASIZero(PRODUCT_PCHAIR, getM_Warehouse_ID(), getTrxName()).intValue();
MInOut shipment = new MInOut(order, 120, order.getDateOrdered());
shipment.setDocStatus(DocAction.STATUS_Drafted);
shipment.setDocAction(DocAction.ACTION_Complete);
shipment.saveEx();
MInOutLine shipmentLine = new MInOutLine(shipment);
shipmentLine.setOrderLine(line1, 0, new BigDecimal("2"));
shipmentLine.setQty(new BigDecimal("2"));
shipmentLine.saveEx();
MAttributeSetInstance asi1 = new MAttributeSetInstance(Env.getCtx(), 0, getTrxName());
asi1.setM_AttributeSet_ID(MProduct.get(PRODUCT_PCHAIR).getM_AttributeSet_ID());
asi1.setSerNo("PChair Serial #1000000");
asi1.saveEx();
MAttributeSetInstance asi2 = new MAttributeSetInstance(Env.getCtx(), 0, getTrxName());
asi2.setM_AttributeSet_ID(MProduct.get(PRODUCT_PCHAIR).getM_AttributeSet_ID());
asi2.setSerNo("PChair Serial #1000000");
asi2.saveEx();
MInOutLineMA ma1 = new MInOutLineMA(Env.getCtx(), 0, getTrxName());
ma1.setM_AttributeSetInstance_ID(asi1.get_ID());
ma1.setM_InOutLine_ID(shipmentLine.get_ID());
ma1.setDateMaterialPolicy(shipment.getMovementDate());
ma1.setMovementQty(new BigDecimal("1"));
ma1.setIsAutoGenerated(false);
ma1.saveEx();
MInOutLineMA ma2 = new MInOutLineMA(Env.getCtx(), 0, getTrxName());
ma2.setM_AttributeSetInstance_ID(asi2.get_ID());
ma2.setM_InOutLine_ID(shipmentLine.get_ID());
ma2.setDateMaterialPolicy(shipment.getMovementDate());
ma2.setMovementQty(new BigDecimal("1"));
ma2.setIsAutoGenerated(false);
ma2.saveEx();
info = MWorkflow.runDocumentActionWorkflow(shipment, DocAction.ACTION_Complete);
assertFalse(info.isError(), info.getSummary());
shipment.load(getTrxName());
assertEquals(DocAction.STATUS_Completed, shipment.getDocStatus(), "Unexpected Shipment document status");
int newOnHand = MStorageOnHand.getQtyOnHandWithASIZero(PRODUCT_PCHAIR, getM_Warehouse_ID(), getTrxName()).intValue();
assertEquals(originalOnHand-2, newOnHand, "Unexpected on hand quantity");
int asiOnHand = MStorageOnHand.getQtyOnHand(PRODUCT_PCHAIR, getM_Warehouse_ID(), asi1.get_ID(), getTrxName()).intValue();
int asiRecords = 0;
MStorageOnHand[] storages = MStorageOnHand.getOfProduct(Env.getCtx(), PRODUCT_PCHAIR, getTrxName());
for (MStorageOnHand storage : storages) {
if (storage.getM_Warehouse_ID()==getM_Warehouse_ID() && storage.getM_AttributeSetInstance_ID()==asi1.get_ID()) {
asiRecords++;
}
}
assertEquals(0, asiOnHand, "Unexpected on hand quantity for Serial ASI 1");
assertEquals(1, asiRecords, "Unexpected number of Serial ASI 1 Storage records");
asiOnHand = MStorageOnHand.getQtyOnHand(PRODUCT_PCHAIR, getM_Warehouse_ID(), asi2.get_ID(), getTrxName()).intValue();
asiRecords = 0;
storages = MStorageOnHand.getOfProduct(Env.getCtx(), PRODUCT_PCHAIR, getTrxName());
for (MStorageOnHand storage : storages) {
if (storage.getM_Warehouse_ID()==getM_Warehouse_ID() && storage.getM_AttributeSetInstance_ID()==asi2.get_ID()) {
asiRecords++;
}
}
assertEquals(0, asiOnHand, "Unexpected on hand quantity for Serial ASI 2");
assertEquals(1, asiRecords, "Unexpected number of Serial ASI 2 Storage records");
Query query = new Query(Env.getCtx(), MTransaction.Table_Name, "M_InOutLine_ID=? AND M_Product_ID=? AND M_AttributeSetInstance_ID=0", getTrxName());
MTransaction trxFrom = query.setParameters(shipmentLine.get_ID(), shipmentLine.getM_Product_ID()).first();
assertNotNull(trxFrom, "Can't find MTransaction record for no ASI MTransaction record");
assertEquals(-1, trxFrom.getMovementQty().intValue(), "Unexpected movement qty for no ASI MTransaction record");
query = new Query(Env.getCtx(), MTransaction.Table_Name, "M_InOutLine_ID=? AND M_Product_ID=? AND M_AttributeSetInstance_ID=?", getTrxName());
List<MTransaction> asiTrxs = query.setParameters(shipmentLine.get_ID(), shipmentLine.getM_Product_ID(), ma1.getM_AttributeSetInstance_ID())
.setOrderBy("M_Transaction_ID")
.list();
assertEquals(2, asiTrxs.size(), "Unexpected number of records for ASI MTransaction");
assertEquals(1, asiTrxs.get(0).getMovementQty().intValue(), "Unexpected movement qty for first ASI 1 MTransaction record");
assertEquals(-1, asiTrxs.get(1).getMovementQty().intValue(), "Unexpected movement qty for second ASI 1 MTransaction record");
query = new Query(Env.getCtx(), MTransaction.Table_Name, "M_InOutLine_ID=? AND M_Product_ID=? AND M_AttributeSetInstance_ID=?", getTrxName());
asiTrxs = query.setParameters(shipmentLine.get_ID(), shipmentLine.getM_Product_ID(), ma2.getM_AttributeSetInstance_ID())
.setOrderBy("M_Transaction_ID")
.list();
assertEquals(2, asiTrxs.size(), "Unexpected number of records for ASI MTransaction");
assertEquals(1, asiTrxs.get(0).getMovementQty().intValue(), "Unexpected movement qty for first ASI 2 MTransaction record");
assertEquals(-1, asiTrxs.get(1).getMovementQty().intValue(), "Unexpected movement qty for second ASI 2 MTransaction record");
//reverse the MR
Timestamp tomorrow = TimeUtil.addDays(today, 1);
Env.setContext(Env.getCtx(), Env.DATE, tomorrow);
shipment.load(getTrxName());
info = MWorkflow.runDocumentActionWorkflow(shipment, DocAction.ACTION_Reverse_Accrual);
assertFalse(info.isError(), info.getSummary());
shipment.load(getTrxName());
assertEquals(DocAction.STATUS_Reversed, shipment.getDocStatus(), "Unexpected Shipment document status");
newOnHand = MStorageOnHand.getQtyOnHandWithASIZero(PRODUCT_PCHAIR, getM_Warehouse_ID(), getTrxName()).intValue();
assertEquals(originalOnHand, newOnHand, "Unexpected on hand quantity no ASI");
asiOnHand = MStorageOnHand.getQtyOnHand(PRODUCT_PCHAIR, getM_Warehouse_ID(), asi1.get_ID(), getTrxName()).intValue();
assertEquals(0, asiOnHand, "Unexpected on hand quantity for Serial ASI 1");
storages = MStorageOnHand.getOfProduct(Env.getCtx(), PRODUCT_PCHAIR, getTrxName());
for (MStorageOnHand storage : storages) {
if (storage.getM_Warehouse_ID() == getM_Warehouse_ID()) {
if (storage.getM_AttributeSetInstance_ID() == asi1.get_ID()) {
assertEquals(0, storage.getQtyOnHand().intValue(), "Unexpected qty on hand for asi 1: " + storage.toString());
}
}
}
asiOnHand = MStorageOnHand.getQtyOnHand(PRODUCT_PCHAIR, getM_Warehouse_ID(), asi2.get_ID(), getTrxName()).intValue();
assertEquals(0, asiOnHand, "Unexpected on hand quantity for Serial ASI 2");
storages = MStorageOnHand.getOfProduct(Env.getCtx(), PRODUCT_PCHAIR, getTrxName());
for (MStorageOnHand storage : storages) {
if (storage.getM_Warehouse_ID() == getM_Warehouse_ID()) {
if (storage.getM_AttributeSetInstance_ID() == asi2.get_ID()) {
assertEquals(0, storage.getQtyOnHand().intValue(), "Unexpected qty on hand for asi 2: " + storage.toString());
}
}
}
MInOut reversal = new MInOut(Env.getCtx(), shipment.getReversal_ID(), getTrxName());
MInOutLine[] reversalLines = reversal.getLines();
query = new Query(Env.getCtx(), MTransaction.Table_Name, "M_InOutLine_ID=? AND M_Product_ID=? AND M_AttributeSetInstance_ID=0", getTrxName());
List<MTransaction> noASITrxs = query.setParameters(reversalLines[0].get_ID(), reversalLines[0].getM_Product_ID())
.setOrderBy("M_Transaction_ID")
.list();
assertEquals(2, noASITrxs.size(), "Unexpected number of records for reversal no ASI MTransaction");
assertEquals(1, noASITrxs.get(0).getMovementQty().intValue(), "Unexpected reversal movement qty for no ASI MTransaction record");
assertEquals(1, noASITrxs.get(1).getMovementQty().intValue(), "Unexpected reversal movement qty for no ASI MTransaction record");
query = new Query(Env.getCtx(), MTransaction.Table_Name, "M_InOutLine_ID=? AND M_Product_ID=? AND M_AttributeSetInstance_ID=?", getTrxName());
asiTrxs = query.setParameters(reversalLines[0].get_ID(), reversalLines[0].getM_Product_ID(), asi1.getM_AttributeSetInstance_ID())
.setOrderBy("M_Transaction_ID")
.list();
assertEquals(2, asiTrxs.size(), "Unexpected number of records for reversal ASI MTransaction");
assertEquals(1, asiTrxs.get(0).getMovementQty().intValue(), "Unexpected reversal movement qty for first ASI 1 MTransaction record");
assertEquals(-1, asiTrxs.get(1).getMovementQty().intValue(), "Unexpected reversal movement qty for second ASI 1 MTransaction record");
query = new Query(Env.getCtx(), MTransaction.Table_Name, "M_InOutLine_ID=? AND M_Product_ID=? AND M_AttributeSetInstance_ID=?", getTrxName());
asiTrxs = query.setParameters(reversalLines[0].get_ID(), reversalLines[0].getM_Product_ID(), asi2.getM_AttributeSetInstance_ID())
.setOrderBy("M_Transaction_ID")
.list();
assertEquals(2, asiTrxs.size(), "Unexpected number of records for reversal ASI MTransaction");
assertEquals(1, asiTrxs.get(0).getMovementQty().intValue(), "Unexpected reversal movement qty for first ASI 2 MTransaction record");
assertEquals(-1, asiTrxs.get(1).getMovementQty().intValue(), "Unexpected reversal movement qty for second ASI 2 MTransaction record");
}
}