Skip to content

Commit 4daf88b

Browse files
committed
FINERACT-2455: working capital delinquency managament range schedule
1 parent 3d7e54f commit 4daf88b

13 files changed

Lines changed: 921 additions & 0 deletions

File tree

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/**
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.apache.fineract.cob.workingcapitalloan.businessstep;
20+
21+
import lombok.RequiredArgsConstructor;
22+
import lombok.extern.slf4j.Slf4j;
23+
import org.apache.fineract.infrastructure.core.service.DateUtils;
24+
import org.apache.fineract.portfolio.workingcapitalloan.repository.WcLoanDelinquencyRangeScheduleRepository;
25+
import org.apache.fineract.portfolio.workingcapitalloan.service.WcLoanDelinquencyRangeScheduleService;
26+
import org.apache.fineract.portfolio.workingcapitalloanproduct.domain.WorkingCapitalLoan;
27+
import org.springframework.stereotype.Component;
28+
29+
@Slf4j
30+
@RequiredArgsConstructor
31+
@Component
32+
public class DelinquencyRangeScheduleBusinessStep extends WorkingCapitalLoanCOBBusinessStep {
33+
34+
private final WcLoanDelinquencyRangeScheduleService rangeScheduleService;
35+
private final WcLoanDelinquencyRangeScheduleRepository rangeScheduleRepository;
36+
37+
@Override
38+
public WorkingCapitalLoan execute(WorkingCapitalLoan input) {
39+
if (input.getActualDisbursementDate() == null) {
40+
log.debug("Skipping delinquency range schedule for WC loan {} - not yet disbursed", input.getId());
41+
return input;
42+
}
43+
44+
java.time.LocalDate businessDate = DateUtils.getBusinessLocalDate();
45+
46+
boolean hasSchedule = rangeScheduleRepository.findTopByLoanIdOrderByPeriodNumberDesc(input.getId()).isPresent();
47+
if (!hasSchedule) {
48+
rangeScheduleService.generateInitialPeriod(input);
49+
}
50+
51+
rangeScheduleService.generateNextPeriodIfNeeded(input, businessDate);
52+
rangeScheduleService.evaluateExpiredPeriods(input, businessDate);
53+
54+
return input;
55+
}
56+
57+
@Override
58+
public String getEnumStyledName() {
59+
return "WC_DELINQUENCY_RANGE_SCHEDULE";
60+
}
61+
62+
@Override
63+
public String getHumanReadableName() {
64+
return "WC Delinquency Range Schedule";
65+
}
66+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/**
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.apache.fineract.portfolio.workingcapitalloan.api;
20+
21+
import io.swagger.v3.oas.annotations.Operation;
22+
import io.swagger.v3.oas.annotations.Parameter;
23+
import io.swagger.v3.oas.annotations.media.ArraySchema;
24+
import io.swagger.v3.oas.annotations.media.Content;
25+
import io.swagger.v3.oas.annotations.media.Schema;
26+
import io.swagger.v3.oas.annotations.responses.ApiResponse;
27+
import io.swagger.v3.oas.annotations.responses.ApiResponses;
28+
import io.swagger.v3.oas.annotations.tags.Tag;
29+
import jakarta.ws.rs.Consumes;
30+
import jakarta.ws.rs.GET;
31+
import jakarta.ws.rs.Path;
32+
import jakarta.ws.rs.PathParam;
33+
import jakarta.ws.rs.Produces;
34+
import jakarta.ws.rs.core.MediaType;
35+
import java.util.List;
36+
import lombok.RequiredArgsConstructor;
37+
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
38+
import org.apache.fineract.portfolio.workingcapitalloan.data.WcLoanDelinquencyRangeScheduleData;
39+
import org.apache.fineract.portfolio.workingcapitalloan.service.WcLoanDelinquencyRangeScheduleService;
40+
import org.springframework.stereotype.Component;
41+
42+
@Path("/v1/working-capital-loans/{loanId}/delinquency-range-schedule")
43+
@Component
44+
@Tag(name = "Working Capital Loan Delinquency Range Schedule", description = "Manages delinquency range schedule periods for Working Capital loans")
45+
@RequiredArgsConstructor
46+
public class WcLoanDelinquencyRangeScheduleApiResource {
47+
48+
private static final String RESOURCE_NAME_FOR_PERMISSIONS = "WORKINGCAPITALLOAN";
49+
50+
private final PlatformSecurityContext context;
51+
private final WcLoanDelinquencyRangeScheduleService rangeScheduleService;
52+
53+
@GET
54+
@Consumes({ MediaType.APPLICATION_JSON })
55+
@Produces({ MediaType.APPLICATION_JSON })
56+
@Operation(summary = "Retrieve Delinquency Range Schedule", description = "Retrieves the delinquency range schedule periods for a Working Capital loan")
57+
@ApiResponses({
58+
@ApiResponse(responseCode = "200", description = "OK", content = @Content(array = @ArraySchema(schema = @Schema(implementation = WcLoanDelinquencyRangeScheduleData.class)))) })
59+
public List<WcLoanDelinquencyRangeScheduleData> retrieveDelinquencyRangeSchedule(
60+
@PathParam("loanId") @Parameter(description = "loanId") final Long loanId) {
61+
this.context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSIONS);
62+
return rangeScheduleService.retrieveRangeSchedule(loanId);
63+
}
64+
65+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/**
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.apache.fineract.portfolio.workingcapitalloan.data;
20+
21+
import java.math.BigDecimal;
22+
import java.time.LocalDate;
23+
import lombok.AllArgsConstructor;
24+
import lombok.Getter;
25+
import lombok.Setter;
26+
27+
@AllArgsConstructor
28+
@Getter
29+
@Setter
30+
public class WcLoanDelinquencyRangeScheduleData {
31+
32+
private Long id;
33+
private Long loanId;
34+
private Integer periodNumber;
35+
private LocalDate fromDate;
36+
private LocalDate toDate;
37+
private BigDecimal expectedAmount;
38+
private BigDecimal paidAmount;
39+
private BigDecimal outstandingAmount;
40+
private Boolean minPaymentCriteriaMet;
41+
42+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/**
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.apache.fineract.portfolio.workingcapitalloan.domain;
20+
21+
import jakarta.persistence.Column;
22+
import jakarta.persistence.Entity;
23+
import jakarta.persistence.FetchType;
24+
import jakarta.persistence.JoinColumn;
25+
import jakarta.persistence.ManyToOne;
26+
import jakarta.persistence.Table;
27+
import jakarta.persistence.UniqueConstraint;
28+
import java.math.BigDecimal;
29+
import java.time.LocalDate;
30+
import lombok.Getter;
31+
import lombok.NoArgsConstructor;
32+
import lombok.Setter;
33+
import org.apache.fineract.infrastructure.core.domain.AbstractAuditableWithUTCDateTimeCustom;
34+
import org.apache.fineract.portfolio.workingcapitalloanproduct.domain.WorkingCapitalLoan;
35+
36+
@Getter
37+
@Setter
38+
@NoArgsConstructor
39+
@Entity
40+
@Table(name = "m_wc_loan_delinquency_range_schedule", uniqueConstraints = {
41+
@UniqueConstraint(columnNames = { "wc_loan_id", "period_number" }, name = "uc_wc_delinquency_range_schedule_loan_period") })
42+
public class WcLoanDelinquencyRangeSchedule extends AbstractAuditableWithUTCDateTimeCustom<Long> {
43+
44+
@ManyToOne(fetch = FetchType.LAZY)
45+
@JoinColumn(name = "wc_loan_id", nullable = false)
46+
private WorkingCapitalLoan loan;
47+
48+
@Column(name = "period_number", nullable = false)
49+
private Integer periodNumber;
50+
51+
@Column(name = "from_date", nullable = false)
52+
private LocalDate fromDate;
53+
54+
@Column(name = "to_date", nullable = false)
55+
private LocalDate toDate;
56+
57+
@Column(name = "expected_amount", scale = 6, precision = 19)
58+
private BigDecimal expectedAmount;
59+
60+
@Column(name = "paid_amount", scale = 6, precision = 19)
61+
private BigDecimal paidAmount;
62+
63+
@Column(name = "outstanding_amount", scale = 6, precision = 19)
64+
private BigDecimal outstandingAmount;
65+
66+
@Column(name = "min_payment_criteria_met")
67+
private Boolean minPaymentCriteriaMet;
68+
69+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/**
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.apache.fineract.portfolio.workingcapitalloan.mapper;
20+
21+
import java.util.List;
22+
import org.apache.fineract.infrastructure.core.config.MapstructMapperConfig;
23+
import org.apache.fineract.portfolio.workingcapitalloan.data.WcLoanDelinquencyRangeScheduleData;
24+
import org.apache.fineract.portfolio.workingcapitalloan.domain.WcLoanDelinquencyRangeSchedule;
25+
import org.mapstruct.Mapper;
26+
import org.mapstruct.Mapping;
27+
28+
@Mapper(config = MapstructMapperConfig.class)
29+
public interface WcLoanDelinquencyRangeScheduleMapper {
30+
31+
@Mapping(target = "loanId", source = "loan.id")
32+
WcLoanDelinquencyRangeScheduleData toData(WcLoanDelinquencyRangeSchedule entity);
33+
34+
List<WcLoanDelinquencyRangeScheduleData> toDataList(List<WcLoanDelinquencyRangeSchedule> entities);
35+
36+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/**
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.apache.fineract.portfolio.workingcapitalloan.repository;
20+
21+
import java.time.LocalDate;
22+
import java.util.List;
23+
import java.util.Optional;
24+
import org.apache.fineract.portfolio.workingcapitalloan.domain.WcLoanDelinquencyRangeSchedule;
25+
import org.springframework.data.jpa.repository.JpaRepository;
26+
27+
public interface WcLoanDelinquencyRangeScheduleRepository extends JpaRepository<WcLoanDelinquencyRangeSchedule, Long> {
28+
29+
List<WcLoanDelinquencyRangeSchedule> findByLoanIdOrderByPeriodNumberAsc(Long loanId);
30+
31+
Optional<WcLoanDelinquencyRangeSchedule> findTopByLoanIdOrderByPeriodNumberDesc(Long loanId);
32+
33+
Optional<WcLoanDelinquencyRangeSchedule> findByLoanIdAndFromDateLessThanEqualAndToDateGreaterThanEqual(Long loanId, LocalDate date,
34+
LocalDate date2);
35+
36+
List<WcLoanDelinquencyRangeSchedule> findByLoanIdAndToDateLessThanAndMinPaymentCriteriaMetIsNull(Long loanId, LocalDate businessDate);
37+
38+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/**
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.apache.fineract.portfolio.workingcapitalloan.service;
20+
21+
import java.math.BigDecimal;
22+
import java.time.LocalDate;
23+
import java.util.List;
24+
import org.apache.fineract.portfolio.workingcapitalloan.data.WcLoanDelinquencyRangeScheduleData;
25+
import org.apache.fineract.portfolio.workingcapitalloanproduct.domain.WorkingCapitalLoan;
26+
27+
public interface WcLoanDelinquencyRangeScheduleService {
28+
29+
void generateInitialPeriod(WorkingCapitalLoan loan);
30+
31+
void generateNextPeriodIfNeeded(WorkingCapitalLoan loan, LocalDate businessDate);
32+
33+
void applyRepayment(Long loanId, LocalDate transactionDate, BigDecimal amount);
34+
35+
void evaluateExpiredPeriods(WorkingCapitalLoan loan, LocalDate businessDate);
36+
37+
List<WcLoanDelinquencyRangeScheduleData> retrieveRangeSchedule(Long loanId);
38+
39+
}

0 commit comments

Comments
 (0)