in fineract-provider/src/main/java/org/apache/fineract/accounting/journalentry/service/CashBasedAccountingProcessorForLoan.java [531:729]
private void createJournalEntriesForChargeOffLoanRepayments(LoanDTO loanDTO, LoanTransactionDTO loanTransactionDTO, Office office) {
// loan properties
final Long loanProductId = loanDTO.getLoanProductId();
final Long loanId = loanDTO.getLoanId();
final String currencyCode = loanDTO.getCurrencyCode();
final boolean isMarkedFraud = loanDTO.isMarkedAsFraud();
// transaction properties
final String transactionId = loanTransactionDTO.getTransactionId();
final LocalDate transactionDate = loanTransactionDTO.getTransactionDate();
final BigDecimal principalAmount = loanTransactionDTO.getPrincipal();
final BigDecimal interestAmount = loanTransactionDTO.getInterest();
final BigDecimal feesAmount = loanTransactionDTO.getFees();
final BigDecimal penaltiesAmount = loanTransactionDTO.getPenalties();
final BigDecimal overPaymentAmount = loanTransactionDTO.getOverPayment();
final Long paymentTypeId = loanTransactionDTO.getPaymentTypeId();
GLAccountBalanceHolder glAccountBalanceHolder = new GLAccountBalanceHolder();
BigDecimal totalDebitAmount = new BigDecimal(0);
// principal payment
if (principalAmount != null && principalAmount.compareTo(BigDecimal.ZERO) > 0) {
totalDebitAmount = totalDebitAmount.add(principalAmount);
if (loanTransactionDTO.getTransactionType().isMerchantIssuedRefund()) {
if (isMarkedFraud) {
populateCreditDebitMaps(loanProductId, principalAmount, paymentTypeId,
CashAccountsForLoan.CHARGE_OFF_FRAUD_EXPENSE.getValue(), CashAccountsForLoan.FUND_SOURCE.getValue(),
glAccountBalanceHolder);
} else {
populateCreditDebitMaps(loanProductId, principalAmount, paymentTypeId,
CashAccountsForLoan.CHARGE_OFF_EXPENSE.getValue(), CashAccountsForLoan.FUND_SOURCE.getValue(),
glAccountBalanceHolder);
}
} else if (loanTransactionDTO.getTransactionType().isPayoutRefund()) {
if (isMarkedFraud) {
populateCreditDebitMaps(loanProductId, principalAmount, paymentTypeId,
CashAccountsForLoan.CHARGE_OFF_FRAUD_EXPENSE.getValue(), CashAccountsForLoan.FUND_SOURCE.getValue(),
glAccountBalanceHolder);
} else {
populateCreditDebitMaps(loanProductId, principalAmount, paymentTypeId,
CashAccountsForLoan.CHARGE_OFF_EXPENSE.getValue(), CashAccountsForLoan.FUND_SOURCE.getValue(),
glAccountBalanceHolder);
}
} else if (loanTransactionDTO.getTransactionType().isGoodwillCredit()) {
populateCreditDebitMaps(loanProductId, principalAmount, paymentTypeId, CashAccountsForLoan.INCOME_FROM_RECOVERY.getValue(),
CashAccountsForLoan.GOODWILL_CREDIT.getValue(), glAccountBalanceHolder);
} else if (loanTransactionDTO.getTransactionType().isRepayment()) {
populateCreditDebitMaps(loanProductId, principalAmount, paymentTypeId, CashAccountsForLoan.INCOME_FROM_RECOVERY.getValue(),
CashAccountsForLoan.FUND_SOURCE.getValue(), glAccountBalanceHolder);
} else {
populateCreditDebitMaps(loanProductId, principalAmount, paymentTypeId, CashAccountsForLoan.LOAN_PORTFOLIO.getValue(),
CashAccountsForLoan.FUND_SOURCE.getValue(), glAccountBalanceHolder);
}
}
// interest payment
if (interestAmount != null && interestAmount.compareTo(BigDecimal.ZERO) > 0) {
totalDebitAmount = totalDebitAmount.add(interestAmount);
if (loanTransactionDTO.getTransactionType().isMerchantIssuedRefund()) {
populateCreditDebitMaps(loanProductId, interestAmount, paymentTypeId,
CashAccountsForLoan.INCOME_FROM_CHARGE_OFF_INTEREST.getValue(), CashAccountsForLoan.FUND_SOURCE.getValue(),
glAccountBalanceHolder);
} else if (loanTransactionDTO.getTransactionType().isPayoutRefund()) {
populateCreditDebitMaps(loanProductId, interestAmount, paymentTypeId,
CashAccountsForLoan.INCOME_FROM_CHARGE_OFF_INTEREST.getValue(), CashAccountsForLoan.FUND_SOURCE.getValue(),
glAccountBalanceHolder);
} else if (loanTransactionDTO.getTransactionType().isGoodwillCredit()) {
populateCreditDebitMaps(loanProductId, interestAmount, paymentTypeId, CashAccountsForLoan.INCOME_FROM_RECOVERY.getValue(),
CashAccountsForLoan.INCOME_FROM_GOODWILL_CREDIT_INTEREST.getValue(), glAccountBalanceHolder);
} else if (loanTransactionDTO.getTransactionType().isRepayment()) {
populateCreditDebitMaps(loanProductId, interestAmount, paymentTypeId, CashAccountsForLoan.INCOME_FROM_RECOVERY.getValue(),
CashAccountsForLoan.FUND_SOURCE.getValue(), glAccountBalanceHolder);
} else {
populateCreditDebitMaps(loanProductId, interestAmount, paymentTypeId, CashAccountsForLoan.INTEREST_ON_LOANS.getValue(),
CashAccountsForLoan.FUND_SOURCE.getValue(), glAccountBalanceHolder);
}
}
// handle fees payment
if (feesAmount != null && feesAmount.compareTo(BigDecimal.ZERO) > 0) {
totalDebitAmount = totalDebitAmount.add(feesAmount);
if (loanTransactionDTO.getTransactionType().isMerchantIssuedRefund()) {
populateCreditDebitMaps(loanProductId, feesAmount, paymentTypeId,
CashAccountsForLoan.INCOME_FROM_CHARGE_OFF_FEES.getValue(), CashAccountsForLoan.FUND_SOURCE.getValue(),
glAccountBalanceHolder);
} else if (loanTransactionDTO.getTransactionType().isPayoutRefund()) {
populateCreditDebitMaps(loanProductId, feesAmount, paymentTypeId,
CashAccountsForLoan.INCOME_FROM_CHARGE_OFF_FEES.getValue(), CashAccountsForLoan.FUND_SOURCE.getValue(),
glAccountBalanceHolder);
} else if (loanTransactionDTO.getTransactionType().isGoodwillCredit()) {
populateCreditDebitMaps(loanProductId, feesAmount, paymentTypeId, CashAccountsForLoan.INCOME_FROM_RECOVERY.getValue(),
CashAccountsForLoan.INCOME_FROM_GOODWILL_CREDIT_FEES.getValue(), glAccountBalanceHolder);
} else if (loanTransactionDTO.getTransactionType().isRepayment()) {
populateCreditDebitMaps(loanProductId, feesAmount, paymentTypeId, CashAccountsForLoan.INCOME_FROM_RECOVERY.getValue(),
CashAccountsForLoan.FUND_SOURCE.getValue(), glAccountBalanceHolder);
} else {
populateCreditDebitMaps(loanProductId, feesAmount, paymentTypeId, CashAccountsForLoan.INCOME_FROM_FEES.getValue(),
CashAccountsForLoan.FUND_SOURCE.getValue(), glAccountBalanceHolder);
}
}
// handle penalties payment
if (penaltiesAmount != null && penaltiesAmount.compareTo(BigDecimal.ZERO) > 0) {
totalDebitAmount = totalDebitAmount.add(penaltiesAmount);
if (loanTransactionDTO.getTransactionType().isMerchantIssuedRefund()) {
populateCreditDebitMaps(loanProductId, penaltiesAmount, paymentTypeId,
CashAccountsForLoan.INCOME_FROM_CHARGE_OFF_PENALTY.getValue(), CashAccountsForLoan.FUND_SOURCE.getValue(),
glAccountBalanceHolder);
} else if (loanTransactionDTO.getTransactionType().isPayoutRefund()) {
populateCreditDebitMaps(loanProductId, penaltiesAmount, paymentTypeId,
CashAccountsForLoan.INCOME_FROM_CHARGE_OFF_PENALTY.getValue(), CashAccountsForLoan.FUND_SOURCE.getValue(),
glAccountBalanceHolder);
} else if (loanTransactionDTO.getTransactionType().isGoodwillCredit()) {
populateCreditDebitMaps(loanProductId, penaltiesAmount, paymentTypeId, CashAccountsForLoan.INCOME_FROM_RECOVERY.getValue(),
CashAccountsForLoan.INCOME_FROM_GOODWILL_CREDIT_PENALTY.getValue(), glAccountBalanceHolder);
} else if (loanTransactionDTO.getTransactionType().isRepayment()) {
populateCreditDebitMaps(loanProductId, penaltiesAmount, paymentTypeId, CashAccountsForLoan.INCOME_FROM_RECOVERY.getValue(),
CashAccountsForLoan.FUND_SOURCE.getValue(), glAccountBalanceHolder);
} else {
populateCreditDebitMaps(loanProductId, penaltiesAmount, paymentTypeId, CashAccountsForLoan.INCOME_FROM_PENALTIES.getValue(),
CashAccountsForLoan.FUND_SOURCE.getValue(), glAccountBalanceHolder);
}
}
// overpayment
if (overPaymentAmount != null && overPaymentAmount.compareTo(BigDecimal.ZERO) > 0) {
totalDebitAmount = totalDebitAmount.add(overPaymentAmount);
if (loanTransactionDTO.getTransactionType().isMerchantIssuedRefund()) {
populateCreditDebitMaps(loanProductId, overPaymentAmount, paymentTypeId, CashAccountsForLoan.OVERPAYMENT.getValue(),
CashAccountsForLoan.FUND_SOURCE.getValue(), glAccountBalanceHolder);
} else if (loanTransactionDTO.getTransactionType().isPayoutRefund()) {
populateCreditDebitMaps(loanProductId, overPaymentAmount, paymentTypeId, CashAccountsForLoan.OVERPAYMENT.getValue(),
CashAccountsForLoan.FUND_SOURCE.getValue(), glAccountBalanceHolder);
} else if (loanTransactionDTO.getTransactionType().isGoodwillCredit()) {
populateCreditDebitMaps(loanProductId, overPaymentAmount, paymentTypeId, CashAccountsForLoan.OVERPAYMENT.getValue(),
CashAccountsForLoan.GOODWILL_CREDIT.getValue(), glAccountBalanceHolder);
} else {
populateCreditDebitMaps(loanProductId, overPaymentAmount, paymentTypeId, CashAccountsForLoan.OVERPAYMENT.getValue(),
CashAccountsForLoan.FUND_SOURCE.getValue(), glAccountBalanceHolder);
}
}
// create credit entries
for (Map.Entry<Long, BigDecimal> creditEntry : glAccountBalanceHolder.getCreditBalances().entrySet()) {
GLAccount glAccount = glAccountBalanceHolder.getGlAccountMap().get(creditEntry.getKey());
this.helper.createCreditJournalEntryForLoan(office, currencyCode, loanId, transactionId, transactionDate,
creditEntry.getValue(), glAccount);
}
/*** create a single debit entry for the entire amount **/
if (loanTransactionDTO.isLoanToLoanTransfer()) {
this.helper.createDebitJournalEntryForLoan(office, currencyCode, FinancialActivity.ASSET_TRANSFER.getValue(), loanProductId,
paymentTypeId, loanId, transactionId, transactionDate, totalDebitAmount);
} else if (loanTransactionDTO.isAccountTransfer()) {
this.helper.createDebitJournalEntryForLoan(office, currencyCode, FinancialActivity.LIABILITY_TRANSFER.getValue(), loanProductId,
paymentTypeId, loanId, transactionId, transactionDate, totalDebitAmount);
} else {
// create debit entries
for (Map.Entry<Long, BigDecimal> debitEntry : glAccountBalanceHolder.getDebitBalances().entrySet()) {
GLAccount glAccount = glAccountBalanceHolder.getGlAccountMap().get(debitEntry.getKey());
this.helper.createDebitJournalEntryForLoan(office, currencyCode, loanId, transactionId, transactionDate,
debitEntry.getValue(), glAccount);
}
}
/**
* Charge Refunds have an extra refund related pair of journal entries in addition to those related to the
* repayment above
***/
if (totalDebitAmount.compareTo(BigDecimal.ZERO) > 0) {
if (loanTransactionDTO.getTransactionType().isChargeRefund()) {
Integer incomeAccount = this.helper.getValueForFeeOrPenaltyIncomeAccount(loanTransactionDTO.getChargeRefundChargeType());
this.helper.createJournalEntriesForLoan(office, currencyCode, incomeAccount, CashAccountsForLoan.FUND_SOURCE.getValue(),
loanProductId, paymentTypeId, loanId, transactionId, transactionDate, totalDebitAmount);
}
}
}