FINERACT-2042 Chargeback with credit allocation, accounting
diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransaction.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransaction.java
index 960ef61..1b737fe 100644
--- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransaction.java
+++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransaction.java
@@ -35,6 +35,7 @@
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.Set;
import org.apache.fineract.infrastructure.core.domain.AbstractAuditableWithUTCDateTimeCustom;
import org.apache.fineract.infrastructure.core.domain.ExternalId;
@@ -763,7 +764,14 @@
thisTransactionData.put("currencyCode", currencyCode);
thisTransactionData.put("amount", this.amount);
thisTransactionData.put("netDisbursalAmount", this.loan.getNetDisbursalAmount());
- thisTransactionData.put("principalPortion", this.principalPortion);
+
+ if (transactionType.isChargeback()
+ && (getLoan().getCreditAllocationRules() == null || getLoan().getCreditAllocationRules().size() == 0)) {
+ thisTransactionData.put("principalPortion", this.amount);
+ } else {
+ thisTransactionData.put("principalPortion", this.principalPortion);
+ }
+
thisTransactionData.put("interestPortion", this.interestPortion);
thisTransactionData.put("feeChargesPortion", this.feeChargesPortion);
thisTransactionData.put("penaltyChargesPortion", this.penaltyChargesPortion);
@@ -790,6 +798,26 @@
thisTransactionData.put("loanChargesPaid", loanChargesPaidData);
}
+ if (transactionType.isChargeback() && this.overPaymentPortion != null && this.overPaymentPortion.compareTo(BigDecimal.ZERO) > 0) {
+ BigDecimal principalPaid = overPaymentPortion;
+ BigDecimal feePaid = BigDecimal.ZERO;
+ BigDecimal penaltyPaid = BigDecimal.ZERO;
+ if (getLoanTransactionToRepaymentScheduleMappings().size() > 0) {
+ principalPaid = getLoanTransactionToRepaymentScheduleMappings().stream()
+ .map(mapping -> Optional.ofNullable(mapping.getPrincipalPortion()).orElse(BigDecimal.ZERO))
+ .reduce(BigDecimal.ZERO, BigDecimal::add);
+ feePaid = getLoanTransactionToRepaymentScheduleMappings().stream()
+ .map(mapping -> Optional.ofNullable(mapping.getFeeChargesPortion()).orElse(BigDecimal.ZERO))
+ .reduce(BigDecimal.ZERO, BigDecimal::add);
+ penaltyPaid = getLoanTransactionToRepaymentScheduleMappings().stream()
+ .map(mapping -> Optional.ofNullable(mapping.getPenaltyChargesPortion()).orElse(BigDecimal.ZERO))
+ .reduce(BigDecimal.ZERO, BigDecimal::add);
+ }
+ thisTransactionData.put("principalPaid", principalPaid);
+ thisTransactionData.put("feePaid", feePaid);
+ thisTransactionData.put("penaltyPaid", penaltyPaid);
+ }
+
LoanTransactionRelation loanTransactionRelation = loanTransactionRelations.stream()
.filter(e -> LoanTransactionRelationTypeEnum.CHARGE_ADJUSTMENT.equals(e.getRelationType())).findAny().orElse(null);
if (loanTransactionRelation != null) {
diff --git a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/data/LoanTransactionDTO.java b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/data/LoanTransactionDTO.java
index bd9ebf2..07defb6 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/data/LoanTransactionDTO.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/data/LoanTransactionDTO.java
@@ -60,4 +60,9 @@
private final String chargeRefundChargeType;
private final LoanChargeData loanChargeData;
+
+ /** In case chargeback and overpayment the below field contains the distribution payment **/
+ private final BigDecimal principalPaid;
+ private final BigDecimal feePaid;
+ private final BigDecimal penaltyPaid;
}
diff --git a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccountingProcessorHelper.java b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccountingProcessorHelper.java
index 804184c..d3ca6da 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccountingProcessorHelper.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccountingProcessorHelper.java
@@ -156,9 +156,15 @@
isAccountTransfer = this.accountTransfersReadPlatformService.isAccountTransfer(Long.parseLong(transactionId),
PortfolioAccountType.LOAN);
}
+
+ BigDecimal principalPaid = (BigDecimal) map.get("principalPaid");
+ BigDecimal feePaid = (BigDecimal) map.get("feePaid");
+ BigDecimal penaltyPaid = (BigDecimal) map.get("penaltyPaid");
+
final LoanTransactionDTO transaction = new LoanTransactionDTO(transactionOfficeId, paymentTypeId, transactionId,
transactionDate, transactionType, amount, principal, interest, fees, penalties, overPayments, reversed,
- penaltyPaymentDetails, feePaymentDetails, isAccountTransfer, chargeRefundChargeType, loanChargeData);
+ penaltyPaymentDetails, feePaymentDetails, isAccountTransfer, chargeRefundChargeType, loanChargeData, principalPaid,
+ feePaid, penaltyPaid);
Boolean isLoanToLoanTransfer = (Boolean) accountingBridgeData.get("isLoanToLoanTransfer");
transaction.setLoanToLoanTransfer(isLoanToLoanTransfer != null && isLoanToLoanTransfer);
newLoanTransactions.add(transaction);
diff --git a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccrualBasedAccountingProcessorForLoan.java b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccrualBasedAccountingProcessorForLoan.java
index f0ed03e..d92657b 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccrualBasedAccountingProcessorForLoan.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/AccrualBasedAccountingProcessorForLoan.java
@@ -430,25 +430,54 @@
final BigDecimal overpaidAmount = Objects.isNull(loanTransactionDTO.getOverPayment()) ? BigDecimal.ZERO
: loanTransactionDTO.getOverPayment();
- if (BigDecimal.ZERO.compareTo(overpaidAmount) == 0) { // when no overpay
- helper.createJournalEntriesAndReversalsForLoan(office, currencyCode, AccrualAccountsForLoan.LOAN_PORTFOLIO.getValue(),
- AccrualAccountsForLoan.FUND_SOURCE.getValue(), loanProductId, paymentTypeId, loanId, transactionId, transactionDate,
- amount, isReversal);
- } else if (overpaidAmount.compareTo(amount) >= 0) { // when the overpay amount is matching with the normal
- // amount
- helper.createJournalEntriesAndReversalsForLoan(office, currencyCode, AccrualAccountsForLoan.OVERPAYMENT.getValue(),
- AccrualAccountsForLoan.FUND_SOURCE.getValue(), loanProductId, paymentTypeId, loanId, transactionId, transactionDate,
- amount, isReversal);
- } else {
- BigDecimal diff = amount.subtract(overpaidAmount);
- helper.createDebitJournalEntryOrReversalForLoan(office, currencyCode, AccrualAccountsForLoan.LOAN_PORTFOLIO.getValue(),
- loanProductId, paymentTypeId, loanId, transactionId, transactionDate, diff, isReversal);
- helper.createCreditJournalEntryOrReversalForLoan(office, currencyCode, AccrualAccountsForLoan.FUND_SOURCE, loanProductId,
- paymentTypeId, loanId, transactionId, transactionDate, amount, isReversal);
+ final BigDecimal principalCredited = Objects.isNull(loanTransactionDTO.getPrincipal()) ? BigDecimal.ZERO
+ : loanTransactionDTO.getPrincipal();
+ final BigDecimal feeCredited = Objects.isNull(loanTransactionDTO.getFees()) ? BigDecimal.ZERO : loanTransactionDTO.getFees();
+ final BigDecimal penaltyCredited = Objects.isNull(loanTransactionDTO.getPenalties()) ? BigDecimal.ZERO
+ : loanTransactionDTO.getPenalties();
+
+ final BigDecimal principalPaid = Objects.isNull(loanTransactionDTO.getPrincipalPaid()) ? BigDecimal.ZERO
+ : loanTransactionDTO.getPrincipalPaid();
+ final BigDecimal feePaid = Objects.isNull(loanTransactionDTO.getFeePaid()) ? BigDecimal.ZERO : loanTransactionDTO.getFeePaid();
+ final BigDecimal penaltyPaid = Objects.isNull(loanTransactionDTO.getPenaltyPaid()) ? BigDecimal.ZERO
+ : loanTransactionDTO.getPenaltyPaid();
+
+ helper.createCreditJournalEntryOrReversalForLoan(office, currencyCode, AccrualAccountsForLoan.FUND_SOURCE, loanProductId,
+ paymentTypeId, loanId, transactionId, transactionDate, amount, isReversal);
+
+ if (overpaidAmount.compareTo(BigDecimal.ZERO) > 0) {
helper.createDebitJournalEntryOrReversalForLoan(office, currencyCode, AccrualAccountsForLoan.OVERPAYMENT.getValue(),
loanProductId, paymentTypeId, loanId, transactionId, transactionDate, overpaidAmount, isReversal);
}
+ if (principalCredited.compareTo(principalPaid) > 0) {
+ helper.createDebitJournalEntryOrReversalForLoan(office, currencyCode, AccrualAccountsForLoan.LOAN_PORTFOLIO.getValue(),
+ loanProductId, paymentTypeId, loanId, transactionId, transactionDate, principalCredited.subtract(principalPaid),
+ isReversal);
+ } else if (principalCredited.compareTo(principalPaid) < 0) {
+ helper.createCreditJournalEntryOrReversalForLoan(office, currencyCode, AccrualAccountsForLoan.LOAN_PORTFOLIO.getValue(),
+ loanProductId, paymentTypeId, loanId, transactionId, transactionDate, principalPaid.subtract(principalCredited),
+ isReversal);
+ }
+
+ if (feeCredited.compareTo(feePaid) > 0) {
+ helper.createDebitJournalEntryOrReversalForLoan(office, currencyCode, AccrualAccountsForLoan.FEES_RECEIVABLE.getValue(),
+ loanProductId, paymentTypeId, loanId, transactionId, transactionDate, feeCredited.subtract(feePaid), isReversal);
+ } else if (feeCredited.compareTo(feePaid) < 0) {
+ helper.createCreditJournalEntryOrReversalForLoan(office, currencyCode, AccrualAccountsForLoan.FEES_RECEIVABLE.getValue(),
+ loanProductId, paymentTypeId, loanId, transactionId, transactionDate, feePaid.subtract(feeCredited), isReversal);
+ }
+
+ if (penaltyCredited.compareTo(penaltyPaid) > 0) {
+ helper.createDebitJournalEntryOrReversalForLoan(office, currencyCode, AccrualAccountsForLoan.PENALTIES_RECEIVABLE.getValue(),
+ loanProductId, paymentTypeId, loanId, transactionId, transactionDate, penaltyCredited.subtract(penaltyPaid),
+ isReversal);
+ } else if (penaltyCredited.compareTo(penaltyPaid) < 0) {
+ helper.createCreditJournalEntryOrReversalForLoan(office, currencyCode, AccrualAccountsForLoan.PENALTIES_RECEIVABLE.getValue(),
+ loanProductId, paymentTypeId, loanId, transactionId, transactionDate, penaltyPaid.subtract(penaltyCredited),
+ isReversal);
+ }
+
}
/**
diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/AdvancedPaymentAllocationLoanRepaymentScheduleTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/AdvancedPaymentAllocationLoanRepaymentScheduleTest.java
index d6cb8f4..aa1bd5e 100644
--- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/AdvancedPaymentAllocationLoanRepaymentScheduleTest.java
+++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/AdvancedPaymentAllocationLoanRepaymentScheduleTest.java
@@ -3194,13 +3194,13 @@
);
// verify journal entries
verifyJournalEntries(loanResponse.getLoanId(), journalEntry(100.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(100.0, suspenseClearingAccount, "CREDIT"), //
+ journalEntry(100.0, fundSource, "CREDIT"), //
journalEntry(100.0, loansReceivableAccount, "CREDIT"), //
journalEntry(50.0, overpaymentAccount, "CREDIT"), //
- journalEntry(150.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(150.0, fundSource, "DEBIT"), //
journalEntry(50.0, loansReceivableAccount, "DEBIT"), //
journalEntry(50.0, overpaymentAccount, "DEBIT"), //
- journalEntry(100.0, suspenseClearingAccount, "CREDIT") //
+ journalEntry(100.0, fundSource, "CREDIT") //
);
});
}
@@ -3273,12 +3273,12 @@
);
// verify journal entries
verifyJournalEntries(loanResponse.getLoanId(), journalEntry(100.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(100.0, suspenseClearingAccount, "CREDIT"), //
+ journalEntry(100.0, fundSource, "CREDIT"), //
journalEntry(100.0, loansReceivableAccount, "CREDIT"), //
journalEntry(50.0, overpaymentAccount, "CREDIT"), //
- journalEntry(150.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(150.0, fundSource, "DEBIT"), //
journalEntry(28.0, overpaymentAccount, "DEBIT"), //
- journalEntry(28.0, suspenseClearingAccount, "CREDIT") //
+ journalEntry(28.0, fundSource, "CREDIT") //
);
});
}
diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/BaseLoanIntegrationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/BaseLoanIntegrationTest.java
index fc4aaf2..bcd50f5 100644
--- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/BaseLoanIntegrationTest.java
+++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/BaseLoanIntegrationTest.java
@@ -72,6 +72,7 @@
import org.apache.fineract.integrationtests.common.BusinessDateHelper;
import org.apache.fineract.integrationtests.common.ClientHelper;
import org.apache.fineract.integrationtests.common.GlobalConfigurationHelper;
+import org.apache.fineract.integrationtests.common.SchedulerJobHelper;
import org.apache.fineract.integrationtests.common.Utils;
import org.apache.fineract.integrationtests.common.accounting.Account;
import org.apache.fineract.integrationtests.common.accounting.AccountHelper;
@@ -114,6 +115,7 @@
protected final LoanProductHelper loanProductHelper = new LoanProductHelper();
protected JournalEntryHelper journalEntryHelper = new JournalEntryHelper(requestSpec, responseSpec);
protected ClientHelper clientHelper = new ClientHelper(requestSpec, responseSpec);
+ protected SchedulerJobHelper schedulerJobHelper = new SchedulerJobHelper(requestSpec);
protected final InlineLoanCOBHelper inlineLoanCOBHelper = new InlineLoanCOBHelper(requestSpec, responseSpec);
protected BusinessDateHelper businessDateHelper = new BusinessDateHelper();
@@ -123,18 +125,22 @@
protected DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(DATETIME_PATTERN);
// asset
- protected final Account loansReceivableAccount = accountHelper.createAssetAccount();
- protected final Account interestFeeReceivableAccount = accountHelper.createAssetAccount();
- protected final Account suspenseAccount = accountHelper.createAssetAccount();
+ protected final Account loansReceivableAccount = accountHelper.createAssetAccount("loanPortfolio");
+
+ protected final Account interestReceivableAccount = accountHelper.createAssetAccount("interestReceivable");
+ protected final Account feeReceivableAccount = accountHelper.createAssetAccount("feeReceivable");
+ protected final Account penaltyReceivableAccount = accountHelper.createAssetAccount("penaltyReceivable");
+ protected final Account suspenseAccount = accountHelper.createAssetAccount("suspense");
// liability
- protected final Account suspenseClearingAccount = accountHelper.createLiabilityAccount();
- protected final Account overpaymentAccount = accountHelper.createLiabilityAccount();
+ protected final Account fundSource = accountHelper.createLiabilityAccount("fundSource");
+ protected final Account overpaymentAccount = accountHelper.createLiabilityAccount("overpayment");
// income
- protected final Account interestIncomeAccount = accountHelper.createIncomeAccount();
- protected final Account feeIncomeAccount = accountHelper.createIncomeAccount();
- protected final Account feeChargeOffAccount = accountHelper.createIncomeAccount();
- protected final Account recoveriesAccount = accountHelper.createIncomeAccount();
- protected final Account interestIncomeChargeOffAccount = accountHelper.createIncomeAccount();
+ protected final Account interestIncomeAccount = accountHelper.createIncomeAccount("interestIncome");
+ protected final Account feeIncomeAccount = accountHelper.createIncomeAccount("feeIncome");
+ protected final Account penaltyIncomeAccount = accountHelper.createIncomeAccount("penaltyIncome");
+ protected final Account feeChargeOffAccount = accountHelper.createIncomeAccount("feeChargeOff");
+ protected final Account recoveriesAccount = accountHelper.createIncomeAccount("recoveries");
+ protected final Account interestIncomeChargeOffAccount = accountHelper.createIncomeAccount("interestIncomeChargeOff");
// expense
protected final Account creditLossBadDebtAccount = accountHelper.createExpenseAccount();
protected final Account creditLossBadDebtFraudAccount = accountHelper.createExpenseAccount();
@@ -159,6 +165,7 @@
.includeInBorrowerCycle(false)//
.currencyCode("USD")//
.digitsAfterDecimal(2)//
+ .inMultiplesOf(0)//
.installmentAmountInMultiplesOf(1)//
.useBorrowerCycle(false)//
.minPrincipal(100.0)//
@@ -207,24 +214,18 @@
.outstandingLoanBalance(10000.0)//
.charges(Collections.emptyList())//
.accountingRule(3)//
- .fundSourceAccountId(suspenseClearingAccount.getAccountID().longValue())//
+ .fundSourceAccountId(fundSource.getAccountID().longValue())//
.loanPortfolioAccountId(loansReceivableAccount.getAccountID().longValue())//
.transfersInSuspenseAccountId(suspenseAccount.getAccountID().longValue())//
.interestOnLoanAccountId(interestIncomeAccount.getAccountID().longValue())//
.incomeFromFeeAccountId(feeIncomeAccount.getAccountID().longValue())//
- .incomeFromPenaltyAccountId(feeIncomeAccount.getAccountID().longValue())//
+ .incomeFromPenaltyAccountId(penaltyIncomeAccount.getAccountID().longValue())//
.incomeFromRecoveryAccountId(recoveriesAccount.getAccountID().longValue())//
.writeOffAccountId(writtenOffAccount.getAccountID().longValue())//
.overpaymentLiabilityAccountId(overpaymentAccount.getAccountID().longValue())//
- .receivableInterestAccountId(interestFeeReceivableAccount.getAccountID().longValue())//
- .receivableFeeAccountId(interestFeeReceivableAccount.getAccountID().longValue())//
- .receivablePenaltyAccountId(interestFeeReceivableAccount.getAccountID().longValue())//
- .dateFormat(DATETIME_PATTERN)//
- .locale("en_GB")//
- .disallowExpectedDisbursements(true)//
- .allowApprovedDisbursedAmountsOverApplied(true)//
- .overAppliedCalculationType("percentage")//
- .overAppliedNumber(50)//
+ .receivableInterestAccountId(interestReceivableAccount.getAccountID().longValue())//
+ .receivableFeeAccountId(feeReceivableAccount.getAccountID().longValue())//
+ .receivablePenaltyAccountId(penaltyReceivableAccount.getAccountID().longValue())//
.goodwillCreditAccountId(goodwillExpenseAccount.getAccountID().longValue())//
.incomeFromGoodwillCreditInterestAccountId(interestIncomeChargeOffAccount.getAccountID().longValue())//
.incomeFromGoodwillCreditFeesAccountId(feeChargeOffAccount.getAccountID().longValue())//
@@ -233,7 +234,12 @@
.incomeFromChargeOffFeesAccountId(feeChargeOffAccount.getAccountID().longValue())//
.chargeOffExpenseAccountId(creditLossBadDebtAccount.getAccountID().longValue())//
.chargeOffFraudExpenseAccountId(creditLossBadDebtFraudAccount.getAccountID().longValue())//
- .incomeFromChargeOffPenaltyAccountId(feeChargeOffAccount.getAccountID().longValue());
+ .incomeFromChargeOffPenaltyAccountId(feeChargeOffAccount.getAccountID().longValue()).dateFormat(DATETIME_PATTERN)//
+ .locale("en_GB")//
+ .disallowExpectedDisbursements(true)//
+ .allowApprovedDisbursedAmountsOverApplied(true)//
+ .overAppliedCalculationType("percentage")//
+ .overAppliedNumber(50);
}
protected PostLoanProductsRequest createOnePeriod30DaysLongNoInterestPeriodicAccrualProductWithAdvancedPaymentAllocation() {
@@ -344,7 +350,7 @@
boolean found = loanDetails.getTransactions().stream().anyMatch(item -> Objects.equals(item.getAmount(), tr.amount) //
&& Objects.equals(item.getType().getValue(), tr.type) //
&& Objects.equals(item.getDate(), LocalDate.parse(tr.date, dateTimeFormatter)) //
- && Objects.equals(item.getOutstandingLoanBalance(), tr.outstandingAmount) //
+ && Objects.equals(item.getOutstandingLoanBalance(), tr.outstandingPrincipal) //
&& Objects.equals(item.getPrincipalPortion(), tr.principalPortion) //
&& Objects.equals(item.getInterestPortion(), tr.interestPortion) //
&& Objects.equals(item.getFeeChargesPortion(), tr.feePortion) //
@@ -416,6 +422,18 @@
});
}
+ protected void verifyTRJournalEntries(Long transactionId, Journal... entries) {
+ GetJournalEntriesTransactionIdResponse journalEntriesForLoan = journalEntryHelper.getJournalEntries("L" + transactionId.toString());
+ Assertions.assertEquals(entries.length, journalEntriesForLoan.getPageItems().size());
+ Arrays.stream(entries).forEach(journalEntry -> {
+ boolean found = journalEntriesForLoan.getPageItems().stream()
+ .anyMatch(item -> Objects.equals(item.getAmount(), journalEntry.amount)
+ && Objects.equals(item.getGlAccountId(), journalEntry.account.getAccountID().longValue())
+ && Objects.requireNonNull(item.getEntryType()).getValue().equals(journalEntry.type));
+ Assertions.assertTrue(found, "Required journal entry not found: " + journalEntry);
+ });
+ }
+
protected Long addCharge(Long loanId, boolean isPenalty, double amount, String dueDate) {
Integer chargeId = ChargesHelper.createCharges(requestSpec, responseSpec,
ChargesHelper.getLoanSpecifiedDueDateJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_FLAT, String.valueOf(amount), isPenalty));
@@ -602,9 +620,10 @@
return response.getResourceId();
}
- protected void addChargebackForLoan(Long loanId, Long transactionId, Double amount) {
- loanTransactionHelper.chargebackLoanTransaction(loanId, transactionId,
+ protected Long addChargebackForLoan(Long loanId, Long transactionId, Double amount) {
+ PostLoansLoanIdTransactionsResponse response = loanTransactionHelper.chargebackLoanTransaction(loanId, transactionId,
new PostLoansLoanIdTransactionsTransactionIdRequest().locale("en").transactionAmount(amount).paymentTypeId(1L));
+ return response.getResourceId();
}
protected PostChargesResponse createCharge(Double amount) {
@@ -627,8 +646,22 @@
new BusinessDateRequest().type(BUSINESS_DATE.getName()).date(date).dateFormat(DATETIME_PATTERN).locale("en"));
}
- protected Journal journalEntry(double principalAmount, Account account, String type) {
- return new Journal(principalAmount, account, type);
+ protected Long getTransactionId(Long loanId, String type, String date) {
+ GetLoansLoanIdResponse loan = loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId.intValue());
+ return loan.getTransactions().stream().filter(tr -> Objects.equals(tr.getType().getValue(), type)
+ && Objects.equals(tr.getDate(), LocalDate.parse(date, dateTimeFormatter))).findAny().orElseThrow().getId();
+ }
+
+ protected Journal journalEntry(double amount, Account account, String type) {
+ return new Journal(amount, account, type);
+ }
+
+ protected Journal debit(Account account, double amount) {
+ return new Journal(amount, account, "DEBIT");
+ }
+
+ protected Journal credit(Account account, double amount) {
+ return new Journal(amount, account, "CREDIT");
}
protected Transaction transaction(double principalAmount, String type, String date) {
@@ -639,16 +672,16 @@
return new Transaction(principalAmount, type, date, true);
}
- protected TransactionExt transaction(double amount, String type, String date, double outstandingAmount, double principalPortion,
+ protected TransactionExt transaction(double amount, String type, String date, double outstandingPrincipal, double principalPortion,
double interestPortion, double feePortion, double penaltyPortion, double unrecognizedIncomePortion, double overpaymentPortion) {
- return new TransactionExt(amount, type, date, outstandingAmount, principalPortion, interestPortion, feePortion, penaltyPortion,
+ return new TransactionExt(amount, type, date, outstandingPrincipal, principalPortion, interestPortion, feePortion, penaltyPortion,
unrecognizedIncomePortion, overpaymentPortion, false);
}
- protected TransactionExt transaction(double amount, String type, String date, double outstandingAmount, double principalPortion,
+ protected TransactionExt transaction(double amount, String type, String date, double outstandingPrincipal, double principalPortion,
double interestPortion, double feePortion, double penaltyPortion, double unrecognizedIncomePortion, double overpaymentPortion,
boolean reversed) {
- return new TransactionExt(amount, type, date, outstandingAmount, principalPortion, interestPortion, feePortion, penaltyPortion,
+ return new TransactionExt(amount, type, date, outstandingPrincipal, principalPortion, interestPortion, feePortion, penaltyPortion,
unrecognizedIncomePortion, overpaymentPortion, reversed);
}
@@ -765,7 +798,7 @@
Double amount;
String type;
String date;
- Double outstandingAmount;
+ Double outstandingPrincipal;
Double principalPortion;
Double interestPortion;
Double feePortion;
diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanChargebackWithCreditAllocationsIntegrationTests.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanChargebackWithCreditAllocationsIntegrationTests.java
index 63ae1b1..ccb3e1a 100644
--- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanChargebackWithCreditAllocationsIntegrationTests.java
+++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanChargebackWithCreditAllocationsIntegrationTests.java
@@ -1011,6 +1011,455 @@
});
}
+ @Test
+ public void testAccountingChargebackOnPrincipal() {
+ runAt("01 January 2023", () -> {
+ // Create Client
+ Long clientId = clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId();
+ // Create Loan Product
+ Long loanProductId = createLoanProduct(//
+ createDefaultPaymentAllocation(), //
+ chargebackAllocation("PENALTY", "FEE", "INTEREST", "PRINCIPAL")//
+ );
+ // Apply and Approve Loan
+ Long loanId = applyAndApproveLoan(clientId, loanProductId, 3);
+
+ // Disburse Loan
+ disburseLoan(loanId, BigDecimal.valueOf(750), "01 January 2023");
+
+ verifyRepaymentSchedule(loanId, //
+ installment(0, null, "01 January 2023"), //
+ installment(250.0, 0, 0, 0, 250.0, false, "01 February 2023"), //
+ installment(250.0, 0, 0, 0, 250.0, false, "01 March 2023"), //
+ installment(250.0, 0, 0, 0, 250.0, false, "01 April 2023") //
+ );
+
+ // Repayment #1
+ updateBusinessDate("01 February 2023");
+ Long repaymentTransaction1 = addRepaymentForLoan(loanId, 250.0, "01 February 2023");
+
+ // Repayment #2
+ updateBusinessDate("01 March 2023");
+ Long repaymentTransaction2 = addRepaymentForLoan(loanId, 250.0, "01 March 2023");
+
+ // Repayment #3
+ updateBusinessDate("30 March 2023");
+ Long repaymentTransaction3 = addRepaymentForLoan(loanId, 250.0, "30 March 2023");
+
+ // Chargeback 250
+ Long chargeback = addChargebackForLoan(loanId, repaymentTransaction2, 250.0);
+
+ verifyTransactions(loanId, //
+ transaction(750.0, "Disbursement", "01 January 2023", 750.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
+ transaction(250.0, "Repayment", "01 February 2023", 500.0, 250.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
+ transaction(250.0, "Repayment", "01 March 2023", 250.0, 250.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
+ transaction(250.0, "Repayment", "30 March 2023", 0.0, 250.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
+ transaction(250.0, "Chargeback", "30 March 2023", 250, 250.0, 0.0, 0.0, 0.0, 0.0, 0.0) //
+ );
+
+ // Verify GL entries
+ verifyTRJournalEntries(repaymentTransaction1, //
+ debit(fundSource, 250), //
+ credit(loansReceivableAccount, 250)//
+ );
+
+ verifyTRJournalEntries(repaymentTransaction2, //
+ debit(fundSource, 250), //
+ credit(loansReceivableAccount, 250) //
+ );
+
+ verifyTRJournalEntries(repaymentTransaction3, //
+ debit(fundSource, 250), //
+ credit(loansReceivableAccount, 250)//
+ );
+
+ verifyTRJournalEntries(chargeback, //
+ debit(loansReceivableAccount, 250), //
+ credit(fundSource, 250) //
+ );
+
+ });
+ }
+
+ @Test
+ public void testAccountingChargebackOnPrincipalAndFees() {
+ runAt("01 January 2023", () -> {
+ // Create Client
+ Long clientId = clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId();
+ // Create Loan Product
+ Long loanProductId = createLoanProduct(//
+ createDefaultPaymentAllocation(), //
+ chargebackAllocation("PENALTY", "FEE", "INTEREST", "PRINCIPAL")//
+ );
+ // Apply and Approve Loan
+ Long loanId = applyAndApproveLoan(clientId, loanProductId, 3);
+
+ // Disburse Loan
+ disburseLoan(loanId, BigDecimal.valueOf(750), "01 January 2023");
+
+ Long feeId = addCharge(loanId, false, 30, "15 February 2023");
+
+ verifyRepaymentSchedule(loanId, //
+ installment(0, null, "01 January 2023"), //
+ installment(250.0, 0, 0, 0, 250.0, false, "01 February 2023"), //
+ installment(250.0, 0, 30, 0, 280.0, false, "01 March 2023"), //
+ installment(250.0, 0, 0, 0, 250.0, false, "01 April 2023") //
+ );
+
+ // Repayment #1
+ updateBusinessDate("01 February 2023");
+ Long repaymentTransaction1 = addRepaymentForLoan(loanId, 250.0, "01 February 2023");
+
+ // Repayment #2
+ updateBusinessDate("01 March 2023");
+ Long repaymentTransaction2 = addRepaymentForLoan(loanId, 280.0, "01 March 2023");
+
+ // Run periodic accrual
+ schedulerJobHelper.executeAndAwaitJob("Add Accrual Transactions");
+
+ // Repayment #3
+ updateBusinessDate("30 March 2023");
+ Long repaymentTransaction3 = addRepaymentForLoan(loanId, 250.0, "30 March 2023");
+
+ // Chargeback 250
+ Long chargeback = addChargebackForLoan(loanId, repaymentTransaction2, 280.0);
+
+ verifyTransactions(loanId, //
+ transaction(750.0, "Disbursement", "01 January 2023", 750.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
+ transaction(250.0, "Repayment", "01 February 2023", 500.0, 250.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
+ transaction(280.0, "Repayment", "01 March 2023", 250.0, 250.0, 0.0, 30.0, 0.0, 0.0, 0.0), //
+ transaction(30.0, "Accrual", "01 March 2023", 0.0, 0.0, 0.0, 30.0, 0.0, 0.0, 0.0), //
+ transaction(250.0, "Repayment", "30 March 2023", 0.0, 250.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
+ transaction(280.0, "Chargeback", "30 March 2023", 250, 250.0, 0.0, 30.0, 0.0, 0.0, 0.0) //
+ );
+
+ // Verify GL entries
+ verifyTRJournalEntries(repaymentTransaction1, //
+ debit(fundSource, 250), //
+ credit(loansReceivableAccount, 250) //
+ );
+
+ verifyTRJournalEntries(repaymentTransaction2, //
+ debit(fundSource, 280), //
+ credit(loansReceivableAccount, 250), //
+ credit(feeReceivableAccount, 30)//
+ );
+
+ verifyTRJournalEntries(repaymentTransaction3, //
+ debit(fundSource, 250), //
+ credit(loansReceivableAccount, 250)//
+ );
+
+ verifyTRJournalEntries(chargeback, //
+ debit(loansReceivableAccount, 250), //
+ debit(feeReceivableAccount, 30), //
+ credit(fundSource, 280) //
+ );
+
+ });
+ }
+
+ @Test
+ public void testAccountingChargebackOnPrincipalAndPenalties() {
+ runAt("01 January 2023", () -> {
+ // Create Client
+ Long clientId = clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId();
+ // Create Loan Product
+ Long loanProductId = createLoanProduct(//
+ createDefaultPaymentAllocation(), //
+ chargebackAllocation("PENALTY", "FEE", "INTEREST", "PRINCIPAL")//
+ );
+ // Apply and Approve Loan
+ Long loanId = applyAndApproveLoan(clientId, loanProductId, 3);
+
+ // Disburse Loan
+ disburseLoan(loanId, BigDecimal.valueOf(750), "01 January 2023");
+
+ Long feeId = addCharge(loanId, true, 30, "15 February 2023");
+
+ verifyRepaymentSchedule(loanId, //
+ installment(0, null, "01 January 2023"), //
+ installment(250.0, 0, 0, 0, 250.0, false, "01 February 2023"), //
+ installment(250.0, 0, 0, 30.0, 280.0, false, "01 March 2023"), //
+ installment(250.0, 0, 0, 0, 250.0, false, "01 April 2023") //
+ );
+
+ // Repayment #1
+ updateBusinessDate("01 February 2023");
+ Long repaymentTransaction1 = addRepaymentForLoan(loanId, 250.0, "01 February 2023");
+
+ // Repayment #2
+ updateBusinessDate("01 March 2023");
+ Long repaymentTransaction2 = addRepaymentForLoan(loanId, 280.0, "01 March 2023");
+
+ // Run periodic accrual
+ schedulerJobHelper.executeAndAwaitJob("Add Accrual Transactions");
+
+ // Repayment #3
+ updateBusinessDate("30 March 2023");
+ Long repaymentTransaction3 = addRepaymentForLoan(loanId, 250.0, "30 March 2023");
+
+ // Chargeback 250
+ Long chargeback = addChargebackForLoan(loanId, repaymentTransaction2, 280.0);
+
+ verifyTransactions(loanId, //
+ transaction(750.0, "Disbursement", "01 January 2023", 750.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
+ transaction(250.0, "Repayment", "01 February 2023", 500.0, 250.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
+ transaction(280.0, "Repayment", "01 March 2023", 250.0, 250.0, 0.0, 0.0, 30.0, 0.0, 0.0), //
+ transaction(30.0, "Accrual", "01 March 2023", 0.0, 0.0, 0.0, 0.0, 30.0, 0.0, 0.0), //
+ transaction(250.0, "Repayment", "30 March 2023", 0.0, 250.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
+ transaction(280.0, "Chargeback", "30 March 2023", 250, 250.0, 0.0, 0.0, 30.0, 0.0, 0.0) //
+ );
+
+ // Verify GL entries
+ verifyTRJournalEntries(repaymentTransaction1, //
+ debit(fundSource, 250), //
+ credit(loansReceivableAccount, 250) //
+ );
+
+ verifyTRJournalEntries(repaymentTransaction2, //
+ debit(fundSource, 280), //
+ credit(loansReceivableAccount, 250), //
+ credit(penaltyReceivableAccount, 30)//
+ );
+
+ verifyTRJournalEntries(repaymentTransaction3, //
+ debit(fundSource, 250), //
+ credit(loansReceivableAccount, 250)//
+ );
+
+ verifyTRJournalEntries(chargeback, //
+ debit(loansReceivableAccount, 250), //
+ debit(penaltyReceivableAccount, 30), //
+ credit(fundSource, 280) //
+ );
+
+ });
+ }
+
+ @Test
+ public void testAccountingOverpaymentAmountIsSmallerThanChargeback() {
+ runAt("01 January 2023", () -> {
+ // Create Client
+ Long clientId = clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId();
+ // Create Loan Product
+ Long loanProductId = createLoanProduct(//
+ createDefaultPaymentAllocation(), //
+ chargebackAllocation("PENALTY", "FEE", "INTEREST", "PRINCIPAL")//
+ );
+ // Apply and Approve Loan
+ Long loanId = applyAndApproveLoan(clientId, loanProductId, 3);
+
+ // Disburse Loan
+ disburseLoan(loanId, BigDecimal.valueOf(750), "01 January 2023");
+
+ verifyRepaymentSchedule(loanId, //
+ installment(0, null, "01 January 2023"), //
+ installment(250.0, 0, 0, 0, 250.0, false, "01 February 2023"), //
+ installment(250.0, 0, 0, 0, 250.0, false, "01 March 2023"), //
+ installment(250.0, 0, 0, 0, 250.0, false, "01 April 2023") //
+ );
+
+ // Repayment #1
+ updateBusinessDate("01 February 2023");
+ Long repaymentTransaction1 = addRepaymentForLoan(loanId, 250.0, "01 February 2023");
+
+ // Repayment #2
+ updateBusinessDate("01 March 2023");
+ Long repaymentTransaction2 = addRepaymentForLoan(loanId, 250.0, "01 March 2023");
+
+ // Repayment #3
+ updateBusinessDate("30 March 2023");
+ Long repaymentTransaction3 = addRepaymentForLoan(loanId, 400.0, "30 March 2023");
+
+ // Chargeback 250
+ updateBusinessDate("31 March 2023");
+ Long chargeback = addChargebackForLoan(loanId, repaymentTransaction2, 250.0);
+
+ verifyTransactions(loanId, //
+ transaction(750.0, "Disbursement", "01 January 2023", 750.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
+ transaction(250.0, "Repayment", "01 February 2023", 500.0, 250.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
+ transaction(250.0, "Repayment", "01 March 2023", 250.0, 250.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
+ transaction(400.0, "Repayment", "30 March 2023", 0.0, 250.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
+ transaction(250.0, "Chargeback", "31 March 2023", 100, 250.0, 0.0, 0.0, 0.0, 0.0, 150.0) //
+ );
+
+ // Verify GL entries
+ verifyTRJournalEntries(repaymentTransaction1, //
+ debit(fundSource, 250), //
+ credit(loansReceivableAccount, 250) //
+ );
+
+ verifyTRJournalEntries(repaymentTransaction2, //
+ debit(fundSource, 250), //
+ credit(loansReceivableAccount, 250) //
+ );
+
+ verifyTRJournalEntries(repaymentTransaction3, //
+ debit(fundSource, 400), //
+ credit(loansReceivableAccount, 250), //
+ credit(overpaymentAccount, 150) //
+ );
+
+ verifyTRJournalEntries(chargeback, //
+ debit(loansReceivableAccount, 100), //
+ debit(overpaymentAccount, 150), //
+ credit(fundSource, 250) //
+ );
+ });
+ }
+
+ @Test
+ public void testAccountingOverpaymentAmountIsBiggerThanChargeback() {
+ runAt("01 January 2023", () -> {
+ // Create Client
+ Long clientId = clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId();
+ // Create Loan Product
+ Long loanProductId = createLoanProduct(//
+ createDefaultPaymentAllocation(), //
+ chargebackAllocation("PENALTY", "FEE", "INTEREST", "PRINCIPAL")//
+ );
+ // Apply and Approve Loan
+ Long loanId = applyAndApproveLoan(clientId, loanProductId, 3);
+
+ // Disburse Loan
+ disburseLoan(loanId, BigDecimal.valueOf(750), "01 January 2023");
+
+ verifyRepaymentSchedule(loanId, //
+ installment(0, null, "01 January 2023"), //
+ installment(250.0, 0, 0, 0, 250.0, false, "01 February 2023"), //
+ installment(250.0, 0, 0, 0, 250.0, false, "01 March 2023"), //
+ installment(250.0, 0, 0, 0, 250.0, false, "01 April 2023") //
+ );
+
+ // Repayment #1
+ updateBusinessDate("01 February 2023");
+ Long repaymentTransaction1 = addRepaymentForLoan(loanId, 250.0, "01 February 2023");
+
+ // Repayment #2
+ updateBusinessDate("01 March 2023");
+ Long repaymentTransaction2 = addRepaymentForLoan(loanId, 250.0, "01 March 2023");
+
+ // Repayment #3
+ updateBusinessDate("30 March 2023");
+ Long repaymentTransaction3 = addRepaymentForLoan(loanId, 400.0, "30 March 2023");
+
+ // Chargeback 250
+ updateBusinessDate("31 March 2023");
+ Long chargeback = addChargebackForLoan(loanId, repaymentTransaction2, 100.0);
+
+ verifyTransactions(loanId, //
+ transaction(750.0, "Disbursement", "01 January 2023", 750.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
+ transaction(250.0, "Repayment", "01 February 2023", 500.0, 250.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
+ transaction(250.0, "Repayment", "01 March 2023", 250.0, 250.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
+ transaction(400.0, "Repayment", "30 March 2023", 0.0, 250.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
+ transaction(100.0, "Chargeback", "31 March 2023", 0.0, 100.0, 0.0, 0.0, 0.0, 0.0, -50.0) //
+ );
+
+ // Verify GL entries
+ verifyTRJournalEntries(repaymentTransaction1, //
+ debit(fundSource, 250), //
+ credit(loansReceivableAccount, 250) //
+ );
+
+ verifyTRJournalEntries(repaymentTransaction2, //
+ debit(fundSource, 250), //
+ credit(loansReceivableAccount, 250) //
+ );
+
+ verifyTRJournalEntries(repaymentTransaction3, //
+ debit(fundSource, 400), //
+ credit(loansReceivableAccount, 250), //
+ credit(overpaymentAccount, 150) //
+ );
+
+ verifyTRJournalEntries(chargeback, //
+ debit(overpaymentAccount, 100), //
+ credit(fundSource, 100) //
+ );
+ });
+ }
+
+ @Test
+ public void testAccountingOverpaidLoansWithFeesWhenOverpaymentAmountIsBiggerThanChargeback() {
+ runAt("01 January 2023", () -> {
+ // Create Client
+ Long clientId = clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId();
+ // Create Loan Product
+ Long loanProductId = createLoanProduct(//
+ createDefaultPaymentAllocation(), //
+ chargebackAllocation("PENALTY", "FEE", "INTEREST", "PRINCIPAL")//
+ );
+ // Apply and Approve Loan
+ Long loanId = applyAndApproveLoan(clientId, loanProductId, 3);
+
+ // Disburse Loan
+ disburseLoan(loanId, BigDecimal.valueOf(750), "01 January 2023");
+
+ verifyRepaymentSchedule(loanId, //
+ installment(0, null, "01 January 2023"), //
+ installment(250.0, 0, 0, 0, 250.0, false, "01 February 2023"), //
+ installment(250.0, 0, 0, 0, 250.0, false, "01 March 2023"), //
+ installment(250.0, 0, 0, 0, 250.0, false, "01 April 2023") //
+ );
+
+ // Repayment #1
+ updateBusinessDate("01 February 2023");
+ Long repaymentTransaction1 = addRepaymentForLoan(loanId, 250.0, "01 February 2023");
+
+ // Add fee & Repayment #2
+ updateBusinessDate("01 March 2023");
+ Long feeId = addCharge(loanId, false, 30, "01 March 2023");
+ Long repaymentTransaction2 = addRepaymentForLoan(loanId, 280.0, "01 March 2023");
+ schedulerJobHelper.executeAndAwaitJob("Add Accrual Transactions");
+
+ // Repayment #3
+ updateBusinessDate("30 March 2023");
+ Long repaymentTransaction3 = addRepaymentForLoan(loanId, 400.0, "30 March 2023");
+
+ // Chargeback 250
+ updateBusinessDate("31 March 2023");
+ Long chargeback = addChargebackForLoan(loanId, repaymentTransaction2, 100.0);
+
+ verifyTransactions(loanId, //
+ transaction(750.0, "Disbursement", "01 January 2023", 750.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
+ transaction(250.0, "Repayment", "01 February 2023", 500.0, 250.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
+ transaction(280.0, "Repayment", "01 March 2023", 250.0, 250.0, 0.0, 30.0, 0.0, 0.0, 0.0), //
+ transaction(30.0, "Accrual", "01 March 2023", 0.0, 0.0, 0.0, 30.0, 0.0, 0.0, 0.0), //
+ transaction(400.0, "Repayment", "30 March 2023", 0.0, 250.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
+ transaction(100.0, "Chargeback", "31 March 2023", 0.0, 70.0, 0.0, 30.0, 0.0, 0.0, -50.0) //
+ );
+
+ // Verify GL entries
+ verifyTRJournalEntries(repaymentTransaction1, //
+ debit(fundSource, 250), //
+ credit(loansReceivableAccount, 250) //
+ );
+
+ verifyTRJournalEntries(repaymentTransaction2, //
+ debit(fundSource, 280), //
+ credit(loansReceivableAccount, 250), //
+ credit(feeReceivableAccount, 30) //
+ );
+
+ verifyTRJournalEntries(getTransactionId(loanId, "Accrual", "01 March 2023"), //
+ debit(feeReceivableAccount, 30), //
+ credit(feeIncomeAccount, 30) //
+ );
+
+ verifyTRJournalEntries(repaymentTransaction3, //
+ debit(fundSource, 400), //
+ credit(loansReceivableAccount, 250), //
+ credit(overpaymentAccount, 150) //
+ );
+
+ verifyTRJournalEntries(chargeback, //
+ debit(overpaymentAccount, 100), //
+ credit(fundSource, 100) //
+ );
+ });
+ }
+
private void verifyLoanSummaryAmounts(Long loanId, double creditedPrincipal, double creditedFee, double creditedPenalty,
double totalOutstanding) {
GetLoansLoanIdResponse loanResponse = loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId.intValue());
@@ -1023,10 +1472,10 @@
}
@Nullable
- private Long applyAndApproveLoan(Long clientId, Long loanProductId) {
- PostLoansRequest applicationRequest = applyLoanRequest(clientId, loanProductId, "01 January 2023", 1250.0, 4)//
+ private Long applyAndApproveLoan(Long clientId, Long loanProductId, int numberOfRepayments) {
+ PostLoansRequest applicationRequest = applyLoanRequest(clientId, loanProductId, "01 January 2023", 1250.0, numberOfRepayments)//
.repaymentEvery(1)//
- .loanTermFrequency(4)//
+ .loanTermFrequency(numberOfRepayments)//
.repaymentFrequencyType(RepaymentFrequencyType.MONTHS)//
.loanTermFrequencyType(RepaymentFrequencyType.MONTHS)//
.transactionProcessingStrategyCode("advanced-payment-allocation-strategy");
@@ -1036,8 +1485,12 @@
PostLoansLoanIdResponse approvedLoanResult = loanTransactionHelper.approveLoan(postLoansResponse.getResourceId(),
approveLoanRequest(1250.0, "01 January 2023"));
- Long loanId = approvedLoanResult.getLoanId();
- return loanId;
+ return approvedLoanResult.getLoanId();
+ }
+
+ @Nullable
+ private Long applyAndApproveLoan(Long clientId, Long loanProductId) {
+ return applyAndApproveLoan(clientId, loanProductId, 4);
}
public Long createLoanProduct(AdvancedPaymentData defaultAllocation, CreditAllocationData creditAllocationData) {
diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanDownPaymentTransactionChargebackTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanDownPaymentTransactionChargebackTest.java
index 17e05c2..2b8f7b0 100644
--- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanDownPaymentTransactionChargebackTest.java
+++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanDownPaymentTransactionChargebackTest.java
@@ -23,7 +23,6 @@
import static org.junit.jupiter.api.Assertions.assertNotNull;
import java.math.BigDecimal;
-import org.apache.fineract.client.models.GetJournalEntriesTransactionIdResponse;
import org.apache.fineract.client.models.GetLoanProductsProductIdResponse;
import org.apache.fineract.client.models.GetLoansLoanIdTransactionsTransactionIdResponse;
import org.apache.fineract.client.models.PostLoanProductsRequest;
@@ -88,15 +87,10 @@
);
// verify journal entries for chargeback transaction
- GetJournalEntriesTransactionIdResponse journalEntries = journalEntryHelper
- .getJournalEntries("L" + chargebackTransactionId.toString());
- assertEquals(2L, journalEntries.getTotalFilteredRecords());
- assertEquals(50.0, journalEntries.getPageItems().get(0).getAmount());
- assertEquals("CREDIT", journalEntries.getPageItems().get(0).getEntryType().getValue());
-
- assertEquals(50.0, journalEntries.getPageItems().get(1).getAmount());
- assertEquals("DEBIT", journalEntries.getPageItems().get(1).getEntryType().getValue());
-
+ verifyTRJournalEntries(chargebackTransactionId, //
+ credit(fundSource, 50.0), //
+ debit(loansReceivableAccount, 50.0) //
+ );
});
}
@@ -152,15 +146,10 @@
);
// verify journal entries for chargeback transaction
- GetJournalEntriesTransactionIdResponse journalEntries = journalEntryHelper
- .getJournalEntries("L" + chargebackTransactionId.toString());
- assertEquals(2L, journalEntries.getTotalFilteredRecords());
- assertEquals(50.0, journalEntries.getPageItems().get(0).getAmount());
- assertEquals("CREDIT", journalEntries.getPageItems().get(0).getEntryType().getValue());
-
- assertEquals(50.0, journalEntries.getPageItems().get(1).getAmount());
- assertEquals("DEBIT", journalEntries.getPageItems().get(1).getEntryType().getValue());
-
+ verifyTRJournalEntries(chargebackTransactionId, //
+ credit(fundSource, 50.0), //
+ debit(loansReceivableAccount, 50.0) //
+ );
});
}
diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRepaymentScheduleWithDownPaymentTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRepaymentScheduleWithDownPaymentTest.java
index d9cf82d..9ef2a6a 100644
--- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRepaymentScheduleWithDownPaymentTest.java
+++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRepaymentScheduleWithDownPaymentTest.java
@@ -1252,10 +1252,11 @@
transaction(1000.0, "Disbursement", "03 March 2023", 1000.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
transaction(250.0, "Down Payment", "03 March 2023", 750.0, 250.0, 0.0, 0.0, 0.0, 0.0, 0.0) //
);
- verifyJournalEntries(loanResponse.getResourceId(), journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(1000.0, suspenseClearingAccount, "CREDIT"), //
+ verifyJournalEntries(loanResponse.getResourceId(), //
+ journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
+ journalEntry(1000.0, fundSource, "CREDIT"), //
journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(250.0, suspenseClearingAccount, "DEBIT") //
+ journalEntry(250.0, fundSource, "DEBIT") //
);
loanTransactionHelper.makeLoanRepayment(loanResponse.getResourceId(), new PostLoansLoanIdTransactionsRequest()
@@ -1464,10 +1465,11 @@
transaction(1000.0, "Disbursement", "03 March 2023", 1000.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0), //
transaction(250.0, "Down Payment", "03 March 2023", 750.0, 250.0, 0.0, 0.0, 0.0, 0.0, 0.0) //
);
- verifyJournalEntries(loanResponse.getResourceId(), journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(1000.0, suspenseClearingAccount, "CREDIT"), //
+ verifyJournalEntries(loanResponse.getResourceId(), //
+ journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
+ journalEntry(1000.0, fundSource, "CREDIT"), //
journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(250.0, suspenseClearingAccount, "DEBIT") //
+ journalEntry(250.0, fundSource, "DEBIT") //
);
String externalId = UUID.randomUUID().toString();
diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRescheduleTestWithDownpayment.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRescheduleTestWithDownpayment.java
index d54a60d..450553f 100644
--- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRescheduleTestWithDownpayment.java
+++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRescheduleTestWithDownpayment.java
@@ -74,9 +74,9 @@
// verify journal entries
verifyJournalEntries(loanId, journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(250.0, fundSource, "DEBIT"), //
journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(1000.0, suspenseClearingAccount, "CREDIT") //
+ journalEntry(1000.0, fundSource, "CREDIT") //
);
// Verify Repayment Schedule
diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanTransactionChargebackTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanTransactionChargebackTest.java
index 635a6c2..0fb211c 100644
--- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanTransactionChargebackTest.java
+++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanTransactionChargebackTest.java
@@ -18,6 +18,7 @@
*/
package org.apache.fineract.integrationtests;
+import static org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder.ACCRUAL_PERIODIC;
import static org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder.DEFAULT_STRATEGY;
import static org.apache.fineract.portfolio.loanaccount.domain.transactionprocessor.impl.AdvancedPaymentScheduleTransactionProcessor.ADVANCED_PAYMENT_ALLOCATION_STRATEGY;
import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -39,7 +40,6 @@
import org.apache.fineract.client.models.AdvancedPaymentData;
import org.apache.fineract.client.models.GetDelinquencyBucketsResponse;
import org.apache.fineract.client.models.GetDelinquencyRangesResponse;
-import org.apache.fineract.client.models.GetJournalEntriesTransactionIdResponse;
import org.apache.fineract.client.models.GetLoanProductsProductIdResponse;
import org.apache.fineract.client.models.GetLoansLoanIdRepaymentPeriod;
import org.apache.fineract.client.models.GetLoansLoanIdRepaymentSchedule;
@@ -53,7 +53,6 @@
import org.apache.fineract.integrationtests.common.ClientHelper;
import org.apache.fineract.integrationtests.common.GlobalConfigurationHelper;
import org.apache.fineract.integrationtests.common.Utils;
-import org.apache.fineract.integrationtests.common.accounting.Account;
import org.apache.fineract.integrationtests.common.accounting.AccountHelper;
import org.apache.fineract.integrationtests.common.accounting.JournalEntryHelper;
import org.apache.fineract.integrationtests.common.loans.LoanApplicationTestBuilder;
@@ -72,7 +71,7 @@
@Slf4j
@ExtendWith(LoanTestLifecycleExtension.class)
-public class LoanTransactionChargebackTest {
+public class LoanTransactionChargebackTest extends BaseLoanIntegrationTest {
private ResponseSpecification responseSpec;
private ResponseSpecification responseSpecErr400;
@@ -139,14 +138,10 @@
loanTransactionHelper.validateLoanPrincipalOustandingBalance(getLoansLoanIdResponse, amount.doubleValue());
- GetJournalEntriesTransactionIdResponse journalEntries = journalEntryHelper
- .getJournalEntries("L" + chargebackTransactionId.toString());
- assertEquals(2L, journalEntries.getTotalFilteredRecords());
- assertEquals(1000.0, journalEntries.getPageItems().get(0).getAmount());
- assertEquals("CREDIT", journalEntries.getPageItems().get(0).getEntryType().getValue());
-
- assertEquals(1000.0, journalEntries.getPageItems().get(1).getAmount());
- assertEquals("DEBIT", journalEntries.getPageItems().get(1).getEntryType().getValue());
+ verifyTRJournalEntries(chargebackTransactionId, //
+ credit(fundSource, 1000.0), //
+ debit(loansReceivableAccount, 1000.0) //
+ );
// Try to reverse a Loan Transaction charge back
PostLoansLoanIdTransactionsResponse reverseTransactionResponse = loanTransactionHelper.reverseLoanTransaction(loanId,
@@ -431,17 +426,11 @@
assertEquals(getLoansLoanIdResponse.getTimeline().getExpectedMaturityDate(),
getLoansLoanIdResponse.getTimeline().getActualMaturityDate());
- GetJournalEntriesTransactionIdResponse journalEntries = journalEntryHelper
- .getJournalEntries("L" + chargebackTransactionId.toString());
- assertEquals(3L, journalEntries.getTotalFilteredRecords());
- assertEquals(100.0, journalEntries.getPageItems().get(0).getAmount());
- assertEquals("DEBIT", journalEntries.getPageItems().get(0).getEntryType().getValue());
-
- assertEquals(200.0, journalEntries.getPageItems().get(1).getAmount());
- assertEquals("CREDIT", journalEntries.getPageItems().get(1).getEntryType().getValue());
-
- assertEquals(100.0, journalEntries.getPageItems().get(2).getAmount());
- assertEquals("DEBIT", journalEntries.getPageItems().get(2).getEntryType().getValue());
+ verifyTRJournalEntries(chargebackTransactionId, //
+ credit(fundSource, 200.0), //
+ debit(loansReceivableAccount, 100.0), //
+ debit(overpaymentAccount, 100.0) //
+ );
final GetDelinquencyRangesResponse delinquencyRange = getLoansLoanIdResponse.getDelinquencyRange();
assertNull(delinquencyRange);
@@ -525,14 +514,10 @@
loanTransactionHelper.validateLoanPrincipalOustandingBalance(getLoansLoanIdResponse, Double.valueOf("0.00"));
- GetJournalEntriesTransactionIdResponse journalEntries = journalEntryHelper
- .getJournalEntries("L" + chargebackTransactionId.toString());
- assertEquals(2L, journalEntries.getTotalFilteredRecords());
- assertEquals(50.0, journalEntries.getPageItems().get(0).getAmount());
- assertEquals("CREDIT", journalEntries.getPageItems().get(0).getEntryType().getValue());
-
- assertEquals(50.0, journalEntries.getPageItems().get(1).getAmount());
- assertEquals("DEBIT", journalEntries.getPageItems().get(1).getEntryType().getValue());
+ verifyTRJournalEntries(chargebackTransactionId, //
+ credit(fundSource, 50.0), //
+ debit(overpaymentAccount, 50.0) //
+ );
}
@ParameterizedTest
@@ -632,12 +617,20 @@
final Integer delinquencyBucketId, final boolean withJournalEntries, LoanProductTestBuilder loanProductTestBuilder) {
final HashMap<String, Object> loanProductMap;
if (withJournalEntries) {
- final Account assetAccount = accountHelper.createAssetAccount();
- final Account expenseAccount = accountHelper.createExpenseAccount();
- final Account incomeAccount = accountHelper.createIncomeAccount();
- final Account overpaymentAccount = accountHelper.createLiabilityAccount();
loanProductMap = loanProductTestBuilder
- .withAccountingRulePeriodicAccrual(new Account[] { assetAccount, expenseAccount, incomeAccount, overpaymentAccount })
+ .withFullAccountingConfig(ACCRUAL_PERIODIC,
+ LoanProductTestBuilder.FullAccountingConfig.builder().fundSourceAccountId(fundSource.getAccountID().longValue())//
+ .loanPortfolioAccountId(loansReceivableAccount.getAccountID().longValue())//
+ .transfersInSuspenseAccountId(suspenseAccount.getAccountID().longValue())//
+ .interestOnLoanAccountId(interestIncomeAccount.getAccountID().longValue())//
+ .incomeFromFeeAccountId(feeIncomeAccount.getAccountID().longValue())//
+ .incomeFromPenaltyAccountId(penaltyIncomeAccount.getAccountID().longValue())//
+ .incomeFromRecoveryAccountId(recoveriesAccount.getAccountID().longValue())//
+ .writeOffAccountId(writtenOffAccount.getAccountID().longValue())//
+ .overpaymentLiabilityAccountId(overpaymentAccount.getAccountID().longValue())//
+ .receivableInterestAccountId(interestReceivableAccount.getAccountID().longValue())//
+ .receivableFeeAccountId(interestReceivableAccount.getAccountID().longValue())//
+ .receivablePenaltyAccountId(interestReceivableAccount.getAccountID().longValue()).build())
.build(null, delinquencyBucketId);
} else {
loanProductMap = loanProductTestBuilder.build(null, delinquencyBucketId);
diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/UndoLoanDisbursalWithDownPaymentIntegrationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/UndoLoanDisbursalWithDownPaymentIntegrationTest.java
index 6ecb979..20f4837 100644
--- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/UndoLoanDisbursalWithDownPaymentIntegrationTest.java
+++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/UndoLoanDisbursalWithDownPaymentIntegrationTest.java
@@ -69,9 +69,9 @@
// verify journal entries
verifyJournalEntries(loanId, //
journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(250.0, fundSource, "DEBIT"), //
journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(1000.0, suspenseClearingAccount, "CREDIT") //
+ journalEntry(1000.0, fundSource, "CREDIT") //
);
// Verify Repayment Schedule
@@ -91,14 +91,14 @@
verifyJournalEntries(loanId,
// original entries
journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(250.0, fundSource, "DEBIT"), //
journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(1000.0, suspenseClearingAccount, "CREDIT"), //
+ journalEntry(1000.0, fundSource, "CREDIT"), //
// original entries reverted
journalEntry(250.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(250.0, suspenseClearingAccount, "CREDIT"), //
+ journalEntry(250.0, fundSource, "CREDIT"), //
journalEntry(1000.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(1000.0, suspenseClearingAccount, "DEBIT")); //
+ journalEntry(1000.0, fundSource, "DEBIT")); //
verifyRepaymentSchedule(loanId, //
installment(1000.0, null, "01 January 2023"), //
@@ -139,9 +139,9 @@
// verify journal entries
verifyJournalEntries(loanId, //
journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(250.0, fundSource, "DEBIT"), //
journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(1000.0, suspenseClearingAccount, "CREDIT") //
+ journalEntry(1000.0, fundSource, "CREDIT") //
);
// make a repayment
@@ -164,23 +164,23 @@
verifyJournalEntries(loanId, //
// original entries down-payment
journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(250.0, fundSource, "DEBIT"), //
journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(1000.0, suspenseClearingAccount, "CREDIT"), //
+ journalEntry(1000.0, fundSource, "CREDIT"), //
// repayment entries
journalEntry(100.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(100.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(100.0, fundSource, "DEBIT"), //
// original entries compensated
journalEntry(250.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(250.0, suspenseClearingAccount, "CREDIT"), //
+ journalEntry(250.0, fundSource, "CREDIT"), //
journalEntry(1000.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(1000.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(1000.0, fundSource, "DEBIT"), //
// repayment entries compensated
journalEntry(250.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(250.0, suspenseClearingAccount, "CREDIT") //
+ journalEntry(250.0, fundSource, "CREDIT") //
);
verifyRepaymentSchedule(loanId, //
@@ -225,9 +225,9 @@
// verify journal entries
verifyJournalEntries(loanId, //
journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(250.0, fundSource, "DEBIT"), //
journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(1000.0, suspenseClearingAccount, "CREDIT") //
+ journalEntry(1000.0, fundSource, "CREDIT") //
);
// undoDisbursal
@@ -240,15 +240,15 @@
verifyJournalEntries(loanId, //
// original entries
journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(250.0, fundSource, "DEBIT"), //
journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(1000.0, suspenseClearingAccount, "CREDIT"), //
+ journalEntry(1000.0, fundSource, "CREDIT"), //
// original entries are compensated
journalEntry(250.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(250.0, suspenseClearingAccount, "CREDIT"), //
+ journalEntry(250.0, fundSource, "CREDIT"), //
journalEntry(1000.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(1000.0, suspenseClearingAccount, "DEBIT") //
+ journalEntry(1000.0, fundSource, "DEBIT") //
);
// verify repayment entries are reverted
@@ -298,11 +298,11 @@
// verify journal entries
verifyJournalEntries(loanId, //
journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(250.0, fundSource, "DEBIT"), //
journalEntry(100.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(100.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(100.0, fundSource, "DEBIT"), //
journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(1000.0, suspenseClearingAccount, "CREDIT") //
+ journalEntry(1000.0, fundSource, "CREDIT") //
);
// Verify Repayment Schedule
@@ -322,23 +322,23 @@
verifyJournalEntries(loanId, //
// original entries
journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(250.0, fundSource, "DEBIT"), //
journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(1000.0, suspenseClearingAccount, "CREDIT"), //
+ journalEntry(1000.0, fundSource, "CREDIT"), //
// original entries compensated
journalEntry(250.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(250.0, suspenseClearingAccount, "CREDIT"), //
+ journalEntry(250.0, fundSource, "CREDIT"), //
journalEntry(1000.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(1000.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(1000.0, fundSource, "DEBIT"), //
// manual partial repayment of the first installment
journalEntry(100.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(100.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(100.0, fundSource, "DEBIT"), //
// manual partial repayment of the first installment compensation after undoDisburse
journalEntry(100.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(100.0, suspenseClearingAccount, "CREDIT") //
+ journalEntry(100.0, fundSource, "CREDIT") //
);
// Verify Repayment Schedule
@@ -381,9 +381,9 @@
// verify journal entries
verifyJournalEntries(loanId, //
journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(250.0, fundSource, "DEBIT"), //
journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(1000.0, suspenseClearingAccount, "CREDIT") //
+ journalEntry(1000.0, fundSource, "CREDIT") //
);
// Verify Repayment Schedule
@@ -429,9 +429,9 @@
// verify journal entries
verifyJournalEntries(loanId, //
journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(250.0, fundSource, "DEBIT"), //
journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(1000.0, suspenseClearingAccount, "CREDIT") //
+ journalEntry(1000.0, fundSource, "CREDIT") //
);
// Verify Repayment Schedule
@@ -476,9 +476,9 @@
// verify journal entries
verifyJournalEntries(loanId, //
journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(250.0, fundSource, "DEBIT"), //
journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(1000.0, suspenseClearingAccount, "CREDIT") //
+ journalEntry(1000.0, fundSource, "CREDIT") //
);
// Verify Repayment Schedule
@@ -498,14 +498,14 @@
verifyJournalEntries(loanId, //
// original entries
journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(250.0, fundSource, "DEBIT"), //
journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(1000.0, suspenseClearingAccount, "CREDIT"), //
+ journalEntry(1000.0, fundSource, "CREDIT"), //
// original entries reverted
journalEntry(250.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(250.0, suspenseClearingAccount, "CREDIT"), //
+ journalEntry(250.0, fundSource, "CREDIT"), //
journalEntry(1000.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(1000.0, suspenseClearingAccount, "DEBIT") //
+ journalEntry(1000.0, fundSource, "DEBIT") //
);
// Verify Repayment Schedule
@@ -548,9 +548,9 @@
// verify journal entries
verifyJournalEntries(loanId, //
journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(250.0, fundSource, "DEBIT"), //
journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(1000.0, suspenseClearingAccount, "CREDIT") //
+ journalEntry(1000.0, fundSource, "CREDIT") //
);
// make a repayment
@@ -573,23 +573,23 @@
verifyJournalEntries(loanId,
// original entries down-payment
journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(250.0, fundSource, "DEBIT"), //
journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(1000.0, suspenseClearingAccount, "CREDIT"), //
+ journalEntry(1000.0, fundSource, "CREDIT"), //
// repayment entries
journalEntry(100.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(100.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(100.0, fundSource, "DEBIT"), //
// original entries compensated
journalEntry(250.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(250.0, suspenseClearingAccount, "CREDIT"), //
+ journalEntry(250.0, fundSource, "CREDIT"), //
journalEntry(1000.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(1000.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(1000.0, fundSource, "DEBIT"), //
// repayment entries compensated
journalEntry(250.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(250.0, suspenseClearingAccount, "CREDIT") //
+ journalEntry(250.0, fundSource, "CREDIT") //
);
// Verify Repayment Schedule
@@ -635,9 +635,9 @@
// verify journal entries
verifyJournalEntries(loanId, //
journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(250.0, fundSource, "DEBIT"), //
journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(1000.0, suspenseClearingAccount, "CREDIT") //
+ journalEntry(1000.0, fundSource, "CREDIT") //
);
// undoDisbursal
@@ -650,15 +650,15 @@
verifyJournalEntries(loanId,
// original entries
journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(250.0, fundSource, "DEBIT"), //
journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(1000.0, suspenseClearingAccount, "CREDIT"), //
+ journalEntry(1000.0, fundSource, "CREDIT"), //
// original entries are compensated
journalEntry(250.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(250.0, suspenseClearingAccount, "CREDIT"), //
+ journalEntry(250.0, fundSource, "CREDIT"), //
journalEntry(1000.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(1000.0, suspenseClearingAccount, "DEBIT") //
+ journalEntry(1000.0, fundSource, "DEBIT") //
);
// Verify Repayment Schedule
@@ -707,11 +707,11 @@
// verify journal entries
verifyJournalEntries(loanId, //
journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(250.0, fundSource, "DEBIT"), //
journalEntry(100.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(100.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(100.0, fundSource, "DEBIT"), //
journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(1000.0, suspenseClearingAccount, "CREDIT") //
+ journalEntry(1000.0, fundSource, "CREDIT") //
);
// Verify Repayment Schedule
@@ -731,23 +731,23 @@
verifyJournalEntries(loanId,
// original entries
journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(250.0, fundSource, "DEBIT"), //
journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(1000.0, suspenseClearingAccount, "CREDIT"), //
+ journalEntry(1000.0, fundSource, "CREDIT"), //
// original entries compensated
journalEntry(250.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(250.0, suspenseClearingAccount, "CREDIT"), //
+ journalEntry(250.0, fundSource, "CREDIT"), //
journalEntry(1000.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(1000.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(1000.0, fundSource, "DEBIT"), //
// manual partial repayment of the first installment
journalEntry(100.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(100.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(100.0, fundSource, "DEBIT"), //
// manual partial repayment of the first installment compensation after undoDisburse
journalEntry(100.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(100.0, suspenseClearingAccount, "CREDIT") //
+ journalEntry(100.0, fundSource, "CREDIT") //
);
// Verify Repayment Schedule
@@ -787,9 +787,9 @@
// verify journal entries
verifyJournalEntries(loanId, journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(250.0, fundSource, "DEBIT"), //
journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(1000.0, suspenseClearingAccount, "CREDIT") //
+ journalEntry(1000.0, fundSource, "CREDIT") //
);
// Verify Repayment Schedule
@@ -815,13 +815,13 @@
// verify journal entries
verifyJournalEntries(loanId, //
journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(250.0, fundSource, "DEBIT"), //
journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(1000.0, suspenseClearingAccount, "CREDIT"), //
+ journalEntry(1000.0, fundSource, "CREDIT"), //
journalEntry(100.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(100.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(100.0, fundSource, "DEBIT"), //
journalEntry(400.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(400.0, suspenseClearingAccount, "CREDIT") //
+ journalEntry(400.0, fundSource, "CREDIT") //
);
// Verify Repayment Schedule
@@ -846,21 +846,21 @@
verifyJournalEntries(loanId,
// first disbursement + down-payment
journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(250.0, fundSource, "DEBIT"), //
journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(1000.0, suspenseClearingAccount, "CREDIT"), //
+ journalEntry(1000.0, fundSource, "CREDIT"), //
// second disbursement + down-payment
journalEntry(100.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(100.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(100.0, fundSource, "DEBIT"), //
journalEntry(400.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(400.0, suspenseClearingAccount, "CREDIT"), //
+ journalEntry(400.0, fundSource, "CREDIT"), //
// compensation of second disbursement + down-payment
journalEntry(100.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(100.0, suspenseClearingAccount, "CREDIT"), //
+ journalEntry(100.0, fundSource, "CREDIT"), //
journalEntry(400.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(400.0, suspenseClearingAccount, "DEBIT") //
+ journalEntry(400.0, fundSource, "DEBIT") //
);
verifyRepaymentSchedule(loanId, //
@@ -901,9 +901,9 @@
// verify journal entries
verifyJournalEntries(loanId, journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(250.0, fundSource, "DEBIT"), //
journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(1000.0, suspenseClearingAccount, "CREDIT") //
+ journalEntry(1000.0, fundSource, "CREDIT") //
);
// Verify Repayment Schedule
@@ -941,15 +941,15 @@
// verify journal entries
verifyJournalEntries(loanId, //
journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(250.0, fundSource, "DEBIT"), //
journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(1000.0, suspenseClearingAccount, "CREDIT"), //
+ journalEntry(1000.0, fundSource, "CREDIT"), //
journalEntry(300.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(300.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(300.0, fundSource, "DEBIT"), //
journalEntry(100.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(100.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(100.0, fundSource, "DEBIT"), //
journalEntry(400.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(400.0, suspenseClearingAccount, "CREDIT") //
+ journalEntry(400.0, fundSource, "CREDIT") //
);
// Verify Repayment Schedule
@@ -975,25 +975,25 @@
verifyJournalEntries(loanId,
// first disbursement + down-payment
journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(250.0, fundSource, "DEBIT"), //
journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(1000.0, suspenseClearingAccount, "CREDIT"), //
+ journalEntry(1000.0, fundSource, "CREDIT"), //
// repayment
journalEntry(300.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(300.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(300.0, fundSource, "DEBIT"), //
// second disbursement + down-payment
journalEntry(100.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(100.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(100.0, fundSource, "DEBIT"), //
journalEntry(400.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(400.0, suspenseClearingAccount, "CREDIT"), //
+ journalEntry(400.0, fundSource, "CREDIT"), //
// compensation of second disbursement + down-payment
journalEntry(100.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(100.0, suspenseClearingAccount, "CREDIT"), //
+ journalEntry(100.0, fundSource, "CREDIT"), //
journalEntry(400.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(400.0, suspenseClearingAccount, "DEBIT") //
+ journalEntry(400.0, fundSource, "DEBIT") //
);
verifyRepaymentSchedule(loanId, //
@@ -1038,9 +1038,9 @@
// verify journal entries
verifyJournalEntries(loanId, //
journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(250.0, fundSource, "DEBIT"), //
journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(1000.0, suspenseClearingAccount, "CREDIT") //
+ journalEntry(1000.0, fundSource, "CREDIT") //
);
// Verify Repayment Schedule
@@ -1070,13 +1070,13 @@
// verify journal entries
verifyJournalEntries(loanId, //
journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(250.0, fundSource, "DEBIT"), //
journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(1000.0, suspenseClearingAccount, "CREDIT"), //
+ journalEntry(1000.0, fundSource, "CREDIT"), //
journalEntry(100.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(100.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(100.0, fundSource, "DEBIT"), //
journalEntry(400.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(400.0, suspenseClearingAccount, "CREDIT") //
+ journalEntry(400.0, fundSource, "CREDIT") //
);
// Verify Repayment Schedule
@@ -1101,21 +1101,21 @@
verifyJournalEntries(loanId,
// first disbursement + down-payment
journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(250.0, fundSource, "DEBIT"), //
journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(1000.0, suspenseClearingAccount, "CREDIT"), //
+ journalEntry(1000.0, fundSource, "CREDIT"), //
// second disbursement + down-payment
journalEntry(100.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(100.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(100.0, fundSource, "DEBIT"), //
journalEntry(400.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(400.0, suspenseClearingAccount, "CREDIT"), //
+ journalEntry(400.0, fundSource, "CREDIT"), //
// compensation of second disbursement + down-payment
journalEntry(100.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(100.0, suspenseClearingAccount, "CREDIT"), //
+ journalEntry(100.0, fundSource, "CREDIT"), //
journalEntry(400.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(400.0, suspenseClearingAccount, "DEBIT") //
+ journalEntry(400.0, fundSource, "DEBIT") //
);
verifyRepaymentSchedule(loanId, //
@@ -1157,9 +1157,9 @@
// verify journal entries
verifyJournalEntries(loanId, //
journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(250.0, fundSource, "DEBIT"), //
journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(1000.0, suspenseClearingAccount, "CREDIT") //
+ journalEntry(1000.0, fundSource, "CREDIT") //
);
// Verify Repayment Schedule
@@ -1186,13 +1186,13 @@
// verify journal entries
verifyJournalEntries(loanId, //
journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(250.0, fundSource, "DEBIT"), //
journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(1000.0, suspenseClearingAccount, "CREDIT"), //
+ journalEntry(1000.0, fundSource, "CREDIT"), //
journalEntry(100.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(100.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(100.0, fundSource, "DEBIT"), //
journalEntry(400.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(400.0, suspenseClearingAccount, "CREDIT") //
+ journalEntry(400.0, fundSource, "CREDIT") //
);
// Verify Repayment Schedule
@@ -1249,9 +1249,9 @@
// verify journal entries
verifyJournalEntries(loanId, //
journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(250.0, fundSource, "DEBIT"), //
journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(1000.0, suspenseClearingAccount, "CREDIT") //
+ journalEntry(1000.0, fundSource, "CREDIT") //
);
// Verify Repayment Schedule
@@ -1281,13 +1281,13 @@
// verify journal entries
verifyJournalEntries(loanId, //
journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(250.0, fundSource, "DEBIT"), //
journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(1000.0, suspenseClearingAccount, "CREDIT"), //
+ journalEntry(1000.0, fundSource, "CREDIT"), //
journalEntry(100.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(100.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(100.0, fundSource, "DEBIT"), //
journalEntry(400.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(400.0, suspenseClearingAccount, "CREDIT") //
+ journalEntry(400.0, fundSource, "CREDIT") //
);
// Verify Repayment Schedule
@@ -1341,9 +1341,9 @@
// verify journal entries
verifyJournalEntries(loanId, //
journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(250.0, fundSource, "DEBIT"), //
journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(1000.0, suspenseClearingAccount, "CREDIT") //
+ journalEntry(1000.0, fundSource, "CREDIT") //
);
// Verify Repayment Schedule
@@ -1370,13 +1370,13 @@
// verify journal entries
verifyJournalEntries(loanId, //
journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(250.0, fundSource, "DEBIT"), //
journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(1000.0, suspenseClearingAccount, "CREDIT"), //
+ journalEntry(1000.0, fundSource, "CREDIT"), //
journalEntry(100.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(100.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(100.0, fundSource, "DEBIT"), //
journalEntry(400.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(400.0, suspenseClearingAccount, "CREDIT") //
+ journalEntry(400.0, fundSource, "CREDIT") //
);
// Verify Repayment Schedule
@@ -1404,27 +1404,27 @@
verifyJournalEntries(loanId,
// 1st disbursal + down-payment
journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(250.0, fundSource, "DEBIT"), //
journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(1000.0, suspenseClearingAccount, "CREDIT"), //
+ journalEntry(1000.0, fundSource, "CREDIT"), //
// 2nd disbursal + down-payment
journalEntry(100.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(100.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(100.0, fundSource, "DEBIT"), //
journalEntry(400.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(400.0, suspenseClearingAccount, "CREDIT"), //
+ journalEntry(400.0, fundSource, "CREDIT"), //
// compensation of the 1st disbursal + down-payment
journalEntry(250.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(250.0, suspenseClearingAccount, "CREDIT"), //
+ journalEntry(250.0, fundSource, "CREDIT"), //
journalEntry(1000.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(1000.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(1000.0, fundSource, "DEBIT"), //
// compensation of the 2nd disbursal + down-payment
journalEntry(100.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(100.0, suspenseClearingAccount, "CREDIT"), //
+ journalEntry(100.0, fundSource, "CREDIT"), //
journalEntry(400.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(400.0, suspenseClearingAccount, "DEBIT") //
+ journalEntry(400.0, fundSource, "DEBIT") //
);
});
}
@@ -1463,9 +1463,9 @@
// verify journal entries
verifyJournalEntries(loanId, //
journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(250.0, fundSource, "DEBIT"), //
journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(1000.0, suspenseClearingAccount, "CREDIT") //
+ journalEntry(1000.0, fundSource, "CREDIT") //
);
// Verify Repayment Schedule
@@ -1495,13 +1495,13 @@
// verify journal entries
verifyJournalEntries(loanId, //
journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(250.0, fundSource, "DEBIT"), //
journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(1000.0, suspenseClearingAccount, "CREDIT"), //
+ journalEntry(1000.0, fundSource, "CREDIT"), //
journalEntry(100.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(100.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(100.0, fundSource, "DEBIT"), //
journalEntry(400.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(400.0, suspenseClearingAccount, "CREDIT") //
+ journalEntry(400.0, fundSource, "CREDIT") //
);
// Verify Repayment Schedule
@@ -1529,27 +1529,27 @@
verifyJournalEntries(loanId,
// 1st disbursal + down-payment
journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(250.0, fundSource, "DEBIT"), //
journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(1000.0, suspenseClearingAccount, "CREDIT"), //
+ journalEntry(1000.0, fundSource, "CREDIT"), //
// 2nd disbursal + down-payment
journalEntry(100.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(100.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(100.0, fundSource, "DEBIT"), //
journalEntry(400.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(400.0, suspenseClearingAccount, "CREDIT"), //
+ journalEntry(400.0, fundSource, "CREDIT"), //
// compensation of the 1st disbursal + down-payment
journalEntry(250.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(250.0, suspenseClearingAccount, "CREDIT"), //
+ journalEntry(250.0, fundSource, "CREDIT"), //
journalEntry(1000.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(1000.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(1000.0, fundSource, "DEBIT"), //
// compensation of the 2nd disbursal + down-payment
journalEntry(100.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(100.0, suspenseClearingAccount, "CREDIT"), //
+ journalEntry(100.0, fundSource, "CREDIT"), //
journalEntry(400.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(400.0, suspenseClearingAccount, "DEBIT") //
+ journalEntry(400.0, fundSource, "DEBIT") //
);
});
}
@@ -1585,9 +1585,9 @@
// verify journal entries
verifyJournalEntries(loanId, //
journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(250.0, fundSource, "DEBIT"), //
journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(1000.0, suspenseClearingAccount, "CREDIT") //
+ journalEntry(1000.0, fundSource, "CREDIT") //
);
// Verify Repayment Schedule
@@ -1614,13 +1614,13 @@
// verify journal entries
verifyJournalEntries(loanId, //
journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(250.0, fundSource, "DEBIT"), //
journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(1000.0, suspenseClearingAccount, "CREDIT"), //
+ journalEntry(1000.0, fundSource, "CREDIT"), //
journalEntry(100.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(100.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(100.0, fundSource, "DEBIT"), //
journalEntry(400.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(400.0, suspenseClearingAccount, "CREDIT") //
+ journalEntry(400.0, fundSource, "CREDIT") //
);
// Verify Repayment Schedule
@@ -1654,35 +1654,35 @@
verifyJournalEntries(loanId,
// 1st disbursal + down-payment
journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(250.0, fundSource, "DEBIT"), //
journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(1000.0, suspenseClearingAccount, "CREDIT"), //
+ journalEntry(1000.0, fundSource, "CREDIT"), //
// 2nd disbursal + down-payment
journalEntry(100.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(100.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(100.0, fundSource, "DEBIT"), //
journalEntry(400.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(400.0, suspenseClearingAccount, "CREDIT"), //
+ journalEntry(400.0, fundSource, "CREDIT"), //
// manual repayment
journalEntry(50.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(50.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(50.0, fundSource, "DEBIT"), //
// compensation of the 1st disbursal + down-payment
journalEntry(250.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(250.0, suspenseClearingAccount, "CREDIT"), //
+ journalEntry(250.0, fundSource, "CREDIT"), //
journalEntry(1000.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(1000.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(1000.0, fundSource, "DEBIT"), //
// compensation of the 2nd disbursal + down-payment
journalEntry(100.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(100.0, suspenseClearingAccount, "CREDIT"), //
+ journalEntry(100.0, fundSource, "CREDIT"), //
journalEntry(400.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(400.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(400.0, fundSource, "DEBIT"), //
// compensation of repayment
journalEntry(50.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(50.0, suspenseClearingAccount, "CREDIT") //
+ journalEntry(50.0, fundSource, "CREDIT") //
);
});
}
@@ -1721,9 +1721,9 @@
// verify journal entries
verifyJournalEntries(loanId, //
journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(250.0, fundSource, "DEBIT"), //
journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(1000.0, suspenseClearingAccount, "CREDIT") //
+ journalEntry(1000.0, fundSource, "CREDIT") //
);
// Verify Repayment Schedule
@@ -1752,13 +1752,13 @@
// verify journal entries
verifyJournalEntries(loanId, journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(250.0, fundSource, "DEBIT"), //
journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(1000.0, suspenseClearingAccount, "CREDIT"), //
+ journalEntry(1000.0, fundSource, "CREDIT"), //
journalEntry(100.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(100.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(100.0, fundSource, "DEBIT"), //
journalEntry(400.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(400.0, suspenseClearingAccount, "CREDIT") //
+ journalEntry(400.0, fundSource, "CREDIT") //
);
// Verify Repayment Schedule
@@ -1792,35 +1792,35 @@
verifyJournalEntries(loanId,
// 1st disbursal + down-payment
journalEntry(250.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(250.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(250.0, fundSource, "DEBIT"), //
journalEntry(1000.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(1000.0, suspenseClearingAccount, "CREDIT"), //
+ journalEntry(1000.0, fundSource, "CREDIT"), //
// 2nd disbursal + down-payment
journalEntry(100.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(100.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(100.0, fundSource, "DEBIT"), //
journalEntry(400.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(400.0, suspenseClearingAccount, "CREDIT"), //
+ journalEntry(400.0, fundSource, "CREDIT"), //
// manual repayment
journalEntry(50.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(50.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(50.0, fundSource, "DEBIT"), //
// compensation of the 1st disbursal + down-payment
journalEntry(250.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(250.0, suspenseClearingAccount, "CREDIT"), //
+ journalEntry(250.0, fundSource, "CREDIT"), //
journalEntry(1000.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(1000.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(1000.0, fundSource, "DEBIT"), //
// compensation of the 2nd disbursal + down-payment
journalEntry(100.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(100.0, suspenseClearingAccount, "CREDIT"), //
+ journalEntry(100.0, fundSource, "CREDIT"), //
journalEntry(400.0, loansReceivableAccount, "CREDIT"), //
- journalEntry(400.0, suspenseClearingAccount, "DEBIT"), //
+ journalEntry(400.0, fundSource, "DEBIT"), //
// compensation of repayment
journalEntry(50.0, loansReceivableAccount, "DEBIT"), //
- journalEntry(50.0, suspenseClearingAccount, "CREDIT") //
+ journalEntry(50.0, fundSource, "CREDIT") //
);
});
}
diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/accounting/AccountHelper.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/accounting/AccountHelper.java
index 0d2a503..1004473 100644
--- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/accounting/AccountHelper.java
+++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/accounting/AccountHelper.java
@@ -42,35 +42,55 @@
}
public Account createAssetAccount() {
- final String assetAccountJSON = new GLAccountBuilder().withAccountTypeAsAsset().build();
+ return this.createAssetAccount(null);
+ }
+
+ public Account createIncomeAccount() {
+ return this.createIncomeAccount(null);
+ }
+
+ public Account createExpenseAccount() {
+ return this.createExpenseAccount(null);
+ }
+
+ public Account createLiabilityAccount() {
+ return this.createLiabilityAccount(null);
+ }
+
+ public Account createEquityAccount() {
+ return this.createEquityAccount(null);
+ }
+
+ public Account createAssetAccount(String accountName) {
+ final String assetAccountJSON = new GLAccountBuilder().withName(accountName).withAccountTypeAsAsset().build();
final Integer accountID = Utils.performServerPost(this.requestSpec, this.responseSpec, CREATE_GL_ACCOUNT_URL, assetAccountJSON,
GL_ACCOUNT_ID_RESPONSE);
return new Account(accountID, Account.AccountType.ASSET);
}
- public Account createIncomeAccount() {
- final String assetAccountJSON = new GLAccountBuilder().withAccountTypeAsIncome().build();
+ public Account createIncomeAccount(String accountName) {
+ final String assetAccountJSON = new GLAccountBuilder().withName(accountName).withAccountTypeAsIncome().build();
final Integer accountID = Utils.performServerPost(this.requestSpec, this.responseSpec, CREATE_GL_ACCOUNT_URL, assetAccountJSON,
GL_ACCOUNT_ID_RESPONSE);
return new Account(accountID, Account.AccountType.INCOME);
}
- public Account createExpenseAccount() {
- final String assetAccountJSON = new GLAccountBuilder().withAccountTypeAsExpense().build();
+ public Account createExpenseAccount(String accountName) {
+ final String assetAccountJSON = new GLAccountBuilder().withName(accountName).withAccountTypeAsExpense().build();
final Integer accountID = Utils.performServerPost(this.requestSpec, this.responseSpec, CREATE_GL_ACCOUNT_URL, assetAccountJSON,
GL_ACCOUNT_ID_RESPONSE);
return new Account(accountID, Account.AccountType.EXPENSE);
}
- public Account createLiabilityAccount() {
- final String liabilityAccountJSON = new GLAccountBuilder().withAccountTypeAsLiability().build();
+ public Account createLiabilityAccount(String accountName) {
+ final String liabilityAccountJSON = new GLAccountBuilder().withName(accountName).withAccountTypeAsLiability().build();
final Integer accountID = Utils.performServerPost(this.requestSpec, this.responseSpec, CREATE_GL_ACCOUNT_URL, liabilityAccountJSON,
GL_ACCOUNT_ID_RESPONSE);
return new Account(accountID, Account.AccountType.LIABILITY);
}
- public Account createEquityAccount() {
- final String equityAccountJSON = new GLAccountBuilder().withAccountTypeAsAsEquity().build();
+ public Account createEquityAccount(String accountName) {
+ final String equityAccountJSON = new GLAccountBuilder().withName(accountName).withAccountTypeAsAsEquity().build();
final Integer accountID = Utils.performServerPost(this.requestSpec, this.responseSpec, CREATE_GL_ACCOUNT_URL, equityAccountJSON,
GL_ACCOUNT_ID_RESPONSE);
return new Account(accountID, Account.AccountType.EQUITY);
diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/accounting/GLAccountBuilder.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/accounting/GLAccountBuilder.java
index 9edec63..9a675d1 100644
--- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/accounting/GLAccountBuilder.java
+++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/accounting/GLAccountBuilder.java
@@ -21,6 +21,7 @@
import com.google.gson.Gson;
import java.util.Calendar;
import java.util.HashMap;
+import org.apache.commons.lang3.StringUtils;
import org.apache.fineract.integrationtests.common.Utils;
public class GLAccountBuilder {
@@ -86,6 +87,13 @@
return this;
}
+ public GLAccountBuilder withName(String name) {
+ if (StringUtils.isNotBlank(name)) {
+ this.name = Utils.uniqueRandomStringGenerator(name + "_", 5);
+ }
+ return this;
+ }
+
public GLAccountBuilder withAccountUsageAsHeader() {
accountUsage = ACCOUNT_USAGE_HEADER;
return this;
diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanProductTestBuilder.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanProductTestBuilder.java
index a5973d5..7fd2529 100644
--- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanProductTestBuilder.java
+++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanProductTestBuilder.java
@@ -25,6 +25,8 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
+import lombok.Builder;
import org.apache.fineract.client.models.AdvancedPaymentData;
import org.apache.fineract.client.models.CreditAllocationData;
import org.apache.fineract.integrationtests.common.Utils;
@@ -69,10 +71,10 @@
public static final String RECALCULATION_COMPOUNDING_METHOD_FEE = "2";
public static final String RECALCULATION_COMPOUNDING_METHOD_INTEREST_AND_FEE = "3";
- private static final String NONE = "1";
- private static final String CASH_BASED = "2";
- private static final String ACCRUAL_PERIODIC = "3";
- private static final String ACCRUAL_UPFRONT = "4";
+ public static final String NONE = "1";
+ public static final String CASH_BASED = "2";
+ public static final String ACCRUAL_PERIODIC = "3";
+ public static final String ACCRUAL_UPFRONT = "4";
public static final String INTEREST_APPLICABLE_STRATEGY_REST_DATE = "2";
public static final String INTEREST_APPLICABLE_STRATEGY_ON_PRE_CLOSE_DATE = "1";
@@ -157,6 +159,7 @@
private Integer repaymentStartDateType = null;
private String loanScheduleType = LoanScheduleType.CUMULATIVE.name();
private String loanScheduleProcessingType = LoanScheduleProcessingType.HORIZONTAL.name();
+ private FullAccountingConfig fullAccountingConfig;
public String build() {
final HashMap<String, Object> map = build(null, null);
@@ -231,7 +234,9 @@
map.put("outstandingLoanBalance", this.outstandingLoanBalance);
}
- if (this.accountingRule.equals(ACCRUAL_UPFRONT) || this.accountingRule.equals(ACCRUAL_PERIODIC)) {
+ if (this.fullAccountingConfig != null) {
+ map.putAll(this.fullAccountingConfig.toMap());
+ } else if (this.accountingRule.equals(ACCRUAL_UPFRONT) || this.accountingRule.equals(ACCRUAL_PERIODIC)) {
map.putAll(getAccountMappingForAccrualBased(this.feeAndPenaltyAssetAccount));
} else if (this.accountingRule.equals(CASH_BASED)) {
map.putAll(getAccountMappingForCashBased());
@@ -487,6 +492,13 @@
return this;
}
+ public LoanProductTestBuilder withFullAccountingConfig(String accountingRule, FullAccountingConfig fullAccountingConfig) {
+ this.accountingRule = accountingRule;
+ this.fullAccountingConfig = fullAccountingConfig;
+ this.accountList = null;
+ return this;
+ }
+
private Map<String, String> getAccountMappingForCashBased() {
final Map<String, String> map = new HashMap<>();
for (int i = 0; i < this.accountList.length; i++) {
@@ -768,4 +780,78 @@
return transactionProcessingStrategyCode;
}
+ @Builder
+ public static class FullAccountingConfig {
+
+ private final Long fundSourceAccountId;
+ private final Long loanPortfolioAccountId;
+ private final Long transfersInSuspenseAccountId;
+ private final Long interestOnLoanAccountId;
+ private final Long incomeFromFeeAccountId;
+ private final Long incomeFromPenaltyAccountId;
+ private final Long incomeFromRecoveryAccountId;
+ private final Long writeOffAccountId;
+ private final Long overpaymentLiabilityAccountId;
+ private final Long receivableInterestAccountId;
+ private final Long receivableFeeAccountId;
+ private final Long receivablePenaltyAccountId;
+ private final Long goodwillCreditAccountId;
+ private final Long incomeFromGoodwillCreditInterestAccountId;
+ private final Long incomeFromGoodwillCreditFeesAccountId;
+ private final Long incomeFromGoodwillCreditPenaltyAccountId;
+ private final Long incomeFromChargeOffInterestAccountId;
+ private final Long incomeFromChargeOffFeesAccountId;
+ private final Long chargeOffExpenseAccountId;
+ private final Long chargeOffFraudExpenseAccountId;
+ private final Long incomeFromChargeOffPenaltyAccountId;
+ private final Long accountingRule;
+
+ public Map<String, String> toMap() {
+ Map<String, String> map = new HashMap<>();
+ Optional.ofNullable(fundSourceAccountId)
+ .ifPresent(fundSourceAccountId -> map.put("fundSourceAccountId", Long.toString(fundSourceAccountId)));
+ Optional.ofNullable(loanPortfolioAccountId)
+ .ifPresent(loanPortfolioAccountId -> map.put("loanPortfolioAccountId", Long.toString(loanPortfolioAccountId)));
+ Optional.ofNullable(transfersInSuspenseAccountId).ifPresent(
+ transfersInSuspenseAccountId -> map.put("transfersInSuspenseAccountId", Long.toString(transfersInSuspenseAccountId)));
+ Optional.ofNullable(interestOnLoanAccountId)
+ .ifPresent(interestOnLoanAccountId -> map.put("interestOnLoanAccountId", Long.toString(interestOnLoanAccountId)));
+ Optional.ofNullable(incomeFromFeeAccountId)
+ .ifPresent(incomeFromFeeAccountId -> map.put("incomeFromFeeAccountId", Long.toString(incomeFromFeeAccountId)));
+ Optional.ofNullable(incomeFromPenaltyAccountId).ifPresent(
+ incomeFromPenaltyAccountId -> map.put("incomeFromPenaltyAccountId", Long.toString(incomeFromPenaltyAccountId)));
+ Optional.ofNullable(incomeFromRecoveryAccountId).ifPresent(
+ incomeFromRecoveryAccountId -> map.put("incomeFromRecoveryAccountId", Long.toString(incomeFromRecoveryAccountId)));
+ Optional.ofNullable(writeOffAccountId)
+ .ifPresent(writeOffAccountId -> map.put("writeOffAccountId", Long.toString(writeOffAccountId)));
+ Optional.ofNullable(overpaymentLiabilityAccountId).ifPresent(overpaymentLiabilityAccountId -> map
+ .put("overpaymentLiabilityAccountId", Long.toString(overpaymentLiabilityAccountId)));
+ Optional.ofNullable(receivableInterestAccountId).ifPresent(
+ receivableInterestAccountId -> map.put("receivableInterestAccountId", Long.toString(receivableInterestAccountId)));
+ Optional.ofNullable(receivableFeeAccountId)
+ .ifPresent(receivableFeeAccountId -> map.put("receivableFeeAccountId", Long.toString(receivableFeeAccountId)));
+ Optional.ofNullable(receivablePenaltyAccountId).ifPresent(
+ receivablePenaltyAccountId -> map.put("receivablePenaltyAccountId", Long.toString(receivablePenaltyAccountId)));
+ Optional.ofNullable(goodwillCreditAccountId)
+ .ifPresent(goodwillCreditAccountId -> map.put("goodwillCreditAccountId", Long.toString(goodwillCreditAccountId)));
+ Optional.ofNullable(incomeFromGoodwillCreditInterestAccountId).ifPresent(incomeFromGoodwillCreditInterestAccountId -> map
+ .put("incomeFromGoodwillCreditInterestAccountId", Long.toString(incomeFromGoodwillCreditInterestAccountId)));
+ Optional.ofNullable(incomeFromGoodwillCreditFeesAccountId).ifPresent(incomeFromGoodwillCreditFeesAccountId -> map
+ .put("incomeFromGoodwillCreditFeesAccountId", Long.toString(incomeFromGoodwillCreditFeesAccountId)));
+ Optional.ofNullable(incomeFromGoodwillCreditPenaltyAccountId).ifPresent(incomeFromGoodwillCreditPenaltyAccountId -> map
+ .put("incomeFromGoodwillCreditPenaltyAccountId", Long.toString(incomeFromGoodwillCreditPenaltyAccountId)));
+ Optional.ofNullable(incomeFromChargeOffInterestAccountId).ifPresent(incomeFromChargeOffInterestAccountId -> map
+ .put("incomeFromChargeOffInterestAccountId", Long.toString(incomeFromChargeOffInterestAccountId)));
+ Optional.ofNullable(incomeFromChargeOffFeesAccountId).ifPresent(incomeFromChargeOffFeesAccountId -> map
+ .put("incomeFromChargeOffFeesAccountId", Long.toString(incomeFromChargeOffFeesAccountId)));
+ Optional.ofNullable(chargeOffExpenseAccountId)
+ .ifPresent(chargeOffExpenseAccountId -> map.put("chargeOffExpenseAccountId", Long.toString(chargeOffExpenseAccountId)));
+ Optional.ofNullable(chargeOffFraudExpenseAccountId).ifPresent(chargeOffFraudExpenseAccountId -> map
+ .put("chargeOffFraudExpenseAccountId", Long.toString(chargeOffFraudExpenseAccountId)));
+ Optional.ofNullable(incomeFromChargeOffPenaltyAccountId).ifPresent(incomeFromChargeOffPenaltyAccountId -> map
+ .put("incomeFromChargeOffPenaltyAccountId", Long.toString(incomeFromChargeOffPenaltyAccountId)));
+ return map;
+ }
+ }
+
}