diff --git a/org.idempiere.test/src/org/idempiere/test/base/MatchInvTest.java b/org.idempiere.test/src/org/idempiere/test/base/MatchInvTest.java index 9ff0486e89..33f7d8bd44 100644 --- a/org.idempiere.test/src/org/idempiere/test/base/MatchInvTest.java +++ b/org.idempiere.test/src/org/idempiere/test/base/MatchInvTest.java @@ -26,24 +26,29 @@ package org.idempiere.test.base; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; import java.math.BigDecimal; import java.math.RoundingMode; import java.sql.Timestamp; +import java.util.List; import org.compiere.acct.Doc; import org.compiere.acct.DocManager; import org.compiere.model.MAccount; import org.compiere.model.MAcctSchema; import org.compiere.model.MBPartner; -import org.compiere.model.MClientInfo; +import org.compiere.model.MClient; import org.compiere.model.MConversionRate; +import org.compiere.model.MCost; import org.compiere.model.MCurrency; import org.compiere.model.MDocType; import org.compiere.model.MFactAcct; import org.compiere.model.MInOut; import org.compiere.model.MInOutLine; +import org.compiere.model.MInventory; +import org.compiere.model.MInventoryLine; import org.compiere.model.MInvoice; import org.compiere.model.MInvoiceLine; import org.compiere.model.MMatchInv; @@ -52,6 +57,8 @@ import org.compiere.model.MOrderLine; import org.compiere.model.MPriceList; import org.compiere.model.MPriceListVersion; import org.compiere.model.MProduct; +import org.compiere.model.MProductCategory; +import org.compiere.model.MProductCategoryAcct; import org.compiere.model.MProductPrice; import org.compiere.model.MRMA; import org.compiere.model.MRMALine; @@ -203,8 +210,8 @@ public class MatchInvTest extends AbstractTestCase { creditMemo.load(getTrxName()); assertTrue(creditMemo.isPosted()); - int C_AcctSchema_ID = MClientInfo.get(Env.getCtx()).getC_AcctSchema1_ID(); - MAcctSchema as = MAcctSchema.get(Env.getCtx(), C_AcctSchema_ID); + MAcctSchema as = MClient.get(getAD_Client_ID()).getAcctSchema(); + BigDecimal credMatchAmt = creditMemoLine.getMatchedQty().negate().multiply(creditMemoLine.getPriceActual()).setScale(as.getStdPrecision(), RoundingMode.HALF_UP); MMatchInv[] miList = MMatchInv.getInvoiceLine(Env.getCtx(), creditMemoLine.get_ID(), getTrxName()); for (MMatchInv mi : miList) { if (!mi.isPosted()) { @@ -223,14 +230,14 @@ public class MatchInvTest extends AbstractTestCase { String whereClause = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MMatchInv.Table_ID + " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + mi.get_ID() - + " AND " + MFactAcct.COLUMNNAME_C_AcctSchema_ID + "=" + C_AcctSchema_ID; + + " AND " + MFactAcct.COLUMNNAME_C_AcctSchema_ID + "=" + as.getC_AcctSchema_ID(); int[] ids = MFactAcct.getAllIDs(MFactAcct.Table_Name, whereClause, getTrxName()); for (int id : ids) { MFactAcct fa = new MFactAcct(Env.getCtx(), id, getTrxName()); if (fa.getAccount_ID() == acctNIR.getAccount_ID()) - assertTrue(fa.getAmtAcctCr().compareTo(Env.ZERO) >= 0); + assertEquals(fa.getAmtAcctCr(), credMatchAmt, "MatchInv incorrect amount posted "+fa.getAmtAcctCr().toPlainString()); else if (fa.getAccount_ID() == acctInvClr.getAccount_ID()) - assertTrue(fa.getAmtAcctDr().compareTo(Env.ZERO) >= 0); + assertEquals(fa.getAmtAcctDr(), credMatchAmt, "MatchInv incorrect amount posted "+fa.getAmtAcctDr().toPlainString()); } } @@ -314,8 +321,8 @@ public class MatchInvTest extends AbstractTestCase { invoice.load(getTrxName()); assertTrue(invoice.isPosted()); - int C_AcctSchema_ID = MClientInfo.get(Env.getCtx()).getC_AcctSchema1_ID(); - MAcctSchema as = MAcctSchema.get(Env.getCtx(), C_AcctSchema_ID); + MAcctSchema as = MClient.get(getAD_Client_ID()).getAcctSchema(); + BigDecimal invMatchAmt = invoiceLine.getMatchedQty().multiply(invoiceLine.getPriceActual()).setScale(as.getStdPrecision(), RoundingMode.HALF_UP); MMatchInv[] miList = MMatchInv.getInvoiceLine(Env.getCtx(), invoiceLine.get_ID(), getTrxName()); for (MMatchInv mi : miList) { if (!mi.isPosted()) { @@ -334,20 +341,190 @@ public class MatchInvTest extends AbstractTestCase { String whereClause = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MMatchInv.Table_ID + " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + mi.get_ID() - + " AND " + MFactAcct.COLUMNNAME_C_AcctSchema_ID + "=" + C_AcctSchema_ID; + + " AND " + MFactAcct.COLUMNNAME_C_AcctSchema_ID + "=" + as.getC_AcctSchema_ID(); int[] ids = MFactAcct.getAllIDs(MFactAcct.Table_Name, whereClause, getTrxName()); for (int id : ids) { MFactAcct fa = new MFactAcct(Env.getCtx(), id, getTrxName()); if (fa.getAccount_ID() == acctNIR.getAccount_ID()) - assertTrue(fa.getAmtAcctDr().compareTo(Env.ZERO) >= 0); + assertEquals(fa.getAmtAcctDr(), invMatchAmt, "MatchInv incorrect amount posted "+fa.getAmtAcctCr().toPlainString()); else if (fa.getAccount_ID() == acctInvClr.getAccount_ID()) - assertTrue(fa.getAmtAcctCr().compareTo(Env.ZERO) >= 0); + assertEquals(fa.getAmtAcctCr(), invMatchAmt, "MatchInv incorrect amount posted "+fa.getAmtAcctCr().toPlainString()); } } rollback(); } + @Test + /** + * Test Standard Cost and Invoice Price Variance posting + */ + public void testMatchInvStdCost() { + MProductCategory category = new MProductCategory(Env.getCtx(), 0, null); + category.setName("Standard Costing"); + category.saveEx(); + String whereClause = "M_Product_Category_ID=?"; + List categoryAccts = new Query(Env.getCtx(), MProductCategoryAcct.Table_Name, whereClause, null) + .setParameters(category.get_ID()) + .list(); + for (MProductCategoryAcct categoryAcct : categoryAccts) { + categoryAcct.setCostingMethod(MAcctSchema.COSTINGMETHOD_StandardCosting); + categoryAcct.saveEx(); + } + + try { + int mulchId = 137; // Mulch product + MProduct mulch = new MProduct(Env.getCtx(), mulchId, getTrxName()); + mulch.setM_Product_Category_ID(category.get_ID()); + mulch.saveEx(); + + int purchaseId = 102; // Purchase Price List + MBPartner bpartner = MBPartner.get(Env.getCtx(), 120); // Seed Farm Inc. + MAcctSchema as = MClient.get(getAD_Client_ID()).getAcctSchema(); + BigDecimal mulchCost = MCost.getCurrentCost(mulch, 0, getTrxName()).setScale(as.getCostingPrecision(), RoundingMode.HALF_UP); + + // Change standard cost of mulch product to 2.1234 + int hqLocator = 101; + int costAdjustmentDocTypeId = 200004; + MInventory inventory = new MInventory(Env.getCtx(), 0, getTrxName()); + inventory.setCostingMethod(MAcctSchema.COSTINGMETHOD_StandardCosting); + inventory.setC_DocType_ID(costAdjustmentDocTypeId); + inventory.setM_Warehouse_ID(getM_Warehouse_ID()); + inventory.setMovementDate(getLoginDate()); + inventory.setDocAction(DocAction.ACTION_Complete); + inventory.saveEx(); + + BigDecimal endProductCost = new BigDecimal("2.1234").setScale(as.getCostingPrecision(), RoundingMode.HALF_UP); + MInventoryLine il = new MInventoryLine(Env.getCtx(), 0, getTrxName()); + il.setM_Inventory_ID(inventory.get_ID()); + il.setM_Locator_ID(hqLocator); + il.setM_Product_ID(mulch.getM_Product_ID()); + il.setCurrentCostPrice(mulchCost); + il.setNewCostPrice(endProductCost); + il.saveEx(); + + ProcessInfo info = MWorkflow.runDocumentActionWorkflow(inventory, DocAction.ACTION_Complete); + inventory.load(getTrxName()); + assertFalse(info.isError(), info.getSummary()); + assertEquals(DocAction.STATUS_Completed, inventory.getDocStatus(), "Cost Adjustment Status="+inventory.getDocStatus()); + + if (!inventory.isPosted()) { + String msg = DocumentEngine.postImmediate(Env.getCtx(), getAD_Client_ID(), MInventory.Table_ID, inventory.get_ID(), false, getTrxName()); + assertNull(msg, msg); + } + mulchCost = MCost.getCurrentCost(mulch, 0, getTrxName()).setScale(as.getCostingPrecision(), RoundingMode.HALF_UP); + assertEquals(endProductCost, mulchCost, "Cost not adjusted: " + mulchCost.toPlainString()); + + MOrder order = new MOrder(Env.getCtx(), 0, getTrxName()); + order.setBPartner(bpartner); + order.setIsSOTrx(false); + order.setC_DocTypeTarget_ID(); + order.setM_PriceList_ID(purchaseId); + order.setDocStatus(DocAction.STATUS_Drafted); + order.setDocAction(DocAction.ACTION_Complete); + order.saveEx(); + + MOrderLine orderLine = new MOrderLine(order); + orderLine.setLine(10); + orderLine.setProduct(mulch); + orderLine.setQty(BigDecimal.ONE); + orderLine.saveEx(); + + info = MWorkflow.runDocumentActionWorkflow(order, DocAction.ACTION_Complete); + order.load(getTrxName()); + assertFalse(info.isError()); + assertEquals(DocAction.STATUS_Completed, order.getDocStatus()); + + MInOut receipt = new MInOut(order, 122, order.getDateOrdered()); // MM Receipt + receipt.saveEx(); + + MInOutLine receiptLine = new MInOutLine(receipt); + receiptLine.setC_OrderLine_ID(orderLine.get_ID()); + receiptLine.setLine(10); + receiptLine.setProduct(mulch); + receiptLine.setQty(BigDecimal.ONE); + MWarehouse wh = MWarehouse.get(Env.getCtx(), receipt.getM_Warehouse_ID()); + int M_Locator_ID = wh.getDefaultLocator().getM_Locator_ID(); + receiptLine.setM_Locator_ID(M_Locator_ID); + receiptLine.saveEx(); + + info = MWorkflow.runDocumentActionWorkflow(receipt, DocAction.ACTION_Complete); + receipt.load(getTrxName()); + assertFalse(info.isError()); + assertEquals(DocAction.STATUS_Completed, receipt.getDocStatus()); + + if (!receipt.isPosted()) { + String error = DocumentEngine.postImmediate(Env.getCtx(), receipt.getAD_Client_ID(), MInOut.Table_ID, receipt.get_ID(), false, getTrxName()); + assertTrue(error == null); + } + receipt.load(getTrxName()); + assertTrue(receipt.isPosted()); + + MInvoice invoice = new MInvoice(receipt, receipt.getMovementDate()); + invoice.setC_DocTypeTarget_ID(MDocType.DOCBASETYPE_APInvoice); + invoice.setDocStatus(DocAction.STATUS_Drafted); + invoice.setDocAction(DocAction.ACTION_Complete); + invoice.saveEx(); + + MInvoiceLine invoiceLine = new MInvoiceLine(invoice); + invoiceLine.setM_InOutLine_ID(receiptLine.get_ID()); + invoiceLine.setLine(10); + invoiceLine.setProduct(mulch); + invoiceLine.setQty(BigDecimal.ONE); + invoiceLine.saveEx(); + + info = MWorkflow.runDocumentActionWorkflow(invoice, DocAction.ACTION_Complete); + invoice.load(getTrxName()); + assertFalse(info.isError()); + assertEquals(DocAction.STATUS_Completed, invoice.getDocStatus()); + + if (!invoice.isPosted()) { + String error = DocumentEngine.postImmediate(Env.getCtx(), invoice.getAD_Client_ID(), MInvoice.Table_ID, invoice.get_ID(), false, getTrxName()); + assertTrue(error == null); + } + invoice.load(getTrxName()); + assertTrue(invoice.isPosted()); + + MMatchInv[] miList = MMatchInv.getInvoiceLine(Env.getCtx(), invoiceLine.get_ID(), getTrxName()); + for (MMatchInv mi : miList) { + if (!mi.isPosted()) { + String error = DocumentEngine.postImmediate(Env.getCtx(), mi.getAD_Client_ID(), MMatchInv.Table_ID, mi.get_ID(), false, getTrxName()); + assertTrue(error == null); + } + mi.load(getTrxName()); + assertTrue(mi.isPosted()); + + Doc doc = DocManager.getDocument(as, MMatchInv.Table_ID, mi.get_ID(), getTrxName()); + doc.setC_BPartner_ID(mi.getC_InvoiceLine().getC_Invoice().getC_BPartner_ID()); + MAccount acctNIR = doc.getAccount(Doc.ACCTTYPE_NotInvoicedReceipts, as); + + ProductCost pc = new ProductCost (Env.getCtx(), mi.getM_Product_ID(), mi.getM_AttributeSetInstance_ID(), getTrxName()); + MAccount acctInvClr = pc.getAccount(ProductCost.ACCTTYPE_P_InventoryClearing, as); + MAccount acctIPV = pc.getAccount(ProductCost.ACCTTYPE_P_IPV, as); + int C_AcctSchema_ID = as.getC_AcctSchema_ID(); + + String whereClause2 = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MMatchInv.Table_ID + + " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + mi.get_ID() + + " AND " + MFactAcct.COLUMNNAME_C_AcctSchema_ID + "=" + C_AcctSchema_ID; + int[] ids = MFactAcct.getAllIDs(MFactAcct.Table_Name, whereClause2, getTrxName()); + BigDecimal invMatchAmt = invoiceLine.getMatchedQty().multiply(invoiceLine.getPriceActual()).setScale(as.getStdPrecision(), RoundingMode.HALF_UP); + mulchCost = mulchCost.setScale(as.getStdPrecision(), RoundingMode.HALF_UP); + for (int id : ids) { + MFactAcct fa = new MFactAcct(Env.getCtx(), id, getTrxName()); + if (fa.getAccount_ID() == acctNIR.getAccount_ID()) + assertEquals(fa.getAmtAcctDr(), mulchCost, ""); + else if (fa.getAccount_ID() == acctInvClr.getAccount_ID()) + assertEquals(fa.getAmtAcctCr(), invMatchAmt, ""); + else if (fa.getAccount_ID() == acctIPV.getAccount_ID()) + assertEquals(fa.getAmtAcctDr().subtract(fa.getAmtAcctCr()), invMatchAmt.subtract(mulchCost), ""); + } + } + } finally { + getTrx().rollback(); + category.deleteEx(true); + } + } + @Test /** * Test the matched invoice posting for credit memo @@ -432,8 +609,8 @@ public class MatchInvTest extends AbstractTestCase { receipt.load(getTrxName()); assertTrue(receipt.isPosted()); - int C_AcctSchema_ID = MClientInfo.get(Env.getCtx()).getC_AcctSchema1_ID(); - MAcctSchema as = MAcctSchema.get(Env.getCtx(), C_AcctSchema_ID); + MAcctSchema as = MClient.get(getAD_Client_ID()).getAcctSchema(); + BigDecimal invMatchAmt = invoiceLine.getMatchedQty().multiply(invoiceLine.getPriceActual()).setScale(as.getStdPrecision(), RoundingMode.HALF_UP); MMatchInv[] miList = MMatchInv.getInvoiceLine(Env.getCtx(), invoiceLine.get_ID(), getTrxName()); for (MMatchInv mi : miList) { if (!mi.isPosted()) { @@ -452,14 +629,14 @@ public class MatchInvTest extends AbstractTestCase { String whereClause = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MMatchInv.Table_ID + " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + mi.get_ID() - + " AND " + MFactAcct.COLUMNNAME_C_AcctSchema_ID + "=" + C_AcctSchema_ID; + + " AND " + MFactAcct.COLUMNNAME_C_AcctSchema_ID + "=" + as.getC_AcctSchema_ID(); int[] ids = MFactAcct.getAllIDs(MFactAcct.Table_Name, whereClause, getTrxName()); for (int id : ids) { MFactAcct fa = new MFactAcct(Env.getCtx(), id, getTrxName()); if (fa.getAccount_ID() == acctNIR.getAccount_ID()) - assertTrue(fa.getAmtAcctDr().compareTo(Env.ZERO) >= 0); + assertEquals(fa.getAmtAcctDr(), invMatchAmt, "MatchInv incorrect amount posted "+fa.getAmtAcctDr().toPlainString()); else if (fa.getAccount_ID() == acctInvClr.getAccount_ID()) - assertTrue(fa.getAmtAcctCr().compareTo(Env.ZERO) >= 0); + assertEquals(fa.getAmtAcctCr(), invMatchAmt, "MatchInv incorrect amount posted "+fa.getAmtAcctCr().toPlainString()); } } @@ -494,6 +671,7 @@ public class MatchInvTest extends AbstractTestCase { creditMemo.load(getTrxName()); assertTrue(creditMemo.isPosted()); + BigDecimal credMatchAmt = creditMemoLine.getMatchedQty().negate().multiply(creditMemoLine.getPriceActual()).setScale(as.getStdPrecision(), RoundingMode.HALF_UP); miList = MMatchInv.getInvoiceLine(Env.getCtx(), creditMemoLine.get_ID(), getTrxName()); for (MMatchInv mi : miList) { if (!mi.isPosted()) { @@ -510,16 +688,16 @@ public class MatchInvTest extends AbstractTestCase { BigDecimal amtAcctCrInvClr = BigDecimal.ZERO; String whereClause = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MMatchInv.Table_ID + " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + mi.get_ID() - + " AND " + MFactAcct.COLUMNNAME_C_AcctSchema_ID + "=" + C_AcctSchema_ID; + + " AND " + MFactAcct.COLUMNNAME_C_AcctSchema_ID + "=" + as.getC_AcctSchema_ID(); int[] ids = MFactAcct.getAllIDs(MFactAcct.Table_Name, whereClause, getTrxName()); for (int id : ids) { MFactAcct fa = new MFactAcct(Env.getCtx(), id, getTrxName()); if (fa.getAccount_ID() == acctInvClr.getAccount_ID() && fa.getQty().compareTo(BigDecimal.ZERO) < 0) { - assertTrue(fa.getAmtAcctCr().compareTo(Env.ZERO) >= 0); + assertEquals(fa.getAmtAcctCr(), credMatchAmt, "MatchInv incorrect amount posted "+fa.getAmtAcctCr().toPlainString()); amtAcctCrInvClr = amtAcctCrInvClr.add(fa.getAmtAcctCr()); } else if (fa.getAccount_ID() == acctInvClr.getAccount_ID() && fa.getQty().compareTo(BigDecimal.ZERO) > 0) { - assertTrue(fa.getAmtAcctDr().compareTo(Env.ZERO) >= 0); + assertEquals(fa.getAmtAcctDr(), credMatchAmt, "MatchInv incorrect amount posted "+fa.getAmtAcctDr().toPlainString()); amtAcctDrInvClr = amtAcctDrInvClr.add(fa.getAmtAcctDr()); } } @@ -651,9 +829,8 @@ public class MatchInvTest extends AbstractTestCase { invoice.load(getTrxName()); assertTrue(invoice.isPosted()); - int C_AcctSchema_ID = MClientInfo.get(Env.getCtx()).getC_AcctSchema1_ID(); //usd schema - MAcctSchema as = MAcctSchema.get(Env.getCtx(), C_AcctSchema_ID); - BigDecimal acctAmount = priceInYen.multiply(yenToUsd).multiply(qtyInvoiced).setScale(as.getC_Currency().getStdPrecision(), RoundingMode.HALF_UP); + MAcctSchema as = MClient.get(getAD_Client_ID()).getAcctSchema(); + BigDecimal acctAmount = priceInYen.multiply(yenToUsd).multiply(qtyInvoiced).setScale(as.getStdPrecision(), RoundingMode.HALF_UP); BigDecimal acctSource = priceInYen.multiply(qtyInvoiced).setScale(japaneseYen.getStdPrecision(), RoundingMode.HALF_UP); MMatchInv[] miList = MMatchInv.getInvoiceLine(Env.getCtx(), invoiceLine.get_ID(), getTrxName()); for (MMatchInv mi : miList) { @@ -673,22 +850,22 @@ public class MatchInvTest extends AbstractTestCase { String whereClause = MFactAcct.COLUMNNAME_AD_Table_ID + "=" + MMatchInv.Table_ID + " AND " + MFactAcct.COLUMNNAME_Record_ID + "=" + mi.get_ID() - + " AND " + MFactAcct.COLUMNNAME_C_AcctSchema_ID + "=" + C_AcctSchema_ID; + + " AND " + MFactAcct.COLUMNNAME_C_AcctSchema_ID + "=" + as.getC_AcctSchema_ID(); int[] ids = MFactAcct.getAllIDs(MFactAcct.Table_Name, whereClause, getTrxName()); for (int id : ids) { MFactAcct fa = new MFactAcct(Env.getCtx(), id, getTrxName()); if (fa.getAccount_ID() == acctNIR.getAccount_ID()) { assertTrue(fa.getAmtAcctDr().compareTo(Env.ZERO) >= 0); - assertTrue(fa.getAmtAcctDr().toPlainString().compareTo(acctAmount.toPlainString()) == 0, fa.getAmtAcctDr().toPlainString() + " != " + acctAmount.toPlainString()); + assertEquals(acctAmount, fa.getAmtAcctDr(), fa.getAmtAcctDr().toPlainString() + " != " + acctAmount.toPlainString()); // verify source amt and currency assertTrue(fa.getC_Currency_ID() == japaneseYen.getC_Currency_ID()); - assertTrue(fa.getAmtSourceDr().toPlainString().compareTo(acctSource.toPlainString()) == 0, fa.getAmtSourceDr().toPlainString() + " != " + acctSource.toPlainString()); + assertEquals(acctSource, fa.getAmtSourceDr(), fa.getAmtSourceDr().toPlainString() + " != " + acctSource.toPlainString()); } else if (fa.getAccount_ID() == acctInvClr.getAccount_ID()) { assertTrue(fa.getAmtAcctCr().compareTo(Env.ZERO) >= 0); - assertTrue(fa.getAmtAcctCr().toPlainString().compareTo(acctAmount.toPlainString()) == 0, fa.getAmtAcctCr().toPlainString() + " != " + acctAmount.toPlainString()); + assertEquals(acctAmount, fa.getAmtAcctCr(), fa.getAmtAcctCr().toPlainString() + " != " + acctAmount.toPlainString()); // verify source amt and currency assertTrue(fa.getC_Currency_ID() == japaneseYen.getC_Currency_ID()); - assertTrue(fa.getAmtSourceCr().toPlainString().compareTo(acctSource.toPlainString()) == 0, fa.getAmtSourceCr().toPlainString() + " != " + acctSource.toPlainString()); + assertEquals(acctSource, fa.getAmtSourceCr(), fa.getAmtSourceCr().toPlainString() + " != " + acctSource.toPlainString()); } } } diff --git a/org.idempiere.test/src/org/idempiere/test/model/MProductTest.java b/org.idempiere.test/src/org/idempiere/test/model/MProductTest.java index e64b715134..4400471007 100644 --- a/org.idempiere.test/src/org/idempiere/test/model/MProductTest.java +++ b/org.idempiere.test/src/org/idempiere/test/model/MProductTest.java @@ -227,7 +227,7 @@ public class MProductTest extends AbstractTestCase { count = query.setParameters(product.get_ID()).count(); assertTrue(count > 0, "No Storage Reservation Record"); - //this should faiil due to on hand > 0 + //this should fail due to on hand > 0 product.setIsActive(false); assertThrows(AdempiereException.class, () -> product.saveEx()); @@ -250,10 +250,14 @@ public class MProductTest extends AbstractTestCase { MPPProductBOM bom = query.setClient_ID().setOnlyActiveRecords(true).first(); MPPProductBOMLine[] lines = bom.getLines(); final MProduct product = new MProduct(Env.getCtx(), lines[0].getM_Product_ID(), getTrxName()); + //clear on hand so that exception is not due to QtyOnHand + DB.executeUpdateEx("UPDATE M_StorageOnHand SET QtyOnHand=0 WHERE M_Product_ID=?", new Object[] {product.get_ID()}, getTrxName()); product.setIsActive(false); assertThrows(AdempiereException.class, () -> product.saveEx(), "No exception throw for deactivation of product in active BOM"); MProduct parent = new MProduct(Env.getCtx(), bom.getM_Product_ID(), getTrxName()); + //clear on hand so that we can deactivate product + DB.executeUpdateEx("UPDATE M_StorageOnHand SET QtyOnHand=0 WHERE M_Product_ID=?", new Object[] {parent.get_ID()}, getTrxName()); parent.setIsActive(false); parent.saveEx(); bom.load(getTrxName());