Skip to content
Draft
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 @@ -1462,7 +1462,7 @@ periodNumberTemp, mc, mergeVariationsToMap(loanApplicationTerms, params), params
}
}

if (!outstanding.isZero()) {
if (!outstanding.isZero() || !params.getLatePaymentMap().isEmpty()) {
PrincipalInterest principalInterestForThisPeriod = calculatePrincipalInterestComponentsForPeriod(
getPaymentPeriodsInOneYearCalculator(), interestCalculationGraceOnRepaymentPeriodFraction, totalInterest.zero(),
totalInterest.zero(), totalInterest.zero(), totalInterest.zero(), outstanding, loanApplicationTerms,
Expand Down Expand Up @@ -1499,7 +1499,8 @@ periodNumberTemp, mc, mergeVariationsToMap(loanApplicationTerms, params), params
}
}
params.setPeriodStartDate(params.getActualRepaymentDate());
} while (DateUtils.isBefore(params.getActualRepaymentDate(), currentDate) && !outstanding.isZero());
} while (DateUtils.isBefore(params.getActualRepaymentDate(), currentDate)
&& (!outstanding.isZero() || !params.getLatePaymentMap().isEmpty()));

if (totalInterest.isGreaterThanZero()) {
LoanScheduleModelRepaymentPeriod installment = LoanScheduleModelRepaymentPeriod.repayment(params.getInstalmentNumber(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,11 @@ private void addInterestAccrual(@NonNull final Loan loan, @NonNull final LocalDa
final boolean isInPeriod = isInPeriod(tillDate, installment, false);
if (isPastPeriod || loan.isClosed() || loanBalanceService.isOverPaid(loan)) {
interest = installment.getInterestCharged(currency).minus(installment.getCreditedInterest());
if (loan.isClosed()) {
Money interestSettled = installment.getInterestPaid(currency).plus(installment.getInterestWaived(currency))
.plus(installment.getInterestWrittenOff(currency));
interest = MathUtil.min(interest, interestSettled, false);
}
} else {
if (isInPeriod) { // first period first day is not accrued
interest = scheduleGenerator.getPeriodInterestTillDate(installment, tillDate);
Expand All @@ -516,6 +521,10 @@ private void addInterestAccrual(@NonNull final Loan loan, @NonNull final LocalDa
period.setTransactionAccrued(transactionAccrued);
final Money accrued = MathUtil.minusToZero(transactionAccrued, transactionWaived);
period.setInterestAccrued(accrued);
if (loan.isClosed() && accruable != null && accrued != null) {
accruable = MathUtil.min(accruable, accrued, false);
period.setInterestAccruable(accruable);
}
}

@NonNull
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import org.apache.fineract.client.feign.FineractFeignClient;
import org.apache.fineract.client.models.GetLoansLoanIdResponse;
import org.apache.fineract.client.models.GetLoansLoanIdStatus;
import org.apache.fineract.client.models.GetLoansLoanIdTransactionsTemplateResponse;
import org.apache.fineract.client.models.PostLoanProductsRequest;
import org.apache.fineract.client.models.PostLoansLoanIdRequest;
import org.apache.fineract.client.models.PostLoansLoanIdTransactionsRequest;
Expand Down Expand Up @@ -97,6 +98,10 @@ protected Long createClient() {
return clientHelper.createClient();
}

protected Long createClient(String activationDate) {
return clientHelper.createClient(activationDate);
}

protected Long createLoanProduct(PostLoanProductsRequest request) {
return loanHelper.createLoanProduct(request);
}
Expand Down Expand Up @@ -219,4 +224,12 @@ protected PostLoansLoanIdTransactionsRequest waiveInterest(double amount, String
protected PostLoansLoanIdTransactionsRequest chargeOff(String date) {
return LoanRequestBuilders.chargeOff(date);
}

protected void executeInlineCOB(Long loanId) {
transactionHelper.executeInlineCOB(loanId);
}

protected GetLoansLoanIdTransactionsTemplateResponse getPrepaymentAmount(Long loanId, String transactionDate, String dateFormat) {
return transactionHelper.getPrepaymentAmount(loanId, transactionDate, dateFormat);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,14 @@

public class FeignBusinessDateHelper {

private static final String ENABLE_BUSINESS_DATE = "enable-business-date";

private final FineractFeignClient fineractClient;
private final FeignGlobalConfigurationHelper configHelper;

public FeignBusinessDateHelper(FineractFeignClient fineractClient) {
this.fineractClient = fineractClient;
this.configHelper = new FeignGlobalConfigurationHelper(fineractClient);
}

public BusinessDateResponse getBusinessDate(String type) {
Expand All @@ -49,14 +53,12 @@ public void updateBusinessDate(String type, String date) {
}

public void runAt(String date, Runnable action) {
BusinessDateResponse originalDate = getBusinessDate("BUSINESS_DATE");
try {
configHelper.updateConfigurationByName(ENABLE_BUSINESS_DATE, true);
updateBusinessDate("BUSINESS_DATE", date);
action.run();
} finally {
if (originalDate != null && originalDate.getDate() != null) {
updateBusinessDate("BUSINESS_DATE", originalDate.getDate().toString());
}
configHelper.updateConfigurationByName(ENABLE_BUSINESS_DATE, false);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,11 @@ public FeignClientHelper(FineractFeignClient fineractClient) {
}

public Long createClient() {
return createClient(Utils.dateFormatter.format(Utils.getLocalDateOfTenant()));
}

public Long createClient(String activationDate) {
String externalId = Utils.randomStringGenerator("EXT_", 7);
String activationDate = Utils.dateFormatter.format(Utils.getLocalDateOfTenant());

PostClientsRequest request = new PostClientsRequest()//
.officeId(1L)//
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,11 @@

import static org.apache.fineract.client.feign.util.FeignCalls.ok;

import java.util.List;
import java.util.Map;
import org.apache.fineract.client.feign.FineractFeignClient;
import org.apache.fineract.client.models.GetLoansLoanIdTransactionsTemplateResponse;
import org.apache.fineract.client.models.InlineJobRequest;
import org.apache.fineract.client.models.PostLoansLoanIdTransactionsRequest;
import org.apache.fineract.client.models.PostLoansLoanIdTransactionsResponse;
import org.apache.fineract.client.models.PostLoansLoanIdTransactionsTransactionIdRequest;
Expand All @@ -34,6 +37,16 @@ public FeignTransactionHelper(FineractFeignClient fineractClient) {
this.fineractClient = fineractClient;
}

public void executeInlineCOB(Long loanId) {
InlineJobRequest request = new InlineJobRequest().loanIds(List.of(loanId));
ok(() -> fineractClient.inlineJob().executeInlineJob("LOAN_COB", request));
}

public GetLoansLoanIdTransactionsTemplateResponse getPrepaymentAmount(Long loanId, String transactionDate, String dateFormat) {
return ok(() -> fineractClient.loanTransactions().retrieveTransactionTemplate(loanId, "prepayLoan", dateFormat, transactionDate,
"en", null));
}

public Long addRepayment(Long loanId, PostLoansLoanIdTransactionsRequest request) {
PostLoansLoanIdTransactionsResponse response = ok(
() -> fineractClient.loanTransactions().executeLoanTransaction(loanId, request, Map.of("command", "repayment")));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,18 @@ default PostLoanProductsRequest fourInstallmentsCumulativeTemplate() {
LoanProductTestBuilder.DUE_PENALTY_FEE_INTEREST_PRINCIPAL_IN_ADVANCE_PRINCIPAL_PENALTY_FEE_INTEREST_STRATEGY);
}

default PostLoanProductsRequest fourInstallmentsCumulativeWithInterestRecalculation() {
return fourInstallmentsCumulativeTemplate()//
.loanScheduleType(LoanScheduleType.CUMULATIVE.toString())//
.isInterestRecalculationEnabled(true)//
.interestRecalculationCompoundingMethod(0)//
.rescheduleStrategyMethod(RescheduleStrategyMethod.REDUCE_EMI_AMOUNT)//
.recalculationRestFrequencyType(1)//
.recalculationRestFrequencyInterval(0)//
.preClosureInterestCalculationStrategy(1)//
.enableAccrualActivityPosting(true);
}

default PostLoanProductsRequest customizeProduct(PostLoanProductsRequest template,
Function<PostLoanProductsRequest, PostLoanProductsRequest> customizer) {
return customizer.apply(template);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public static PostLoansRequest applyCumulativeLoan(Long clientId, Long productId
.amortizationType(LoanTestData.AmortizationType.EQUAL_INSTALLMENTS)//
.interestType(LoanTestData.InterestType.DECLINING_BALANCE)//
.interestCalculationPeriodType(LoanTestData.InterestCalculationPeriodType.DAILY)//
.transactionProcessingStrategyCode("DUE_PENALTY_FEE_INTEREST_PRINCIPAL_IN_ADVANCE_PRINCIPAL_PENALTY_FEE_INTEREST_STRATEGY")//
.transactionProcessingStrategyCode("due-penalty-fee-interest-principal-in-advance-principal-penalty-fee-interest-strategy")//
.loanType("individual")//
.locale(LoanTestData.LOCALE)//
.dateFormat(LoanTestData.DATETIME_PATTERN);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ public static class OutstandingAmounts {

public static final class AmortizationType {

public static final Integer EQUAL_PRINCIPAL = 0;
public static final Integer EQUAL_INSTALLMENTS = 1;

private AmortizationType() {}
Expand Down
Loading
Loading