Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FINERACT-2042 Credit Allocation for Principal and Interest components #3732

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,9 @@ protected LoanTransactionRelation(@NotNull LoanTransaction fromTransaction, Loan

public static LoanTransactionRelation linkToTransaction(@NotNull LoanTransaction fromTransaction,
@NotNull LoanTransaction toTransaction, LoanTransactionRelationTypeEnum relation) {
return new LoanTransactionRelation(fromTransaction, toTransaction, null, relation);
LoanTransactionRelation loanTransactionRelation = new LoanTransactionRelation(fromTransaction, toTransaction, null, relation);
fromTransaction.getLoanTransactionRelations().add(loanTransactionRelation);
return loanTransactionRelation;
}

public static LoanTransactionRelation linkToCharge(@NotNull LoanTransaction fromTransaction, @NotNull LoanCharge loanCharge,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -474,7 +474,7 @@ protected void createNewTransaction(LoanTransaction loanTransaction, LoanTransac

}

private void processCreditTransaction(LoanTransaction loanTransaction, MoneyHolder overpaymentHolder, MonetaryCurrency currency,
protected void processCreditTransaction(LoanTransaction loanTransaction, MoneyHolder overpaymentHolder, MonetaryCurrency currency,
List<LoanRepaymentScheduleInstallment> installments) {
loanTransaction.resetDerivedComponents();
List<LoanTransactionToRepaymentScheduleMapping> transactionMappings = new ArrayList<>();
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -430,11 +430,12 @@ private void createJournalEntriesForChargeback(LoanDTO loanDTO, LoanTransactionD
final BigDecimal overpaidAmount = Objects.isNull(loanTransactionDTO.getOverPayment()) ? BigDecimal.ZERO
: loanTransactionDTO.getOverPayment();

if (BigDecimal.ZERO.compareTo(overpaidAmount) == 0) {
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) {
} 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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
import org.apache.fineract.portfolio.loanaccount.domain.LoanCharge;
import org.apache.fineract.portfolio.loanaccount.domain.LoanCollateralManagement;
import org.apache.fineract.portfolio.loanaccount.domain.LoanCreditAllocationRule;
import org.apache.fineract.portfolio.loanaccount.domain.LoanDisbursementDetails;
import org.apache.fineract.portfolio.loanaccount.domain.LoanLifecycleStateMachine;
import org.apache.fineract.portfolio.loanaccount.domain.LoanPaymentAllocationRule;
Expand Down Expand Up @@ -390,6 +391,12 @@ private void copyAdvancedPaymentRulesIfApplicable(String transactionProcessingSt
r.getFutureInstallmentAllocationRule()))
.toList();
loanApplication.setPaymentAllocationRules(loanPaymentAllocationRules);

if (loanProduct.getCreditAllocationRules() != null && loanProduct.getCreditAllocationRules().size() > 0) {
List<LoanCreditAllocationRule> loanCreditAllocationRules = loanProduct.getCreditAllocationRules().stream()
.map(r -> new LoanCreditAllocationRule(loanApplication, r.getTransactionType(), r.getAllocationTypes())).toList();
loanApplication.setCreditAllocationRules(loanCreditAllocationRules);
}
}
}
}

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@
import org.apache.fineract.client.models.PostLoansLoanIdRequest;
import org.apache.fineract.client.models.PostLoansLoanIdResponse;
import org.apache.fineract.client.models.PostLoansLoanIdTransactionsRequest;
import org.apache.fineract.client.models.PostLoansLoanIdTransactionsResponse;
import org.apache.fineract.client.models.PostLoansLoanIdTransactionsTransactionIdRequest;
import org.apache.fineract.client.models.PostLoansRequest;
import org.apache.fineract.client.models.PostLoansResponse;
import org.apache.fineract.client.util.CallFailedRuntimeException;
Expand Down Expand Up @@ -335,7 +337,7 @@ protected void verifyTransactions(Long loanId, TransactionExt... transactions) {
&& Objects.equals(item.getPenaltyChargesPortion(), tr.penaltyPortion) //
&& Objects.equals(item.getUnrecognizedIncomePortion(), tr.unrecognizedPortion) //
);
Assertions.assertTrue(found, "Required transaction not found: " + tr);
Assertions.assertTrue(found, "Required transaction not found: " + tr);
});
}
}
Expand Down Expand Up @@ -414,6 +416,14 @@ protected void verifyRepaymentSchedule(Long loanId, Installment... installments)
"%d. installment's fee charges due is different, expected: %.2f, actual: %.2f".formatted(i, feeAmount, feeDue));
}

