Skip to content

Commit 2d390ba

Browse files
authored
Merge pull request #5718
FINERACT-2455: WC delinquency RESCHEDULE action to change minimum payment amount and frequency
2 parents 5fa483a + 9fe5da3 commit 2d390ba

17 files changed

Lines changed: 1403 additions & 65 deletions

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

Lines changed: 309 additions & 0 deletions
Large diffs are not rendered by default.

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -863,9 +863,18 @@ private void createWorkingCapitalLoanAccount(final List<String> loanData) {
863863
final PostWorkingCapitalLoansResponse response = ok(
864864
() -> fineractClient.workingCapitalLoans().submitWorkingCapitalLoanApplication(loansRequest));
865865
testContext().set(TestContextKey.LOAN_CREATE_RESPONSE, response);
866+
trackLoanIdIfEnabled(response.getLoanId());
866867
log.info("Working Capital Loan created with ID: {}", response.getLoanId());
867868
}
868869

870+
@SuppressWarnings("unchecked")
871+
private void trackLoanIdIfEnabled(final Long loanId) {
872+
final List<Long> trackedIds = testContext().get(TestContextKey.WC_LOAN_IDS);
873+
if (trackedIds != null) {
874+
trackedIds.add(loanId);
875+
}
876+
}
877+
869878
private void modifyWorkingCapitalLoanAccount(final List<String> loanData) {
870879
final PutWorkingCapitalLoansLoanIdRequest modifyRequest = buildModifyLoanRequest(loanData);
871880

@@ -945,6 +954,11 @@ private Long extractClientId() {
945954
}
946955

947956
private Long resolveLoanProductId(final String loanProductName) {
957+
if ("WCLP_DELINQUENCY".equals(loanProductName)) {
958+
final PostWorkingCapitalLoanProductsResponse response = testContext()
959+
.get(TestContextKey.WORKING_CAPITAL_LOAN_PRODUCT_CREATE_RESPONSE);
960+
return response.getResourceId();
961+
}
948962
final DefaultWorkingCapitalLoanProduct product = DefaultWorkingCapitalLoanProduct.valueOf(loanProductName);
949963
return workingCapitalLoanProductResolver.resolve(product);
950964
}

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

Lines changed: 650 additions & 0 deletions
Large diffs are not rendered by default.

fineract-loan/src/main/java/org/apache/fineract/portfolio/delinquency/domain/DelinquencyAction.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,6 @@
2020

2121
public enum DelinquencyAction {
2222
PAUSE, //
23-
RESUME //
23+
RESUME, //
24+
RESCHEDULE //
2425
}

fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/api/WorkingCapitalLoanDelinquencyActionApiResource.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ public class WorkingCapitalLoanDelinquencyActionApiResource {
6666
@Path("{loanId}/delinquency-actions")
6767
@Consumes({ MediaType.APPLICATION_JSON })
6868
@Produces({ MediaType.APPLICATION_JSON })
69-
@Operation(summary = "Create Delinquency Pause Action", description = "Creates a delinquency pause action for a Working Capital loan, extending the active delinquency range period and shifting future periods by the pause duration.")
69+
@Operation(summary = "Create Delinquency Action", description = "Creates a delinquency action (pause or reschedule) for a Working Capital loan.")
7070
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = WorkingCapitalLoanDelinquencyActionApiResourceSwagger.PostWorkingCapitalLoansDelinquencyActionRequest.class)))
7171
@ApiResponses({
7272
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = WorkingCapitalLoanDelinquencyActionApiResourceSwagger.PostWorkingCapitalLoansDelinquencyActionResponse.class))),
@@ -86,7 +86,7 @@ public CommandProcessingResult createDelinquencyAction(@PathParam("loanId") @Par
8686
@Path("external-id/{loanExternalId}/delinquency-actions")
8787
@Consumes({ MediaType.APPLICATION_JSON })
8888
@Produces({ MediaType.APPLICATION_JSON })
89-
@Operation(operationId = "createDelinquencyActionByExternalId", summary = "Create Delinquency Pause Action by external id", description = "Creates a delinquency pause action for a Working Capital loan identified by external id, extending the active delinquency range period and shifting future periods by the pause duration.")
89+
@Operation(operationId = "createDelinquencyActionByExternalId", summary = "Create Delinquency Action by external id", description = "Creates a delinquency action (pause or reschedule) for a Working Capital loan identified by external id.")
9090
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = WorkingCapitalLoanDelinquencyActionApiResourceSwagger.PostWorkingCapitalLoansDelinquencyActionRequest.class)))
9191
@ApiResponses({
9292
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = WorkingCapitalLoanDelinquencyActionApiResourceSwagger.PostWorkingCapitalLoansDelinquencyActionResponse.class))),

fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/api/WorkingCapitalLoanDelinquencyActionApiResourceSwagger.java

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
package org.apache.fineract.portfolio.workingcapitalloan.api;
2020

2121
import io.swagger.v3.oas.annotations.media.Schema;
22+
import java.math.BigDecimal;
2223

2324
public final class WorkingCapitalLoanDelinquencyActionApiResourceSwagger {
2425

@@ -29,12 +30,20 @@ public static final class PostWorkingCapitalLoansDelinquencyActionRequest {
2930

3031
private PostWorkingCapitalLoansDelinquencyActionRequest() {}
3132

32-
@Schema(example = "pause")
33+
@Schema(example = "pause", description = "Delinquency action type: pause or reschedule")
3334
public String action;
34-
@Schema(example = "2026-03-05")
35+
@Schema(example = "2026-03-05", description = "Start date of the pause period (required for pause)")
3536
public String startDate;
36-
@Schema(example = "2026-03-12")
37+
@Schema(example = "2026-03-12", description = "End date of the pause period (required for pause)")
3738
public String endDate;
39+
@Schema(example = "2", description = "Minimum payment value (required together with minimumPaymentType)")
40+
public BigDecimal minimumPayment;
41+
@Schema(example = "PERCENTAGE", description = "Minimum payment type: PERCENTAGE, FLAT (required together with minimumPayment)")
42+
public String minimumPaymentType;
43+
@Schema(example = "30", description = "Frequency value (required together with frequencyType)")
44+
public Integer frequency;
45+
@Schema(example = "DAYS", description = "Frequency type: DAYS, WEEKS, MONTHS, YEARS (required together with frequency)")
46+
public String frequencyType;
3847
@Schema(example = "yyyy-MM-dd")
3948
public String dateFormat;
4049
@Schema(example = "en")

fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/data/WorkingCapitalLoanDelinquencyActionData.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,14 @@
1818
*/
1919
package org.apache.fineract.portfolio.workingcapitalloan.data;
2020

21+
import java.math.BigDecimal;
2122
import java.time.LocalDate;
2223
import lombok.AllArgsConstructor;
2324
import lombok.Getter;
2425
import lombok.Setter;
2526
import org.apache.fineract.portfolio.delinquency.domain.DelinquencyAction;
27+
import org.apache.fineract.portfolio.delinquency.domain.DelinquencyFrequencyType;
28+
import org.apache.fineract.portfolio.delinquency.domain.DelinquencyMinimumPaymentType;
2629

2730
@AllArgsConstructor
2831
@Getter
@@ -33,5 +36,9 @@ public class WorkingCapitalLoanDelinquencyActionData {
3336
private DelinquencyAction action;
3437
private LocalDate startDate;
3538
private LocalDate endDate;
39+
private BigDecimal minimumPayment;
40+
private DelinquencyMinimumPaymentType minimumPaymentType;
41+
private Integer frequency;
42+
private DelinquencyFrequencyType frequencyType;
3643

3744
}

fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/domain/WorkingCapitalLoanDelinquencyAction.java

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,15 @@
2626
import jakarta.persistence.JoinColumn;
2727
import jakarta.persistence.ManyToOne;
2828
import jakarta.persistence.Table;
29+
import java.math.BigDecimal;
2930
import java.time.LocalDate;
3031
import lombok.Getter;
3132
import lombok.NoArgsConstructor;
3233
import lombok.Setter;
3334
import org.apache.fineract.infrastructure.core.domain.AbstractAuditableWithUTCDateTimeCustom;
3435
import org.apache.fineract.portfolio.delinquency.domain.DelinquencyAction;
36+
import org.apache.fineract.portfolio.delinquency.domain.DelinquencyFrequencyType;
37+
import org.apache.fineract.portfolio.delinquency.domain.DelinquencyMinimumPaymentType;
3538

3639
@Getter
3740
@Setter
@@ -51,7 +54,21 @@ public class WorkingCapitalLoanDelinquencyAction extends AbstractAuditableWithUT
5154
@Column(name = "start_date", nullable = false)
5255
private LocalDate startDate;
5356

54-
@Column(name = "end_date", nullable = false)
57+
@Column(name = "end_date")
5558
private LocalDate endDate;
5659

60+
@Column(name = "minimum_payment", scale = 6, precision = 19)
61+
private BigDecimal minimumPayment;
62+
63+
@Enumerated(EnumType.STRING)
64+
@Column(name = "minimum_payment_type")
65+
private DelinquencyMinimumPaymentType minimumPaymentType;
66+
67+
@Column(name = "frequency")
68+
private Integer frequency;
69+
70+
@Enumerated(EnumType.STRING)
71+
@Column(name = "frequency_type")
72+
private DelinquencyFrequencyType frequencyType;
73+
5774
}

fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/domain/WorkingCapitalLoanDelinquencyRangeSchedule.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import jakarta.persistence.ManyToOne;
2626
import jakarta.persistence.Table;
2727
import jakarta.persistence.UniqueConstraint;
28+
import jakarta.persistence.Version;
2829
import java.math.BigDecimal;
2930
import java.time.LocalDate;
3031
import lombok.Getter;
@@ -40,6 +41,10 @@
4041
@UniqueConstraint(columnNames = { "wc_loan_id", "period_number" }, name = "uc_wc_delinquency_range_schedule_loan_period") })
4142
public class WorkingCapitalLoanDelinquencyRangeSchedule extends AbstractAuditableWithUTCDateTimeCustom<Long> {
4243

44+
@Version
45+
@Column(name = "version")
46+
private Integer version;
47+
4348
@ManyToOne(fetch = FetchType.LAZY)
4449
@JoinColumn(name = "wc_loan_id", nullable = false)
4550
private WorkingCapitalLoan loan;

fineract-working-capital-loan/src/main/java/org/apache/fineract/portfolio/workingcapitalloan/repository/WorkingCapitalLoanDelinquencyActionRepository.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
package org.apache.fineract.portfolio.workingcapitalloan.repository;
2020

2121
import java.util.List;
22+
import java.util.Optional;
23+
import org.apache.fineract.portfolio.delinquency.domain.DelinquencyAction;
2224
import org.apache.fineract.portfolio.workingcapitalloan.domain.WorkingCapitalLoanDelinquencyAction;
2325
import org.springframework.data.jpa.repository.JpaRepository;
2426
import org.springframework.stereotype.Repository;
@@ -28,4 +30,7 @@ public interface WorkingCapitalLoanDelinquencyActionRepository extends JpaReposi
2830

2931
List<WorkingCapitalLoanDelinquencyAction> findByWorkingCapitalLoanIdOrderById(Long workingCapitalLoanId);
3032

33+
Optional<WorkingCapitalLoanDelinquencyAction> findTopByWorkingCapitalLoanIdAndActionOrderByIdDesc(Long workingCapitalLoanId,
34+
DelinquencyAction action);
35+
3136
}

0 commit comments

Comments
 (0)