diff --git a/org.adempiere.base/src/org/compiere/model/MMatchInv.java b/org.adempiere.base/src/org/compiere/model/MMatchInv.java index d736963dec..46c7b62e37 100644 --- a/org.adempiere.base/src/org/compiere/model/MMatchInv.java +++ b/org.adempiere.base/src/org/compiere/model/MMatchInv.java @@ -24,6 +24,7 @@ import java.util.Properties; import org.compiere.util.CLogger; import org.compiere.util.DB; +import org.compiere.util.Env; /** * Match Invoice (Receipt<>Invoice) Model. @@ -394,4 +395,21 @@ public class MMatchInv extends X_M_MatchInv } return false; } + + + @Override + public MInOutLine getM_InOutLine() throws RuntimeException { + return new MInOutLine(Env.getCtx(), getM_InOutLine_ID(), get_TrxName()); + } + + /** + * @return true if this is created to reverse another match invoice document + */ + public boolean isReversal() { + if (getReversal_ID() > 0) { + if (getM_InOutLine().getMovementQty().signum() != getQty().signum()) + return true; + } + return false; + } } // MMatchInv 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 588acb1f38..9ff0486e89 100644 --- a/org.idempiere.test/src/org/idempiere/test/base/MatchInvTest.java +++ b/org.idempiere.test/src/org/idempiere/test/base/MatchInvTest.java @@ -723,4 +723,98 @@ public class MatchInvTest extends AbstractTestCase { rollback(); } } + + @Test + public void testIsReversal() { + MBPartner bpartner = MBPartner.get(Env.getCtx(), 114); // Tree Farm Inc. + MProduct product = MProduct.get(Env.getCtx(), 124); // Elm Tree + + MOrder order = new MOrder(Env.getCtx(), 0, getTrxName()); + order.setBPartner(bpartner); + order.setIsSOTrx(false); + order.setC_DocTypeTarget_ID(); + order.setDocStatus(DocAction.STATUS_Drafted); + order.setDocAction(DocAction.ACTION_Complete); + order.saveEx(); + + MOrderLine orderLine = new MOrderLine(order); + orderLine.setLine(10); + orderLine.setProduct(product); + orderLine.setQty(BigDecimal.ONE); + orderLine.saveEx(); + + ProcessInfo 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(product); + 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(product); + 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[] beforeList = MMatchInv.getInvoiceLine(Env.getCtx(), invoiceLine.get_ID(), getTrxName()); + assertEquals(1, beforeList.length); + + info = MWorkflow.runDocumentActionWorkflow(invoice, DocAction.ACTION_Reverse_Correct); + invoice.load(getTrxName()); + assertFalse(info.isError()); + assertEquals(DocAction.STATUS_Reversed, invoice.getDocStatus()); + + MMatchInv[] afterList = MMatchInv.getInvoiceLine(Env.getCtx(), invoiceLine.get_ID(), getTrxName()); + assertEquals(2, afterList.length); + beforeList[0].load(getTrxName()); + assertFalse(beforeList[0].isReversal()); + for(MMatchInv mi : afterList) { + if (!mi.equals(beforeList[0])) { + assertTrue(mi.isReversal()); + break; + } + } + } }