FINERACT-2042 Chargeback with credit allocation, accounting
This commit is contained in:
committed by
Peter Bagrij
parent
5f9845f86a
commit
697449e7e7
+29
-1
@@ -35,6 +35,7 @@ import java.util.HashSet;
|
||||
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 @@ public class LoanTransaction extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
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 @@ public class LoanTransaction extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
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) {
|
||||
|
||||
+5
@@ -60,4 +60,9 @@ public class LoanTransactionDTO {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
+7
-1
@@ -156,9 +156,15 @@ public class AccountingProcessorHelper {
|
||||
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);
|
||||
|
||||
+44
-15
@@ -430,25 +430,54 @@ public class AccrualBasedAccountingProcessorForLoan implements AccountingProcess
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+6
-6
@@ -3194,13 +3194,13 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
|
||||
);
|
||||
// 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 @@ public class AdvancedPaymentAllocationLoanRepaymentScheduleTest extends BaseLoan
|
||||
);
|
||||
// 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") //
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
+65
-32
@@ -72,6 +72,7 @@ import org.apache.fineract.integrationtests.common.BatchHelper;
|
||||
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 @@ public abstract class BaseLoanIntegrationTest {
|
||||
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 @@ public abstract class BaseLoanIntegrationTest {
|
||||
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 @@ public abstract class BaseLoanIntegrationTest {
|
||||
.includeInBorrowerCycle(false)//
|
||||
.currencyCode("USD")//
|
||||
.digitsAfterDecimal(2)//
|
||||
.inMultiplesOf(0)//
|
||||
.installmentAmountInMultiplesOf(1)//
|
||||
.useBorrowerCycle(false)//
|
||||
.minPrincipal(100.0)//
|
||||
@@ -207,24 +214,18 @@ public abstract class BaseLoanIntegrationTest {
|
||||
.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 @@ public abstract class BaseLoanIntegrationTest {
|
||||
.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 @@ public abstract class BaseLoanIntegrationTest {
|
||||
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 @@ public abstract class BaseLoanIntegrationTest {
|
||||
});
|
||||
}
|
||||
|
||||
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 @@ public abstract class BaseLoanIntegrationTest {
|
||||
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 @@ public abstract class BaseLoanIntegrationTest {
|
||||
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 @@ public abstract class BaseLoanIntegrationTest {
|
||||
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 @@ public abstract class BaseLoanIntegrationTest {
|
||||
Double amount;
|
||||
String type;
|
||||
String date;
|
||||
Double outstandingAmount;
|
||||
Double outstandingPrincipal;
|
||||
Double principalPortion;
|
||||
Double interestPortion;
|
||||
Double feePortion;
|
||||
|
||||
+458
-5
@@ -1011,6 +1011,455 @@ public class LoanChargebackWithCreditAllocationsIntegrationTests extends BaseLoa
|
||||
});
|
||||
}
|
||||
|
||||
@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 @@ public class LoanChargebackWithCreditAllocationsIntegrationTests extends BaseLoa
|
||||
}
|
||||
|
||||
@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 @@ public class LoanChargebackWithCreditAllocationsIntegrationTests extends BaseLoa
|
||||
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) {
|
||||
|
||||
+8
-19
@@ -23,7 +23,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
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 @@ public class LoanDownPaymentTransactionChargebackTest extends BaseLoanIntegratio
|
||||
);
|
||||
|
||||
// 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 @@ public class LoanDownPaymentTransactionChargebackTest extends BaseLoanIntegratio
|
||||
);
|
||||
|
||||
// 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) //
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
+8
-6
@@ -1252,10 +1252,11 @@ public class LoanRepaymentScheduleWithDownPaymentTest extends BaseLoanIntegratio
|
||||
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 @@ public class LoanRepaymentScheduleWithDownPaymentTest extends BaseLoanIntegratio
|
||||
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();
|
||||
|
||||
+2
-2
@@ -74,9 +74,9 @@ public class LoanRescheduleTestWithDownpayment extends BaseLoanIntegrationTest {
|
||||
|
||||
// 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
|
||||
|
||||
+28
-35
@@ -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 lombok.extern.slf4j.Slf4j;
|
||||
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.BusinessDateHelper;
|
||||
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 @@ import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
@Slf4j
|
||||
@ExtendWith(LoanTestLifecycleExtension.class)
|
||||
public class LoanTransactionChargebackTest {
|
||||
public class LoanTransactionChargebackTest extends BaseLoanIntegrationTest {
|
||||
|
||||
private ResponseSpecification responseSpec;
|
||||
private ResponseSpecification responseSpecErr400;
|
||||
@@ -139,14 +138,10 @@ public class LoanTransactionChargebackTest {
|
||||
|
||||
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 @@ public class LoanTransactionChargebackTest {
|
||||
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 @@ public class LoanTransactionChargebackTest {
|
||||
|
||||
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 @@ public class LoanTransactionChargebackTest {
|
||||
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);
|
||||
|
||||
+172
-172
@@ -69,9 +69,9 @@ public class UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
|
||||
// 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 @@ public class UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
|
||||
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 @@ public class UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
|
||||
// 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 @@ public class UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
|
||||
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 @@ public class UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
|
||||
// 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 @@ public class UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
|
||||
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 @@ public class UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
|
||||
// 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 @@ public class UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
|
||||
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 @@ public class UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
|
||||
// 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 @@ public class UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
|
||||
// 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 @@ public class UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
|
||||
// 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 @@ public class UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
|
||||
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 @@ public class UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
|
||||
// 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 @@ public class UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
|
||||
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 @@ public class UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
|
||||
// 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 @@ public class UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
|
||||
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 @@ public class UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
|
||||
// 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 @@ public class UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
|
||||
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 @@ public class UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
|
||||
|
||||
// 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 @@ public class UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
|
||||
// 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 @@ public class UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
|
||||
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 @@ public class UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
|
||||
|
||||
// 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 @@ public class UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
|
||||
// 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 @@ public class UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
|
||||
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 @@ public class UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
|
||||
// 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 @@ public class UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
|
||||
// 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 @@ public class UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
|
||||
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 @@ public class UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
|
||||
// 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 @@ public class UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
|
||||
// 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 @@ public class UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
|
||||
// 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 @@ public class UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
|
||||
// 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 @@ public class UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
|
||||
// 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 @@ public class UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
|
||||
// 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 @@ public class UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
|
||||
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 @@ public class UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
|
||||
// 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 @@ public class UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
|
||||
// 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 @@ public class UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
|
||||
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 @@ public class UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
|
||||
// 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 @@ public class UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
|
||||
// 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 @@ public class UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
|
||||
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 @@ public class UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
|
||||
// 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 @@ public class UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
|
||||
|
||||
// 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 @@ public class UndoLoanDisbursalWithDownPaymentIntegrationTest extends BaseLoanInt
|
||||
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") //
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
+29
-9
@@ -42,35 +42,55 @@ public class AccountHelper extends IntegrationTest {
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
+8
@@ -21,6 +21,7 @@ package org.apache.fineract.integrationtests.common.accounting;
|
||||
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 @@ public class GLAccountBuilder {
|
||||
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;
|
||||
|
||||
+91
-5
@@ -25,6 +25,8 @@ import java.util.Arrays;
|
||||
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 class LoanProductTestBuilder {
|
||||
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 @@ public class LoanProductTestBuilder {
|
||||
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 @@ public class LoanProductTestBuilder {
|
||||
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 @@ public class LoanProductTestBuilder {
|
||||
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 @@ public class LoanProductTestBuilder {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user