Double penaltyAmount = installments[i].penaltyAmount;
Double penaltyDue = period.getPenaltyChargesDue();
if (penaltyAmount != null) {
Assertions.assertEquals(penaltyAmount, penaltyDue,
"%d. installment's penalty charges due is different, expected: %.2f, actual: %.2f".formatted(i, penaltyAmount,
penaltyDue));
}

Double outstandingAmount = installments[i].totalOutstandingAmount;
Double totalOutstanding = period.getTotalOutstandingForPeriod();
if (outstandingAmount != null) {
Expand Down Expand Up @@ -497,10 +507,17 @@ protected Long applyAndApproveLoan(Long clientId, Long loanProductId, String loa
return applyAndApproveLoan(clientId, loanProductId, loanDisbursementDate, amount, 1);
}

protected void addRepaymentForLoan(Long loanId, Double amount, String date) {
protected Long addRepaymentForLoan(Long loanId, Double amount, String date) {
String firstRepaymentUUID = UUID.randomUUID().toString();
loanTransactionHelper.makeLoanRepayment(loanId, new PostLoansLoanIdTransactionsRequest().dateFormat(DATETIME_PATTERN)
.transactionDate(date).locale("en").transactionAmount(amount).externalId(firstRepaymentUUID));
PostLoansLoanIdTransactionsResponse response = loanTransactionHelper.makeLoanRepayment(loanId,
new PostLoansLoanIdTransactionsRequest().dateFormat(DATETIME_PATTERN).transactionDate(date).locale("en")
.transactionAmount(amount).externalId(firstRepaymentUUID));
return response.getResourceId();
}

protected void addChargebackForLoan(Long loanId, Long transactionId, Double amount) {
loanTransactionHelper.chargebackLoanTransaction(loanId, transactionId,
new PostLoansLoanIdTransactionsTransactionIdRequest().locale("en").transactionAmount(amount).paymentTypeId(1L));
}

protected PostChargesResponse createCharge(Double amount) {
Expand Down Expand Up @@ -538,17 +555,22 @@ protected TransactionExt transaction(double amount, String type, String date, do
}

protected Installment installment(double principalAmount, Boolean completed, String dueDate) {
return new Installment(principalAmount, null, null, null, completed, dueDate);
return new Installment(principalAmount, null, null, null, null, completed, dueDate);
}

protected Installment installment(double principalAmount, double interestAmount, double totalOutstandingAmount, Boolean completed,
String dueDate) {
return new Installment(principalAmount, interestAmount, null, totalOutstandingAmount, completed, dueDate);
return new Installment(principalAmount, interestAmount, null, null, totalOutstandingAmount, completed, dueDate);
}

protected Installment installment(double principalAmount, double interestAmount, double feeAmount, double totalOutstandingAmount,
Boolean completed, String dueDate) {
return new Installment(principalAmount, interestAmount, feeAmount, totalOutstandingAmount, completed, dueDate);
return new Installment(principalAmount, interestAmount, feeAmount, null, totalOutstandingAmount, completed, dueDate);
}

protected Installment installment(double principalAmount, double interestAmount, double feeAmount, double penaltyAmount,
double totalOutstandingAmount, Boolean completed, String dueDate) {
return new Installment(principalAmount, interestAmount, feeAmount, penaltyAmount, totalOutstandingAmount, completed, dueDate);
}

protected BatchRequestBuilder batchRequest() {
Expand Down Expand Up @@ -655,6 +677,7 @@ public static class Installment {
Double principalAmount;
Double interestAmount;
Double feeAmount;
Double penaltyAmount;
Double totalOutstandingAmount;
Boolean completed;
String dueDate;
Expand Down
Loading
Loading