FINERACT-2322: Extend loan collection data with next due payment amount field
This commit is contained in:
+58
@@ -0,0 +1,58 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.delinquency.service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.infrastructure.core.service.MathUtil;
|
||||
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public abstract class AbstractPossibleNextRepaymentCalculationService implements PossibleNextRepaymentCalculationService {
|
||||
|
||||
@Override
|
||||
public BigDecimal possibleNextRepaymentAmount(Loan loan, LocalDate nextPaymentDueDate) {
|
||||
LoanRepaymentScheduleInstallment nextInstallment = loan.getRelatedRepaymentScheduleInstallment(nextPaymentDueDate);
|
||||
if (nextInstallment == null || nextInstallment.isObligationsMet()) {
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
if (loan.isInterestRecalculationEnabled()
|
||||
// if rest frequency type is same as repayment, then interest values should be on the repayment schedule
|
||||
// correctly.
|
||||
&& !loan.getLoanInterestRecalculationDetails().getRestFrequencyType().isSameAsRepayment()
|
||||
// if charge off, installments already shows correct values, no further calculation is required.
|
||||
&& !loan.isChargeOffOnDate(nextPaymentDueDate)
|
||||
// all strategy works like same as repayment on installment due date.
|
||||
&& nextInstallment.getDueDate().isAfter(ThreadLocalContextUtil.getBusinessDate())
|
||||
// there is no overdue / overdue related to that installment is calculated.
|
||||
&& !nextInstallment.getFromDate().isEqual(ThreadLocalContextUtil.getBusinessDate())
|
||||
&& MathUtil.isGreaterThanZero(loan.getDisbursedAmount())) {
|
||||
// try to predict future outstanding balances with interest recalculation
|
||||
return calculateInterestRecalculationFutureOutstandingValue(loan, nextPaymentDueDate, nextInstallment);
|
||||
}
|
||||
return nextInstallment.getTotalOutstanding(loan.getCurrency()).getAmount();
|
||||
}
|
||||
|
||||
public abstract BigDecimal calculateInterestRecalculationFutureOutstandingValue(Loan loan, LocalDate nextPaymentDueDate,
|
||||
LoanRepaymentScheduleInstallment nextInstallment);
|
||||
|
||||
}
|
||||
+7
@@ -81,6 +81,7 @@ public class DelinquencyReadPlatformServiceImpl implements DelinquencyReadPlatfo
|
||||
private final DelinquencyEffectivePauseHelper delinquencyEffectivePauseHelper;
|
||||
private final ConfigurationDomainService configurationDomainService;
|
||||
private final LoanTransactionRepository loanTransactionRepository;
|
||||
private final PossibleNextRepaymentCalculationServiceDiscovery possibleNextRepaymentCalculationServiceDiscovery;
|
||||
|
||||
@Override
|
||||
public List<DelinquencyRangeData> retrieveAllDelinquencyRanges() {
|
||||
@@ -152,6 +153,12 @@ public class DelinquencyReadPlatformServiceImpl implements DelinquencyReadPlatfo
|
||||
collectionData = loanDelinquencyDomainService.getOverdueCollectionData(loan, effectiveDelinquencyList);
|
||||
collectionData.setAvailableDisbursementAmount(calculateAvailableDisbursementAmount(loan));
|
||||
collectionData.setNextPaymentDueDate(possibleNextRepaymentDate(nextPaymentDueDateConfig, loan));
|
||||
PossibleNextRepaymentCalculationService possibleNextRepaymentCalculationService = possibleNextRepaymentCalculationServiceDiscovery
|
||||
.getService(loan);
|
||||
if (possibleNextRepaymentCalculationService != null) {
|
||||
collectionData.setNextPaymentAmount(
|
||||
possibleNextRepaymentCalculationService.possibleNextRepaymentAmount(loan, collectionData.getNextPaymentDueDate()));
|
||||
}
|
||||
|
||||
final LoanTransaction lastPayment = loan.getLastPaymentTransaction();
|
||||
if (lastPayment != null) {
|
||||
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.delinquency.service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||
|
||||
public interface PossibleNextRepaymentCalculationService {
|
||||
|
||||
boolean canAccept(Loan loan);
|
||||
|
||||
BigDecimal possibleNextRepaymentAmount(Loan loan, LocalDate nextPaymentDueDate);
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.delinquency.service;
|
||||
|
||||
import java.util.List;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@AllArgsConstructor
|
||||
@Service
|
||||
public class PossibleNextRepaymentCalculationServiceDiscovery {
|
||||
|
||||
private final List<PossibleNextRepaymentCalculationService> services;
|
||||
|
||||
public PossibleNextRepaymentCalculationService getService(final Loan loan) {
|
||||
return services.stream().filter(s -> s.canAccept(loan)).findAny().orElse(null);
|
||||
}
|
||||
}
|
||||
+4
-2
@@ -37,6 +37,7 @@ import org.apache.fineract.portfolio.delinquency.service.DelinquencyWritePlatfor
|
||||
import org.apache.fineract.portfolio.delinquency.service.DelinquencyWritePlatformServiceImpl;
|
||||
import org.apache.fineract.portfolio.delinquency.service.LoanDelinquencyDomainService;
|
||||
import org.apache.fineract.portfolio.delinquency.service.LoanDelinquencyDomainServiceImpl;
|
||||
import org.apache.fineract.portfolio.delinquency.service.PossibleNextRepaymentCalculationServiceDiscovery;
|
||||
import org.apache.fineract.portfolio.delinquency.validator.DelinquencyActionParseAndValidator;
|
||||
import org.apache.fineract.portfolio.delinquency.validator.DelinquencyBucketParseAndValidator;
|
||||
import org.apache.fineract.portfolio.delinquency.validator.DelinquencyRangeParseAndValidator;
|
||||
@@ -62,11 +63,12 @@ public class DelinquencyConfiguration {
|
||||
LoanInstallmentDelinquencyTagRepository repositoryLoanInstallmentDelinquencyTag,
|
||||
LoanDelinquencyActionRepository loanDelinquencyActionRepository,
|
||||
DelinquencyEffectivePauseHelper delinquencyEffectivePauseHelper, ConfigurationDomainService configurationDomainService,
|
||||
LoanTransactionRepository loanTransactionRepository) {
|
||||
LoanTransactionRepository loanTransactionRepository,
|
||||
PossibleNextRepaymentCalculationServiceDiscovery possibleNextRepaymentCalculationService) {
|
||||
return new DelinquencyReadPlatformServiceImpl(repositoryRange, repositoryBucket, repositoryLoanDelinquencyTagHistory, mapperRange,
|
||||
mapperBucket, mapperLoanDelinquencyTagHistory, loanRepository, loanDelinquencyDomainService,
|
||||
repositoryLoanInstallmentDelinquencyTag, loanDelinquencyActionRepository, delinquencyEffectivePauseHelper,
|
||||
configurationDomainService, loanTransactionRepository);
|
||||
configurationDomainService, loanTransactionRepository, possibleNextRepaymentCalculationService);
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
+2
-1
@@ -31,6 +31,7 @@ public final class CollectionData {
|
||||
private BigDecimal availableDisbursementAmount;
|
||||
private Long pastDueDays;
|
||||
private LocalDate nextPaymentDueDate;
|
||||
private BigDecimal nextPaymentAmount;
|
||||
private Long delinquentDays;
|
||||
private LocalDate delinquentDate;
|
||||
private BigDecimal delinquentAmount;
|
||||
@@ -50,7 +51,7 @@ public final class CollectionData {
|
||||
|
||||
public static CollectionData template() {
|
||||
final BigDecimal zero = BigDecimal.ZERO;
|
||||
return new CollectionData(zero, 0L, null, 0L, null, zero, null, zero, null, zero, null, null, zero, zero, zero, zero);
|
||||
return new CollectionData(zero, 0L, null, zero, 0L, null, zero, null, zero, null, zero, null, null, zero, zero, zero, zero);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1403,7 +1403,6 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom<Long> {
|
||||
* @return a schedule installment is related to the provided date
|
||||
**/
|
||||
public LoanRepaymentScheduleInstallment getRelatedRepaymentScheduleInstallment(LocalDate date) {
|
||||
// TODO first installment should be fromInclusive
|
||||
return getRepaymentScheduleInstallment(e -> DateUtils.isDateInRangeFromExclusiveToInclusive(date, e.getFromDate(), e.getDueDate()));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user