Skip to content

Commit 6d79e2e

Browse files
FINERACT-2421: Allow ProgressiveLoanInterestScheduleModel recalculation
Co-authored-by: Soma Sörös <soma.soros@dpc.hu>
1 parent 76df848 commit 6d79e2e

File tree

25 files changed

+558
-10
lines changed

25 files changed

+558
-10
lines changed

fineract-e2e-tests-core/src/test/java/org/apache/fineract/test/stepdef/loan/LoanStepDef.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5926,6 +5926,13 @@ public void inLoanTransactionsTheThTransactionOfOnHasRelationshipWithTypeREPLAYE
59265926
assertEquals(Integer.valueOf(numberOfRelations), relationshipOptional.size(), "Missed relationship for transaction");
59275927
}
59285928

5929+
@When("Call Internal API to remove progressive loan model by loan Id")
5930+
public void callInternalAPIToRemoveProgressiveLoanModelByLoanId() {
5931+
final PostLoansResponse loanCreateResponse = testContext().get(TestContextKey.LOAN_CREATE_RESPONSE);
5932+
final long loanId = loanCreateResponse.getLoanId();
5933+
ok(() -> fineractClient.progressiveLoan().deleteModel(loanId));
5934+
}
5935+
59295936
public static AdvancedPaymentData editPaymentAllocationFutureInstallment(String transactionType, String futureInstallmentAllocationRule,
59305937
List<PaymentAllocationOrder> paymentAllocationOrder) {
59315938
AdvancedPaymentData advancedPaymentData = new AdvancedPaymentData();

fineract-e2e-tests-runner/src/test/resources/features/LoanAccrualTransaction.feature

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1619,6 +1619,7 @@ Feature: LoanAccrualTransaction
16191619
| 01 January 2024 | Disbursement | 100.0 | 0.0 | 0.0 | 0.0 | 0.0 | 100.0 | false | false |
16201620
# --- Early repayment with 17.01 EUR on 15 Jan ---
16211621
When Admin sets the business date to "15 January 2024"
1622+
When Call Internal API to remove progressive loan model by loan Id
16221623
When Admin makes "MERCHANT_ISSUED_REFUND" transaction with "AUTOPAY" payment type on "15 January 2024" with 17.01 EUR transaction amount
16231624
Then Loan Repayment schedule has 6 periods, with the following data for periods:
16241625
| Nr | Days | Date | Paid date | Balance of loan | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |
@@ -1660,6 +1661,7 @@ Feature: LoanAccrualTransaction
16601661
| 01 May 2024 | Accrual Activity | 0.48 | 0.0 | 0.48 | 0.0 | 0.0 | 0.0 | false | false |
16611662
| 31 May 2024 | Accrual | 1.87 | 0.0 | 1.87 | 0.0 | 0.0 | 0.0 | false | false |
16621663
When Admin sets the business date to "02 June 2024"
1664+
When Call Internal API to remove progressive loan model by loan Id
16631665
And Admin runs inline COB job for Loan
16641666
Then Loan Repayment schedule has 6 periods, with the following data for periods:
16651667
| Nr | Days | Date | Paid date | Balance of loan | Principal due | Interest | Fees | Penalties | Due | Paid | In advance | Late | Outstanding |

fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepository.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,4 +279,10 @@ List<Loan> findLoansForAddAccrual(@Param("accountingType") AccountingRuleType ac
279279
@Query(FIND_ALL_LOANS_BEHIND_ON_DISBURSEMENT_DATE)
280280
List<COBIdAndLastClosedBusinessDate> findAllLoansBehindOnDisbursementDate(@Param("cobBusinessDate") LocalDate cobBusinessDate,
281281
@Param("loanIds") List<Long> loanIds, @Param("loanStatuses") Collection<LoanStatus> loanStatuses);
282+
283+
@Query("SELECT CASE WHEN COUNT(l) > 0 THEN TRUE ELSE FALSE END FROM Loan l WHERE l.id = :loanId and l.loanRepaymentScheduleDetail.loanScheduleType = org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleType.PROGRESSIVE")
284+
Boolean isProgressiveLoan(@Param("loanId") Long loanId);
285+
286+
@Query("SELECT CASE WHEN COUNT(l) > 0 THEN TRUE ELSE FALSE END FROM Loan l WHERE l.id = :loanId and l.loanStatus in :allowedLoanStatuses")
287+
Boolean isLoanInAllowedStatus(@Param("loanId") Long loanId, @Param("allowedLoanStatuses") List<LoanStatus> allowedLoanStatuses);
282288
}

fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepositoryWrapper.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,4 +313,8 @@ public boolean existsByLoanId(Long loanId) {
313313
public boolean isEnabledCapitalizedIncome(Long loanId) {
314314
return repository.isEnabledCapitalizedIncome(loanId);
315315
}
316+
317+
public boolean isLoanInAllowedStatus(Long loanId, List<LoanStatus> allowedLoanStatuses) {
318+
return repository.isLoanInAllowedStatus(loanId, allowedLoanStatuses);
319+
}
316320
}

fineract-progressive-loan-embeddable-schedule-generator/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/EmbeddableProgressiveLoanScheduleGenerator.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,5 +83,10 @@ public boolean hasValidModelForDate(Long loanId, LocalDate targetDate) {
8383
public Optional<ProgressiveLoanInterestScheduleModel> getSavedModel(Loan loan, LocalDate businessDate) {
8484
return Optional.empty();
8585
}
86+
87+
@Override
88+
public Long removeByLoanId(Long loanId) {
89+
return 0L;
90+
}
8691
}
8792
}

fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/ProgressiveLoanModel.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,4 +52,7 @@ public class ProgressiveLoanModel extends AbstractPersistableCustom<Long> {
5252
@Column(name = "last_modified_on_utc", nullable = false)
5353
private OffsetDateTime lastModifiedDate;
5454

55+
@Column(name = "json_model_version", nullable = false)
56+
private String jsonModelVersion;
57+
5558
}

fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/repository/ProgressiveLoanModelRepository.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,18 @@
2323
import org.apache.fineract.portfolio.loanaccount.domain.ProgressiveLoanModel;
2424
import org.springframework.data.jpa.repository.JpaRepository;
2525
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
26+
import org.springframework.data.jpa.repository.Query;
27+
import org.springframework.data.repository.query.Param;
2628

2729
public interface ProgressiveLoanModelRepository
2830
extends JpaSpecificationExecutor<ProgressiveLoanModel>, JpaRepository<ProgressiveLoanModel, Long> {
2931

3032
Optional<ProgressiveLoanModel> findOneByLoanId(Long loanId);
3133

3234
Optional<ProgressiveLoanModel> findOneByLoan(Loan loan);
35+
36+
Long removeByLoanId(Long loanId);
37+
38+
@Query("SELECT CASE WHEN COUNT(plm) > 0 THEN TRUE ELSE FALSE END FROM ProgressiveLoanModel plm WHERE plm.loan.id = :loanId AND plm.jsonModelVersion = :modelVersion")
39+
Boolean hasValidModel(@Param("loanId") Long loanId, @Param("modelVersion") String modelVersion);
3340
}

fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/InterestScheduleModelRepositoryWrapper.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,6 @@ Optional<ProgressiveLoanInterestScheduleModel> readProgressiveLoanInterestSchedu
4141
boolean hasValidModelForDate(Long loanId, LocalDate targetDate);
4242

4343
Optional<ProgressiveLoanInterestScheduleModel> getSavedModel(Loan loan, LocalDate businessDate);
44+
45+
Long removeByLoanId(Long loanId);
4446
}

fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/InterestScheduleModelRepositoryWrapperImpl.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,11 +61,13 @@ public ProgressiveLoanInterestScheduleModel writeInterestScheduleModel(Loan loan
6161
ProgressiveLoanModel progressiveLoanModel = loanModelRepository.findOneByLoanId(loan.getId()).orElseGet(() -> {
6262
ProgressiveLoanModel plm = new ProgressiveLoanModel();
6363
plm.setLoan(loan);
64+
plm.setJsonModelVersion(ProgressiveLoanInterestScheduleModel.getModelVersion());
6465
return plm;
6566
});
6667
progressiveLoanModel.setBusinessDate(ThreadLocalContextUtil.getBusinessDate());
6768
progressiveLoanModel.setLastModifiedDate(DateUtils.getAuditOffsetDateTime());
6869
progressiveLoanModel.setJsonModel(jsonModel);
70+
progressiveLoanModel.setJsonModelVersion(ProgressiveLoanInterestScheduleModel.getModelVersion());
6971
loanModelRepository.save(progressiveLoanModel);
7072
});
7173
return model;
@@ -133,4 +135,9 @@ public Optional<ProgressiveLoanInterestScheduleModel> readProgressiveLoanInteres
133135
.map(jsonModel -> progressiveLoanInterestScheduleModelParserService.fromJson(jsonModel, detail,
134136
MoneyHelper.getMathContext(), installmentAmountInMultipliesOf)); //
135137
}
138+
139+
@Override
140+
public Long removeByLoanId(Long loanId) {
141+
return loanModelRepository.removeByLoanId(loanId);
142+
}
136143
}

fineract-progressive-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/InternalProgressiveLoanApiResource.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import io.swagger.v3.oas.annotations.Operation;
2323
import io.swagger.v3.oas.annotations.Parameter;
2424
import io.swagger.v3.oas.annotations.tags.Tag;
25+
import jakarta.ws.rs.DELETE;
2526
import jakarta.ws.rs.GET;
2627
import jakarta.ws.rs.POST;
2728
import jakarta.ws.rs.Path;
@@ -99,4 +100,13 @@ public ProgressiveLoanInterestScheduleModel updateModel(@PathParam("loanId") @Pa
99100

100101
return writePlatformService.writeInterestScheduleModel(loan, model);
101102
}
103+
104+
@DELETE
105+
@Path("{loanId}/model")
106+
@Produces({ MediaType.APPLICATION_JSON })
107+
@Operation(summary = "Delete ProgressiveLoanInterestScheduleModel By Loan ID", description = "DO NOT USE THIS IN PRODUCTION!")
108+
@Transactional
109+
public Long deleteModel(@PathParam("loanId") @Parameter(description = "loanId") long loanId) {
110+
return writePlatformService.removeByLoanId(loanId);
111+
}
102112
}

0 commit comments

Comments
 (0)