From e057072bc7d264f4eb4750e2fe6ce73455c59d95 Mon Sep 17 00:00:00 2001 From: Carlos Ruiz Date: Tue, 30 Jun 2020 12:45:14 +0200 Subject: [PATCH] IDEMPIERE-829 Implement MInvoice.getOpenAmt with paymentDate (#135) --- .../src/org/compiere/model/MInvoice.java | 57 ++++--- .../test/model/InvoiceCustomerTest.java | 148 ++++++++++++++++++ 2 files changed, 184 insertions(+), 21 deletions(-) create mode 100644 org.idempiere.test/src/org/idempiere/test/model/InvoiceCustomerTest.java diff --git a/org.adempiere.base/src/org/compiere/model/MInvoice.java b/org.adempiere.base/src/org/compiere/model/MInvoice.java index b522064c36..aedf9cf93b 100644 --- a/org.adempiere.base/src/org/compiere/model/MInvoice.java +++ b/org.adempiere.base/src/org/compiere/model/MInvoice.java @@ -68,7 +68,7 @@ public class MInvoice extends X_C_Invoice implements DocAction /** * */ - private static final long serialVersionUID = -3191227310812025813L; + private static final long serialVersionUID = 5581441980246794522L; /** * Get Payments Of BPartner @@ -1283,43 +1283,58 @@ public class MInvoice extends X_C_Invoice implements DocAction */ public BigDecimal getOpenAmt () { - return getOpenAmt (true, null); + return getOpenAmt (true, null, false); } // getOpenAmt + public BigDecimal getOpenAmt (boolean creditMemoAdjusted, Timestamp paymentDate) + { + return getOpenAmt(creditMemoAdjusted, paymentDate, false); + } /** * Get Open Amount * @param creditMemoAdjusted adjusted for CM (negative) - * @param paymentDate ignored Payment Date + * @param paymentDate Payment Date * @return Open Amt */ - public BigDecimal getOpenAmt (boolean creditMemoAdjusted, Timestamp paymentDate) + public BigDecimal getOpenAmt (boolean creditMemoAdjusted, Timestamp paymentDate, boolean requery) { - if (isPaid()) + if (isPaid() && paymentDate == null) return Env.ZERO; // - if (m_openAmt == null) - { - m_openAmt = getGrandTotal(); - if (paymentDate != null) - { - // Payment Discount - // Payment Schedule - } - BigDecimal allocated = getAllocatedAmt(); - if (allocated != null) - { - allocated = allocated.abs(); // is absolute - m_openAmt = m_openAmt.subtract(allocated); + if (paymentDate != null || m_openAmt == null || requery) { + BigDecimal l_openAmt = getOpenAmt(paymentDate); + if (paymentDate != null) { + if (isCreditMemo() && creditMemoAdjusted) + return l_openAmt.negate(); + return l_openAmt; + } else { + m_openAmt = l_openAmt; } } // - if (!creditMemoAdjusted) - return m_openAmt; - if (isCreditMemo()) + if (isCreditMemo() && creditMemoAdjusted) return m_openAmt.negate(); return m_openAmt; } // getOpenAmt + /* + * Get open amt depending on payment date + * @return open Amt + */ + public BigDecimal getOpenAmt (Timestamp paymentDate) + { + BigDecimal retValue; + if (paymentDate == null) { + retValue = DB.getSQLValueBDEx(get_TrxName(), + "SELECT invoiceOpen(?,?) FROM DUAL", + getC_Invoice_ID(), 0); + } else { + retValue = DB.getSQLValueBDEx(get_TrxName(), + "SELECT invoiceOpenToDate(?,?,?) FROM DUAL", + getC_Invoice_ID(), 0, paymentDate); + } + return retValue; + } // getOpenAmt /** * Get Document Status diff --git a/org.idempiere.test/src/org/idempiere/test/model/InvoiceCustomerTest.java b/org.idempiere.test/src/org/idempiere/test/model/InvoiceCustomerTest.java new file mode 100644 index 0000000000..84f75956a4 --- /dev/null +++ b/org.idempiere.test/src/org/idempiere/test/model/InvoiceCustomerTest.java @@ -0,0 +1,148 @@ +/*********************************************************************** + * 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: * + * - Carlos Ruiz - globalqss * + **********************************************************************/ +package org.idempiere.test.model; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.math.BigDecimal; +import java.sql.Timestamp; + +import org.compiere.model.MBPartner; +import org.compiere.model.MDocType; +import org.compiere.model.MInvoice; +import org.compiere.model.MInvoiceLine; +import org.compiere.model.MPayment; +import org.compiere.process.DocAction; +import org.compiere.process.ProcessInfo; +import org.compiere.util.Env; +import org.compiere.util.TimeUtil; +import org.compiere.wf.MWorkflow; +import org.idempiere.test.AbstractTestCase; +import org.junit.jupiter.api.Test; + +/** + * @author Carlos Ruiz - globalqss + */ +public class InvoiceCustomerTest extends AbstractTestCase { + + public InvoiceCustomerTest() { + } + + final static BigDecimal TWOHUNDRED = new BigDecimal("200"); + + @Test + /** + * https://idempiere.atlassian.net/browse/IDEMPIERE-829 + */ + public void testOpenAmt() { + // Invoice $200 today + MInvoice invoice = new MInvoice(Env.getCtx(), 0, getTrxName()); + invoice.setBPartner(MBPartner.get(Env.getCtx(), 117)); // C&W + invoice.setC_DocTypeTarget_ID(MDocType.DOCBASETYPE_ARInvoice); + invoice.setC_DocType_ID(invoice.getC_DocTypeTarget_ID()); // required to avoid runDocumentActionWorkflow exception + invoice.setPaymentRule(MInvoice.PAYMENTRULE_Check); + invoice.setC_PaymentTerm_ID(105); // Immediate + Timestamp today = TimeUtil.getDay(System.currentTimeMillis()); + invoice.setDateInvoiced(today); + invoice.setDateAcct(today); + invoice.setDocStatus(DocAction.STATUS_Drafted); + invoice.setDocAction(DocAction.ACTION_Complete); + invoice.saveEx(); + + MInvoiceLine line1 = new MInvoiceLine(invoice); + line1.setLine(10); + line1.setC_Charge_ID(100); // Bank Charge + line1.setQty(new BigDecimal("1")); + line1.setPrice(Env.ONEHUNDRED); + line1.saveEx(); + + MInvoiceLine line2 = new MInvoiceLine(invoice); + line2.setLine(20); + line2.setC_Charge_ID(101); // Commissions Paid + line2.setQty(new BigDecimal("1")); + line2.setPrice(Env.ONEHUNDRED); + line2.saveEx(); + + ProcessInfo info = MWorkflow.runDocumentActionWorkflow(invoice, DocAction.ACTION_Complete); + invoice.load(getTrxName()); + assertFalse(info.isError()); + assertEquals(DocAction.STATUS_Completed, invoice.getDocStatus()); + assertTrue(TWOHUNDRED.compareTo(invoice.getGrandTotal()) == 0); + + // first $100 payment next week + MPayment payment1 = new MPayment(Env.getCtx(), 0, getTrxName()); + payment1.setC_Invoice_ID(invoice.getC_Invoice_ID()); + payment1.setC_BPartner_ID(invoice.getC_BPartner_ID()); + payment1.setC_DocType_ID(true); // Receipt + payment1.setDocStatus(DocAction.STATUS_Drafted); + payment1.setDocAction(DocAction.ACTION_Complete); + payment1.setPayAmt(Env.ONEHUNDRED); + payment1.setTenderType(MPayment.TENDERTYPE_Check); + payment1.setC_BankAccount_ID(100); // 1234_MoneyBank_123456789 + payment1.setC_Currency_ID(100); // USD + Timestamp nextweek = TimeUtil.addDays(today, 7); + payment1.setDateTrx(nextweek); + payment1.setDateAcct(nextweek); + payment1.saveEx(); + + info = MWorkflow.runDocumentActionWorkflow(payment1, DocAction.ACTION_Complete); + payment1.load(getTrxName()); + assertFalse(info.isError()); + assertEquals(DocAction.STATUS_Completed, payment1.getDocStatus()); + assertEquals(false, invoice.isPaid()); + + // second $100 payment next two weeks + MPayment payment2 = new MPayment(Env.getCtx(), 0, getTrxName()); + payment2.setC_Invoice_ID(invoice.getC_Invoice_ID()); + payment2.setC_BPartner_ID(invoice.getC_BPartner_ID()); + payment2.setC_DocType_ID(true); // Receipt + payment2.setDocStatus(DocAction.STATUS_Drafted); + payment2.setDocAction(DocAction.ACTION_Complete); + payment2.setPayAmt(Env.ONEHUNDRED); + payment2.setTenderType(MPayment.TENDERTYPE_Check); + payment2.setC_BankAccount_ID(100); // 1234_MoneyBank_123456789 + payment2.setC_Currency_ID(100); // USD + Timestamp next2weeks = TimeUtil.addDays(today, 14); + payment2.setDateTrx(next2weeks); + payment2.setDateAcct(next2weeks); + payment2.saveEx(); + + info = MWorkflow.runDocumentActionWorkflow(payment2, DocAction.ACTION_Complete); + payment2.load(getTrxName()); + assertFalse(info.isError()); + assertEquals(DocAction.STATUS_Completed, payment2.getDocStatus()); + + invoice.load(getTrxName()); + assertEquals(true, invoice.isPaid()); + assertTrue(Env.ZERO.compareTo(invoice.getOpenAmt()) == 0); + assertTrue(TWOHUNDRED.compareTo(invoice.getOpenAmt(false, today, true)) == 0); + assertTrue(Env.ONEHUNDRED.compareTo(invoice.getOpenAmt(false, nextweek, true)) == 0); + assertTrue(Env.ZERO.compareTo(invoice.getOpenAmt(false, next2weeks, true)) == 0); + + rollback(); + } +}