IDEMPIERE-5878 Wrong GL posting in allocation for payment REVERSE/ACCRUAL, if payment WITH charge (#2074)
This commit is contained in:
parent
5379315ab3
commit
a061eeedb4
|
@ -32,6 +32,7 @@ import org.compiere.model.MAcctSchemaElement;
|
||||||
import org.compiere.model.MAllocationHdr;
|
import org.compiere.model.MAllocationHdr;
|
||||||
import org.compiere.model.MAllocationLine;
|
import org.compiere.model.MAllocationLine;
|
||||||
import org.compiere.model.MCashLine;
|
import org.compiere.model.MCashLine;
|
||||||
|
import org.compiere.model.MCharge;
|
||||||
import org.compiere.model.MConversionRate;
|
import org.compiere.model.MConversionRate;
|
||||||
import org.compiere.model.MDocType;
|
import org.compiere.model.MDocType;
|
||||||
import org.compiere.model.MFactAcct;
|
import org.compiere.model.MFactAcct;
|
||||||
|
@ -687,7 +688,9 @@ public class Doc_AllocationHdr extends Doc
|
||||||
// or Doc.ACCTTYPE_PaymentSelect (AP) or V_Prepayment
|
// or Doc.ACCTTYPE_PaymentSelect (AP) or V_Prepayment
|
||||||
int accountType = Doc.ACCTTYPE_UnallocatedCash;
|
int accountType = Doc.ACCTTYPE_UnallocatedCash;
|
||||||
//
|
//
|
||||||
String sql = "SELECT p.C_BankAccount_ID, d.DocBaseType, p.IsReceipt, p.IsPrepayment "
|
int C_Charge_ID = 0;
|
||||||
|
|
||||||
|
String sql = "SELECT p.C_BankAccount_ID, d.DocBaseType, p.IsReceipt, p.IsPrepayment, p.C_Charge_ID "
|
||||||
+ "FROM C_Payment p INNER JOIN C_DocType d ON (p.C_DocType_ID=d.C_DocType_ID) "
|
+ "FROM C_Payment p INNER JOIN C_DocType d ON (p.C_DocType_ID=d.C_DocType_ID) "
|
||||||
+ "WHERE C_Payment_ID=?";
|
+ "WHERE C_Payment_ID=?";
|
||||||
PreparedStatement pstmt = null;
|
PreparedStatement pstmt = null;
|
||||||
|
@ -700,6 +703,7 @@ public class Doc_AllocationHdr extends Doc
|
||||||
if (rs.next ())
|
if (rs.next ())
|
||||||
{
|
{
|
||||||
setC_BankAccount_ID(rs.getInt(1));
|
setC_BankAccount_ID(rs.getInt(1));
|
||||||
|
C_Charge_ID = rs.getInt(5); // Charge
|
||||||
if (DOCTYPE_APPayment.equals(rs.getString(2)))
|
if (DOCTYPE_APPayment.equals(rs.getString(2)))
|
||||||
accountType = Doc.ACCTTYPE_PaymentSelect;
|
accountType = Doc.ACCTTYPE_PaymentSelect;
|
||||||
// Prepayment
|
// Prepayment
|
||||||
|
@ -728,6 +732,9 @@ public class Doc_AllocationHdr extends Doc
|
||||||
log.log(Level.SEVERE, "NONE for C_Payment_ID=" + C_Payment_ID);
|
log.log(Level.SEVERE, "NONE for C_Payment_ID=" + C_Payment_ID);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (C_Charge_ID != 0)
|
||||||
|
return MCharge.getAccount(C_Charge_ID, as);
|
||||||
return getAccount (accountType, as);
|
return getAccount (accountType, as);
|
||||||
} // getPaymentAcct
|
} // getPaymentAcct
|
||||||
|
|
||||||
|
|
|
@ -1882,6 +1882,68 @@ public class Allocation2ndAcctSchemaTest extends AbstractTestCase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@ResourceLock(value = MConversionRate.Table_Name)
|
||||||
|
/**
|
||||||
|
* Test the allocation posting (different period + reversal)
|
||||||
|
* Payment with Charge Total=1000, Period 1
|
||||||
|
* Payment with Charge Total=1000, Period 2 (Reversed)
|
||||||
|
* https://idempiere.atlassian.net/browse/IDEMPIERE-5878
|
||||||
|
*/
|
||||||
|
public void testAllocatePaymentPosting_5() {
|
||||||
|
MBPartner bpartner = MBPartner.get(Env.getCtx(), DictionaryIDs.C_BPartner.AGRI_TECH.id);
|
||||||
|
Timestamp currentDate = Env.getContextAsDate(Env.getCtx(), "#Date");
|
||||||
|
|
||||||
|
Calendar cal = Calendar.getInstance();
|
||||||
|
cal.setTimeInMillis(currentDate.getTime());
|
||||||
|
cal.add(Calendar.DAY_OF_MONTH, -1);
|
||||||
|
Timestamp date1 = new Timestamp(cal.getTimeInMillis());
|
||||||
|
Timestamp date2 = currentDate;
|
||||||
|
|
||||||
|
int C_ConversionType_ID = DictionaryIDs.C_ConversionType.COMPANY.id; // Company
|
||||||
|
|
||||||
|
MCurrency usd = MCurrency.get(DictionaryIDs.C_Currency.USD.id); // USD
|
||||||
|
MCurrency euro = MCurrency.get(DictionaryIDs.C_Currency.EUR.id); // EUR
|
||||||
|
BigDecimal eurToUsd1 = new BigDecimal(4);
|
||||||
|
MConversionRate cr1 = createConversionRate(euro.getC_Currency_ID(), usd.getC_Currency_ID(), C_ConversionType_ID, date1, eurToUsd1);
|
||||||
|
|
||||||
|
BigDecimal eurToUsd2 = new BigDecimal(5);
|
||||||
|
MConversionRate cr2 = createConversionRate(euro.getC_Currency_ID(), usd.getC_Currency_ID(), C_ConversionType_ID, date2, eurToUsd2);
|
||||||
|
|
||||||
|
try {
|
||||||
|
MBankAccount ba = getBankAccount(usd.getC_Currency_ID());
|
||||||
|
BigDecimal payAmt = new BigDecimal(1000);
|
||||||
|
MPayment payment = createPayment(true, bpartner, ba.getC_BankAccount_ID(), date1, payAmt, euro.getC_Currency_ID(), C_ConversionType_ID);
|
||||||
|
payment.setC_Charge_ID(DictionaryIDs.C_Charge.BANK.id); // Bank Charge
|
||||||
|
payment.saveEx();
|
||||||
|
completeDocument(payment);
|
||||||
|
postDocument(payment);
|
||||||
|
|
||||||
|
reverseDocument(payment, false);
|
||||||
|
MPayment reversalPayment = new MPayment(Env.getCtx(), payment.getReversal_ID(), getTrxName());
|
||||||
|
postDocument(reversalPayment);
|
||||||
|
|
||||||
|
MAcctSchema[] ass = MAcctSchema.getClientAcctSchema(Env.getCtx(), Env.getAD_Client_ID(Env.getCtx()));
|
||||||
|
MAllocationHdr[] allocList = MAllocationHdr.getOfPayment(Env.getCtx(), payment.getC_Payment_ID(), getTrxName());
|
||||||
|
|
||||||
|
BigDecimal allocAmount = payAmt;
|
||||||
|
ArrayList<PostingLine> paymentLineList = new ArrayList<PostingLine>();
|
||||||
|
ArrayList<PostingLine> gainLossLineList = new ArrayList<PostingLine>();
|
||||||
|
BigDecimal accountedDrAmt = getAccountedAmount(usd, allocAmount, cr1.getMultiplyRate());
|
||||||
|
BigDecimal accountedCrAmt = getAccountedAmount(usd, allocAmount, cr2.getMultiplyRate());
|
||||||
|
paymentLineList.add(new PostingLine(usd, accountedDrAmt, Env.ZERO));
|
||||||
|
paymentLineList.add(new PostingLine(usd, Env.ZERO, accountedCrAmt));
|
||||||
|
BigDecimal gainLossAmt = new BigDecimal(1000).setScale(usd.getStdPrecision(), RoundingMode.HALF_UP);
|
||||||
|
gainLossLineList.add(new PostingLine(usd, gainLossAmt, Env.ZERO));
|
||||||
|
|
||||||
|
testAllocationPosting(ass, allocList, paymentLineList, null, gainLossLineList, null);
|
||||||
|
} finally {
|
||||||
|
rollback();
|
||||||
|
deleteConversionRate(cr1);
|
||||||
|
deleteConversionRate(cr2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private MConversionRate createConversionRate(int C_Currency_ID, int C_Currency_ID_To, int C_ConversionType_ID,
|
private MConversionRate createConversionRate(int C_Currency_ID, int C_Currency_ID_To, int C_ConversionType_ID,
|
||||||
Timestamp date, BigDecimal rate) {
|
Timestamp date, BigDecimal rate) {
|
||||||
return createConversionRate(C_Currency_ID, C_Currency_ID_To, C_ConversionType_ID, date, rate, true);
|
return createConversionRate(C_Currency_ID, C_Currency_ID_To, C_ConversionType_ID, date, rate, true);
|
||||||
|
@ -2072,11 +2134,13 @@ public class Allocation2ndAcctSchemaTest extends AbstractTestCase {
|
||||||
|
|
||||||
int C_BPartner_ID = 0;
|
int C_BPartner_ID = 0;
|
||||||
int C_BankAccount_ID = 0;
|
int C_BankAccount_ID = 0;
|
||||||
|
int C_Charge_ID = 0;
|
||||||
MAllocationLine[] lines = alloc.getLines(false);
|
MAllocationLine[] lines = alloc.getLines(false);
|
||||||
for (MAllocationLine line : lines) {
|
for (MAllocationLine line : lines) {
|
||||||
if (line.getC_Payment_ID() > 0) {
|
if (line.getC_Payment_ID() > 0) {
|
||||||
C_BPartner_ID = line.getC_Payment().getC_BPartner_ID();
|
C_BPartner_ID = line.getC_Payment().getC_BPartner_ID();
|
||||||
C_BankAccount_ID = line.getC_Payment().getC_BankAccount_ID();
|
C_BankAccount_ID = line.getC_Payment().getC_BankAccount_ID();
|
||||||
|
C_Charge_ID = line.getC_Payment().getC_Charge_ID();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2101,6 +2165,10 @@ public class Allocation2ndAcctSchemaTest extends AbstractTestCase {
|
||||||
if (C_BPartner_ID > 0)
|
if (C_BPartner_ID > 0)
|
||||||
doc.setC_BPartner_ID(C_BPartner_ID);
|
doc.setC_BPartner_ID(C_BPartner_ID);
|
||||||
|
|
||||||
|
MAccount acctCharge = null;
|
||||||
|
if (C_Charge_ID != 0)
|
||||||
|
acctCharge = MCharge.getAccount(C_Charge_ID, as);
|
||||||
|
|
||||||
MAccount acctUnallocatedCash = doc.getAccount(Doc.ACCTTYPE_UnallocatedCash, as);
|
MAccount acctUnallocatedCash = doc.getAccount(Doc.ACCTTYPE_UnallocatedCash, as);
|
||||||
MAccount acctReceivable = doc.getAccount(Doc.ACCTTYPE_C_Receivable, as);
|
MAccount acctReceivable = doc.getAccount(Doc.ACCTTYPE_C_Receivable, as);
|
||||||
MAccount acctLiability = doc.getAccount(Doc.ACCTTYPE_V_Liability, as);
|
MAccount acctLiability = doc.getAccount(Doc.ACCTTYPE_V_Liability, as);
|
||||||
|
@ -2119,7 +2187,9 @@ public class Allocation2ndAcctSchemaTest extends AbstractTestCase {
|
||||||
int[] ids = MFactAcct.getAllIDs(MFactAcct.Table_Name, whereClause, getTrxName());
|
int[] ids = MFactAcct.getAllIDs(MFactAcct.Table_Name, whereClause, getTrxName());
|
||||||
for (int id : ids) {
|
for (int id : ids) {
|
||||||
MFactAcct fa = new MFactAcct(Env.getCtx(), id, getTrxName());
|
MFactAcct fa = new MFactAcct(Env.getCtx(), id, getTrxName());
|
||||||
if (acctUnallocatedCash != null && acctUnallocatedCash.getAccount_ID() == fa.getAccount_ID())
|
if (C_Charge_ID != 0 && acctCharge != null && acctCharge.getAccount_ID() == fa.getAccount_ID())
|
||||||
|
totalPaymentAmtAcct = totalPaymentAmtAcct.add(fa.getAmtAcctDr()).subtract(fa.getAmtAcctCr());
|
||||||
|
else if (C_Charge_ID == 0 && acctUnallocatedCash != null && acctUnallocatedCash.getAccount_ID() == fa.getAccount_ID())
|
||||||
totalPaymentAmtAcct = totalPaymentAmtAcct.add(fa.getAmtAcctDr()).subtract(fa.getAmtAcctCr());
|
totalPaymentAmtAcct = totalPaymentAmtAcct.add(fa.getAmtAcctDr()).subtract(fa.getAmtAcctCr());
|
||||||
else if ((acctReceivable != null && acctReceivable.getAccount_ID() == fa.getAccount_ID()) ||
|
else if ((acctReceivable != null && acctReceivable.getAccount_ID() == fa.getAccount_ID()) ||
|
||||||
(acctLiability != null && acctLiability.getAccount_ID() == fa.getAccount_ID()))
|
(acctLiability != null && acctLiability.getAccount_ID() == fa.getAccount_ID()))
|
||||||
|
|
Loading…
Reference in New Issue