Delinquency buckets management for Loans (#2442)
Co-authored-by: Jose Alberto Hernandez <alberto@MacBook-Pro.local>
This commit is contained in:
co-authored by
Jose Alberto Hernandez
parent
f78a596878
commit
9e949887b9
+46
@@ -3494,4 +3494,50 @@ public class CommandWrapperBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandWrapperBuilder createDelinquencyRange() {
|
||||
this.actionName = "CREATE";
|
||||
this.entityName = "DELINQUENCY_RANGE";
|
||||
this.href = "/delinquency/range";
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandWrapperBuilder updateDelinquencyRange(final Long delinquencyRangeId) {
|
||||
this.actionName = "UPDATE";
|
||||
this.entityName = "DELINQUENCY_RANGE";
|
||||
this.entityId = delinquencyRangeId;
|
||||
this.href = "/delinquency/range";
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandWrapperBuilder deleteDelinquencyRange(final Long delinquencyRangeId) {
|
||||
this.actionName = "DELETE";
|
||||
this.entityName = "DELINQUENCY_RANGE";
|
||||
this.entityId = delinquencyRangeId;
|
||||
this.href = "/delinquency/range";
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandWrapperBuilder createDelinquencyBucket() {
|
||||
this.actionName = "CREATE";
|
||||
this.entityName = "DELINQUENCY_BUCKET";
|
||||
this.href = "/delinquency/bucket";
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandWrapperBuilder updateDelinquencyBucket(final Long delinquencyBucketId) {
|
||||
this.actionName = "UPDATE";
|
||||
this.entityName = "DELINQUENCY_BUCKET";
|
||||
this.entityId = delinquencyBucketId;
|
||||
this.href = "/delinquency/bucket";
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandWrapperBuilder deleteDelinquencyBucket(final Long delinquencyBucketId) {
|
||||
this.actionName = "DELETE";
|
||||
this.entityName = "DELINQUENCY_BUCKET";
|
||||
this.entityId = delinquencyBucketId;
|
||||
this.href = "/delinquency/bucket";
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* 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.infrastructure.core.validator;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
|
||||
import org.apache.fineract.infrastructure.core.exception.InvalidJsonException;
|
||||
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
|
||||
|
||||
@Slf4j
|
||||
public class ParseAndValidator {
|
||||
|
||||
protected JsonObject extractJsonObject(final FromJsonHelper jsonHelper, final JsonCommand command) {
|
||||
String json = command.json();
|
||||
if (StringUtils.isBlank(json)) {
|
||||
throw new InvalidJsonException();
|
||||
}
|
||||
|
||||
final JsonElement element = jsonHelper.parse(json);
|
||||
return element.getAsJsonObject();
|
||||
}
|
||||
|
||||
protected void throwExceptionIfValidationWarningsExist(DataValidatorBuilder dataValidator) {
|
||||
if (dataValidator.hasError()) {
|
||||
log.error("Validation errors: {}", dataValidator.getDataValidationErrors());
|
||||
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.",
|
||||
dataValidator.getDataValidationErrors());
|
||||
}
|
||||
}
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* 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.api;
|
||||
|
||||
public final class DelinquencyApiConstants {
|
||||
|
||||
private DelinquencyApiConstants() {
|
||||
|
||||
}
|
||||
|
||||
public static final String NAME_PARAM_NAME = "name";
|
||||
public static final String CLASSIFICATION_PARAM_NAME = "classification";
|
||||
public static final String RANGES_PARAM_NAME = "ranges";
|
||||
public static final String MINIMUMAGEDAYS_PARAM_NAME = "minimumAgeDays";
|
||||
public static final String MAXIMUMAGEDAYS_PARAM_NAME = "maximumAgeDays";
|
||||
public static final String LOCALE_PARAM_NAME = "locale";
|
||||
|
||||
}
|
||||
+235
@@ -0,0 +1,235 @@
|
||||
/**
|
||||
* 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.api;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.media.ArraySchema;
|
||||
import io.swagger.v3.oas.annotations.media.Content;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.parameters.RequestBody;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponses;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import java.util.Collection;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.DELETE;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.PUT;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.commands.domain.CommandWrapper;
|
||||
import org.apache.fineract.commands.service.CommandWrapperBuilder;
|
||||
import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
|
||||
import org.apache.fineract.infrastructure.core.api.ApiRequestParameterHelper;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.infrastructure.core.serialization.ApiRequestJsonSerializationSettings;
|
||||
import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSerializer;
|
||||
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.apache.fineract.portfolio.delinquency.data.DelinquencyBucketData;
|
||||
import org.apache.fineract.portfolio.delinquency.data.DelinquencyRangeData;
|
||||
import org.apache.fineract.portfolio.delinquency.service.DelinquencyReadPlatformService;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Path("delinquency")
|
||||
@Component
|
||||
@Tag(name = "Delinquency Range and Buckets Management", description = "Delinquency Range and Buckets management enables you to set up, fetch and adjust Delinquency overdue ranges")
|
||||
public class DelinquencyApiResource {
|
||||
|
||||
private final ApiRequestParameterHelper parameterHelper;
|
||||
private final PlatformSecurityContext securityContext;
|
||||
private final DefaultToApiJsonSerializer<DelinquencyBucketData> jsonSerializerBucket;
|
||||
private final DefaultToApiJsonSerializer<DelinquencyRangeData> jsonSerializerRange;
|
||||
private final DelinquencyReadPlatformService readPlatformService;
|
||||
private final PortfolioCommandSourceWritePlatformService commandWritePlatformService;
|
||||
|
||||
@GET
|
||||
@Path("ranges")
|
||||
@Consumes({ MediaType.TEXT_HTML, MediaType.APPLICATION_JSON })
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Operation(summary = "List all Delinquency Ranges", description = "")
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(array = @ArraySchema(schema = @Schema(implementation = DelinquencyApiResourceSwagger.GetDelinquencyRangesResponse.class)))) })
|
||||
public String getDelinquencyRanges(@Context final UriInfo uriInfo) {
|
||||
securityContext.authenticatedUser().validateHasReadPermission("DELINQUENCY_BUCKET");
|
||||
final Collection<DelinquencyRangeData> delinquencyRangeData = this.readPlatformService.retrieveAllDelinquencyRanges();
|
||||
ApiRequestJsonSerializationSettings settings = parameterHelper.process(uriInfo.getQueryParameters());
|
||||
return this.jsonSerializerRange.serialize(settings, delinquencyRangeData);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("ranges/{delinquencyRangeId}")
|
||||
@Consumes({ MediaType.TEXT_HTML, MediaType.APPLICATION_JSON })
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Operation(summary = "Retrieve a specific Delinquency Range based on the Id", description = "")
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = DelinquencyApiResourceSwagger.GetDelinquencyRangesResponse.class))) })
|
||||
public String getDelinquencyRange(
|
||||
@PathParam("delinquencyRangeId") @Parameter(description = "delinquencyRangeId") final Long delinquencyRangeId,
|
||||
@Context final UriInfo uriInfo) {
|
||||
securityContext.authenticatedUser().validateHasReadPermission("DELINQUENCY_BUCKET");
|
||||
final DelinquencyRangeData delinquencyRangeData = this.readPlatformService.retrieveDelinquencyRange(delinquencyRangeId);
|
||||
ApiRequestJsonSerializationSettings settings = parameterHelper.process(uriInfo.getQueryParameters());
|
||||
return this.jsonSerializerRange.serialize(settings, delinquencyRangeData);
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("ranges")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Create Delinquency Range", description = "")
|
||||
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = DelinquencyApiResourceSwagger.PostDelinquencyRangeRequest.class)))
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = DelinquencyApiResourceSwagger.PostDelinquencyRangeResponse.class))) })
|
||||
public String createDelinquencyRange(final String jsonRequestBody, @Context UriInfo uriInfo) {
|
||||
securityContext.authenticatedUser().validateHasCreatePermission("DELINQUENCY_BUCKET");
|
||||
final CommandWrapper commandRequest = new CommandWrapperBuilder().createDelinquencyRange().withJson(jsonRequestBody).build();
|
||||
|
||||
CommandProcessingResult result = commandWritePlatformService.logCommandSource(commandRequest);
|
||||
return jsonSerializerRange.serialize(result);
|
||||
}
|
||||
|
||||
@PUT
|
||||
@Path("ranges/{delinquencyRangeId}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Update Delinquency Range based on the Id", description = "")
|
||||
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = DelinquencyApiResourceSwagger.PostDelinquencyRangeRequest.class)))
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = DelinquencyApiResourceSwagger.PutDelinquencyRangeResponse.class))) })
|
||||
public String updateDelinquencyRange(
|
||||
@PathParam("delinquencyRangeId") @Parameter(description = "delinquencyRangeId") final Long delinquencyRangeId,
|
||||
final String jsonRequestBody, @Context UriInfo uriInfo) {
|
||||
securityContext.authenticatedUser().validateHasUpdatePermission("DELINQUENCY_BUCKET");
|
||||
final CommandWrapper commandRequest = new CommandWrapperBuilder().updateDelinquencyRange(delinquencyRangeId)
|
||||
.withJson(jsonRequestBody).build();
|
||||
|
||||
CommandProcessingResult result = commandWritePlatformService.logCommandSource(commandRequest);
|
||||
return jsonSerializerRange.serialize(result);
|
||||
}
|
||||
|
||||
@DELETE
|
||||
@Path("ranges/{delinquencyRangeId}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Update Delinquency Range based on the Id", description = "")
|
||||
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = DelinquencyApiResourceSwagger.PostDelinquencyRangeRequest.class)))
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = DelinquencyApiResourceSwagger.DeleteDelinquencyRangeResponse.class))) })
|
||||
public String deleteDelinquencyRange(
|
||||
@PathParam("delinquencyRangeId") @Parameter(description = "delinquencyRangeId") final Long delinquencyRangeId,
|
||||
@Context UriInfo uriInfo) {
|
||||
securityContext.authenticatedUser().validateHasDeletePermission("DELINQUENCY_BUCKET");
|
||||
final CommandWrapper commandRequest = new CommandWrapperBuilder().deleteDelinquencyRange(delinquencyRangeId).build();
|
||||
|
||||
CommandProcessingResult result = commandWritePlatformService.logCommandSource(commandRequest);
|
||||
return jsonSerializerRange.serialize(result);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("buckets")
|
||||
@Consumes({ MediaType.TEXT_HTML, MediaType.APPLICATION_JSON })
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Operation(summary = "List all Delinquency Buckets", description = "")
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(array = @ArraySchema(schema = @Schema(implementation = DelinquencyApiResourceSwagger.GetDelinquencyBucketsResponse.class)))) })
|
||||
public String getDelinquencyBuckets(@Context final UriInfo uriInfo) {
|
||||
securityContext.authenticatedUser().validateHasReadPermission("DELINQUENCY_BUCKET");
|
||||
final Collection<DelinquencyBucketData> delinquencyBucketData = this.readPlatformService.retrieveAllDelinquencyBuckets();
|
||||
ApiRequestJsonSerializationSettings settings = parameterHelper.process(uriInfo.getQueryParameters());
|
||||
return this.jsonSerializerBucket.serialize(settings, delinquencyBucketData);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("buckets/{delinquencyBucketId}")
|
||||
@Consumes({ MediaType.TEXT_HTML, MediaType.APPLICATION_JSON })
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Operation(summary = "Retrieve a specific Delinquency Bucket based on the Id", description = "")
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = DelinquencyApiResourceSwagger.GetDelinquencyBucketsResponse.class))) })
|
||||
public String getDelinquencyBucket(
|
||||
@PathParam("delinquencyBucketId") @Parameter(description = "delinquencyBucketId") final Long delinquencyBucketId,
|
||||
@Context final UriInfo uriInfo) {
|
||||
securityContext.authenticatedUser().validateHasReadPermission("DELINQUENCY_BUCKET");
|
||||
final DelinquencyBucketData delinquencyBucketData = this.readPlatformService.retrieveDelinquencyBucket(delinquencyBucketId);
|
||||
ApiRequestJsonSerializationSettings settings = parameterHelper.process(uriInfo.getQueryParameters());
|
||||
return this.jsonSerializerBucket.serialize(settings, delinquencyBucketData);
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("buckets")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Create Delinquency Bucket", description = "")
|
||||
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = DelinquencyApiResourceSwagger.PostDelinquencyBucketRequest.class)))
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = DelinquencyApiResourceSwagger.PostDelinquencyBucketResponse.class))) })
|
||||
public String createDelinquencyBucket(final String jsonRequestBody, @Context UriInfo uriInfo) {
|
||||
securityContext.authenticatedUser().validateHasCreatePermission("DELINQUENCY_BUCKET");
|
||||
final CommandWrapper commandRequest = new CommandWrapperBuilder().createDelinquencyBucket().withJson(jsonRequestBody).build();
|
||||
|
||||
CommandProcessingResult result = commandWritePlatformService.logCommandSource(commandRequest);
|
||||
return jsonSerializerRange.serialize(result);
|
||||
}
|
||||
|
||||
@PUT
|
||||
@Path("buckets/{delinquencyBucketId}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Update Delinquency Bucket based on the Id", description = "")
|
||||
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = DelinquencyApiResourceSwagger.PostDelinquencyBucketRequest.class)))
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = DelinquencyApiResourceSwagger.PutDelinquencyBucketResponse.class))) })
|
||||
public String updateDelinquencyBucket(
|
||||
@PathParam("delinquencyBucketId") @Parameter(description = "delinquencyBucketId") final Long delinquencyBucketId,
|
||||
final String jsonRequestBody, @Context UriInfo uriInfo) {
|
||||
securityContext.authenticatedUser().validateHasUpdatePermission("DELINQUENCY_BUCKET");
|
||||
final CommandWrapper commandRequest = new CommandWrapperBuilder().updateDelinquencyBucket(delinquencyBucketId)
|
||||
.withJson(jsonRequestBody).build();
|
||||
|
||||
CommandProcessingResult result = commandWritePlatformService.logCommandSource(commandRequest);
|
||||
return jsonSerializerRange.serialize(result);
|
||||
}
|
||||
|
||||
@DELETE
|
||||
@Path("buckets/{delinquencyBucketId}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Delete Delinquency Bucket based on the Id", description = "")
|
||||
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = DelinquencyApiResourceSwagger.PostDelinquencyBucketRequest.class)))
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = DelinquencyApiResourceSwagger.DeleteDelinquencyBucketResponse.class))) })
|
||||
public String deleteDelinquencyBucket(
|
||||
@PathParam("delinquencyBucketId") @Parameter(description = "delinquencyBucketId") final Long delinquencyBucketId,
|
||||
@Context UriInfo uriInfo) {
|
||||
securityContext.authenticatedUser().validateHasDeletePermission("DELINQUENCY_BUCKET");
|
||||
final CommandWrapper commandRequest = new CommandWrapperBuilder().deleteDelinquencyBucket(delinquencyBucketId).build();
|
||||
|
||||
CommandProcessingResult result = commandWritePlatformService.logCommandSource(commandRequest);
|
||||
return jsonSerializerRange.serialize(result);
|
||||
}
|
||||
|
||||
}
|
||||
+136
@@ -0,0 +1,136 @@
|
||||
/**
|
||||
* 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.api;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
public final class DelinquencyApiResourceSwagger {
|
||||
|
||||
private DelinquencyApiResourceSwagger() {}
|
||||
|
||||
@Schema(description = "GetDelinquencyRangesResponse")
|
||||
public static final class GetDelinquencyRangesResponse {
|
||||
|
||||
private GetDelinquencyRangesResponse() {}
|
||||
|
||||
@Schema(example = "1")
|
||||
public Integer id;
|
||||
@Schema(example = "Delinquent 1")
|
||||
public String classification;
|
||||
@Schema(example = "1")
|
||||
public Long minimumAgeDays;
|
||||
@Schema(example = "3")
|
||||
public Long maximumAgeDays;
|
||||
}
|
||||
|
||||
@Schema(description = "GetDelinquencyBucketsResponse")
|
||||
public static final class GetDelinquencyBucketsResponse {
|
||||
|
||||
private GetDelinquencyBucketsResponse() {}
|
||||
|
||||
@Schema(example = "1")
|
||||
public Integer id;
|
||||
@Schema(example = "Delinquent Bucket Set 1")
|
||||
public String name;
|
||||
|
||||
public GetDelinquencyRangesResponse[] ranges;
|
||||
}
|
||||
|
||||
@Schema(description = "PostDelinquencyRangeRequest")
|
||||
public static final class PostDelinquencyRangeRequest {
|
||||
|
||||
private PostDelinquencyRangeRequest() {}
|
||||
|
||||
@Schema(example = "Delinquent 1")
|
||||
public String classification;
|
||||
@Schema(example = "1")
|
||||
public Integer minimumAgeDays;
|
||||
@Schema(example = "3")
|
||||
public Integer maximumAgeDays;
|
||||
@Schema(example = "en")
|
||||
public String locale;
|
||||
}
|
||||
|
||||
@Schema(description = "PostDelinquencyRangeResponse")
|
||||
public static final class PostDelinquencyRangeResponse {
|
||||
|
||||
private PostDelinquencyRangeResponse() {}
|
||||
|
||||
@Schema(example = "1")
|
||||
public Integer resourceId;
|
||||
}
|
||||
|
||||
@Schema(description = "PutDelinquencyRangeResponse")
|
||||
public static final class PutDelinquencyRangeResponse {
|
||||
|
||||
private PutDelinquencyRangeResponse() {}
|
||||
|
||||
@Schema(example = "1")
|
||||
public Integer resourceId;
|
||||
public PostDelinquencyRangeRequest changes;
|
||||
}
|
||||
|
||||
@Schema(description = "DeleteDelinquencyRangeResponse")
|
||||
public static final class DeleteDelinquencyRangeResponse {
|
||||
|
||||
private DeleteDelinquencyRangeResponse() {}
|
||||
|
||||
@Schema(example = "1")
|
||||
public Integer resourceId;
|
||||
}
|
||||
|
||||
@Schema(description = "PostDelinquencyBucketRequest")
|
||||
public static final class PostDelinquencyBucketRequest {
|
||||
|
||||
private PostDelinquencyBucketRequest() {}
|
||||
|
||||
@Schema(example = "Delinquent 1")
|
||||
public String name;
|
||||
@Schema(example = "[1,2,3]")
|
||||
public Long[] ranges;
|
||||
}
|
||||
|
||||
@Schema(description = "PostDelinquencyBucketResponse")
|
||||
public static final class PostDelinquencyBucketResponse {
|
||||
|
||||
private PostDelinquencyBucketResponse() {}
|
||||
|
||||
@Schema(example = "1")
|
||||
public Integer resourceId;
|
||||
}
|
||||
|
||||
@Schema(description = "PutDelinquencyBucketResponse")
|
||||
public static final class PutDelinquencyBucketResponse {
|
||||
|
||||
private PutDelinquencyBucketResponse() {}
|
||||
|
||||
@Schema(example = "1")
|
||||
public Integer resourceId;
|
||||
}
|
||||
|
||||
@Schema(description = "DeleteDelinquencyBucketResponse")
|
||||
public static final class DeleteDelinquencyBucketResponse {
|
||||
|
||||
private DeleteDelinquencyBucketResponse() {}
|
||||
|
||||
@Schema(example = "1")
|
||||
public Integer resourceId;
|
||||
}
|
||||
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* 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.data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
|
||||
@ToString
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
@Setter
|
||||
public class DelinquencyBucketData implements Serializable {
|
||||
|
||||
private Long id;
|
||||
private String name;
|
||||
private List<DelinquencyRangeData> ranges;
|
||||
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* 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.data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
|
||||
@ToString
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
@Setter
|
||||
public class DelinquencyRangeData implements Serializable {
|
||||
|
||||
private Long id;
|
||||
private String classification;
|
||||
private Integer minimumAgeDays;
|
||||
private Integer maximumAgeDays;
|
||||
|
||||
public static DelinquencyRangeData instance(String classification, Integer minimumAgeDays, Integer maximumAgeDays) {
|
||||
return new DelinquencyRangeData(null, classification, minimumAgeDays, maximumAgeDays);
|
||||
}
|
||||
|
||||
public static DelinquencyRangeData reference(Long id) {
|
||||
return new DelinquencyRangeData(id, "", 0, 0);
|
||||
}
|
||||
|
||||
}
|
||||
+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.domain;
|
||||
|
||||
import java.util.Set;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.JoinTable;
|
||||
import javax.persistence.ManyToMany;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.UniqueConstraint;
|
||||
import javax.persistence.Version;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import org.apache.fineract.infrastructure.core.domain.AbstractAuditableWithUTCDateTimeCustom;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@Entity
|
||||
@Table(name = "m_delinquency_bucket", uniqueConstraints = {
|
||||
@UniqueConstraint(name = "uq_delinquency_bucket_name", columnNames = { "name" }) })
|
||||
public class DelinquencyBucket extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
|
||||
@Column(name = "name", nullable = false)
|
||||
private String name;
|
||||
|
||||
@ManyToMany(fetch = FetchType.LAZY)
|
||||
@JoinTable(name = "m_delinquency_bucket_mappings", joinColumns = @JoinColumn(name = "delinquency_bucket_id"), inverseJoinColumns = @JoinColumn(name = "delinquency_range_id"))
|
||||
private Set<DelinquencyRange> ranges;
|
||||
|
||||
@Version
|
||||
private Long version;
|
||||
|
||||
public DelinquencyBucket(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* 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.domain;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.UniqueConstraint;
|
||||
import javax.persistence.Version;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import org.apache.fineract.infrastructure.core.domain.AbstractAuditableWithUTCDateTimeCustom;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@Entity
|
||||
@Table(name = "m_delinquency_bucket_mappings", uniqueConstraints = {
|
||||
@UniqueConstraint(name = "uq_delinquency_bucket_mapping", columnNames = { "delinquencyBucket", "delinquencyRange" }) })
|
||||
public class DelinquencyBucketMappings extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "delinquency_bucket_id", nullable = false)
|
||||
private DelinquencyBucket delinquencyBucket;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "delinquency_range_id", nullable = false)
|
||||
private DelinquencyRange delinquencyRange;
|
||||
|
||||
@Version
|
||||
private Long version;
|
||||
|
||||
public DelinquencyBucketMappings(DelinquencyBucket delinquencyBucket, DelinquencyRange delinquencyRange) {
|
||||
this.delinquencyBucket = delinquencyBucket;
|
||||
this.delinquencyRange = delinquencyRange;
|
||||
}
|
||||
|
||||
public static DelinquencyBucketMappings instance(DelinquencyBucket delinquencyBucket, DelinquencyRange delinquencyRange) {
|
||||
return new DelinquencyBucketMappings(delinquencyBucket, delinquencyRange);
|
||||
}
|
||||
|
||||
}
|
||||
+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.domain;
|
||||
|
||||
import java.util.List;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
|
||||
public interface DelinquencyBucketMappingsRepository
|
||||
extends JpaRepository<DelinquencyBucketMappings, Long>, JpaSpecificationExecutor<DelinquencyBucketMappings> {
|
||||
|
||||
List<DelinquencyBucketMappings> findByDelinquencyBucket(DelinquencyBucket delinquencyBucket);
|
||||
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* 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.domain;
|
||||
|
||||
import java.util.Optional;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
|
||||
public interface DelinquencyBucketRepository extends JpaRepository<DelinquencyBucket, Long>, JpaSpecificationExecutor<DelinquencyBucket> {
|
||||
|
||||
Optional<DelinquencyBucket> findByName(String name);
|
||||
}
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
* 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.domain;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.UniqueConstraint;
|
||||
import javax.persistence.Version;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import org.apache.fineract.infrastructure.core.domain.AbstractAuditableWithUTCDateTimeCustom;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@Entity
|
||||
@Table(name = "m_delinquency_range", uniqueConstraints = {
|
||||
@UniqueConstraint(name = "uq_delinquency_range_classification", columnNames = { "classification" }) })
|
||||
public class DelinquencyRange extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
|
||||
@Column(name = "classification", nullable = false)
|
||||
private String classification;
|
||||
|
||||
@Column(name = "min_age_days", nullable = false)
|
||||
private Integer minimumAgeDays;
|
||||
|
||||
@Column(name = "max_age_days", nullable = true)
|
||||
private Integer maximumAgeDays;
|
||||
|
||||
@Version
|
||||
private Long version;
|
||||
|
||||
protected DelinquencyRange(@NotNull String classification, @NotNull Integer minimumAgeDays, Integer maximumAgeDays) {
|
||||
this.classification = classification;
|
||||
this.minimumAgeDays = minimumAgeDays;
|
||||
this.maximumAgeDays = maximumAgeDays;
|
||||
}
|
||||
|
||||
public static DelinquencyRange instance(@NotNull String classification, @NotNull Integer minimumAge, Integer maximumAge) {
|
||||
return new DelinquencyRange(classification, minimumAge, maximumAge);
|
||||
}
|
||||
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* 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.domain;
|
||||
|
||||
import java.util.Optional;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
|
||||
public interface DelinquencyRangeRepository extends JpaRepository<DelinquencyRange, Long>, JpaSpecificationExecutor<DelinquencyRange> {
|
||||
|
||||
Optional<DelinquencyRange> findByClassification(String classification);
|
||||
}
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* 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.domain;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Version;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import org.apache.fineract.infrastructure.core.domain.AbstractAuditableWithUTCDateTimeCustom;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@Entity
|
||||
@Table(name = "m_loan_delinquency_tag_history")
|
||||
public class LoanDelinquencyTagHistory extends AbstractAuditableWithUTCDateTimeCustom {
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "delinquency_range_id", nullable = false)
|
||||
private DelinquencyRange delinquencyRange;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "loan_id", nullable = false)
|
||||
private Loan loan;
|
||||
|
||||
@Column(name = "addedon_date", nullable = false)
|
||||
private LocalDate addedOnDate;
|
||||
|
||||
@Column(name = "liftedon_date", nullable = true)
|
||||
private LocalDate liftedOnDate;
|
||||
|
||||
@Version
|
||||
private Long version;
|
||||
|
||||
public LoanDelinquencyTagHistory(DelinquencyRange delinquencyRange, Loan loan, LocalDate addedOnDate, LocalDate liftedOnDate) {
|
||||
this.delinquencyRange = delinquencyRange;
|
||||
this.loan = loan;
|
||||
this.addedOnDate = addedOnDate;
|
||||
this.liftedOnDate = liftedOnDate;
|
||||
}
|
||||
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* 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.domain;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
|
||||
public interface LoanDelinquencyTagHistoryRepository
|
||||
extends JpaRepository<LoanDelinquencyTagHistory, Long>, JpaSpecificationExecutor<LoanDelinquencyTagHistory> {
|
||||
|
||||
List<LoanDelinquencyTagHistory> findByLoanOrderByAddedOnDateDesc(Loan loan);
|
||||
|
||||
Optional<LoanDelinquencyTagHistory> findByLoanAndLiftedOnDate(Loan loan, LocalDate liftedOnDate);
|
||||
|
||||
Long countByDelinquencyRangeAndLiftedOnDate(DelinquencyRange delinquencyRange, LocalDate liftedOnDate);
|
||||
|
||||
Long countByDelinquencyRange(DelinquencyRange delinquencyRange);
|
||||
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* 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.exception;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformDomainRuleException;
|
||||
|
||||
public class DelinquencyBucketAgesOverlapedException extends AbstractPlatformDomainRuleException {
|
||||
|
||||
public DelinquencyBucketAgesOverlapedException(final String defaultUserMessage, final Object... defaultUserMessageArgs) {
|
||||
super("error.msg.loan.delinquency.bucket.ages.overlaped", defaultUserMessage, defaultUserMessageArgs);
|
||||
}
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* 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.exception;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformResourceNotFoundException;
|
||||
|
||||
public class DelinquencyBucketNotFoundException extends AbstractPlatformResourceNotFoundException {
|
||||
|
||||
public DelinquencyBucketNotFoundException(String globalisationMessageCode, String defaultUserMessage,
|
||||
Object... defaultUserMessageArgs) {
|
||||
super(globalisationMessageCode, defaultUserMessage, defaultUserMessageArgs);
|
||||
}
|
||||
|
||||
public static DelinquencyBucketNotFoundException notExist(final Long id, Throwable... e) {
|
||||
return new DelinquencyBucketNotFoundException("error.msg.delinquency.bucket.id.not.exist",
|
||||
"Delinquency bucket with id `" + id + "` does not exist.", id, e);
|
||||
}
|
||||
|
||||
public static DelinquencyBucketNotFoundException notFound(final Long id, Throwable... e) {
|
||||
return new DelinquencyBucketNotFoundException("error.msg.delinquency.bucket.not.found",
|
||||
"Delinquency bucket with id `" + id + "` does not found.", id, e);
|
||||
}
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* 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.exception;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformDomainRuleException;
|
||||
|
||||
public class DelinquencyRangeInvalidAgesException extends AbstractPlatformDomainRuleException {
|
||||
|
||||
public DelinquencyRangeInvalidAgesException(final String defaultUserMessage, final Object... defaultUserMessageArgs) {
|
||||
super("error.msg.loan.delinquency.age.days,invalid", defaultUserMessage, defaultUserMessageArgs);
|
||||
}
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* 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.exception;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformResourceNotFoundException;
|
||||
|
||||
public class DelinquencyRangeNotFoundException extends AbstractPlatformResourceNotFoundException {
|
||||
|
||||
public DelinquencyRangeNotFoundException(String globalisationMessageCode, String defaultUserMessage, Object... defaultUserMessageArgs) {
|
||||
super(globalisationMessageCode, defaultUserMessage, defaultUserMessageArgs);
|
||||
}
|
||||
|
||||
public static DelinquencyRangeNotFoundException notExist(final Long id, Throwable... e) {
|
||||
return new DelinquencyRangeNotFoundException("error.msg.delinquency.range.id.not.exist",
|
||||
"Delinquency range with id `" + id + "` does not exist.", id, e);
|
||||
}
|
||||
|
||||
public static DelinquencyRangeNotFoundException notFound(final Long id, Throwable... e) {
|
||||
return new DelinquencyRangeNotFoundException("error.msg.delinquency.range.not.found",
|
||||
"Delinquency range with id `" + id + "` does not found.", id, e);
|
||||
}
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* 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.handler;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.commands.annotation.CommandType;
|
||||
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.portfolio.delinquency.service.DelinquencyWritePlatformService;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@CommandType(entity = "DELINQUENCY_BUCKET", action = "CREATE")
|
||||
public class CreateDelinquencyBucketCommandHandler implements NewCommandSourceHandler {
|
||||
|
||||
private final DelinquencyWritePlatformService writePlatformService;
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public CommandProcessingResult processCommand(final JsonCommand command) {
|
||||
return this.writePlatformService.createDelinquencyBucket(command);
|
||||
}
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* 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.handler;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.commands.annotation.CommandType;
|
||||
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.portfolio.delinquency.service.DelinquencyWritePlatformService;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@CommandType(entity = "DELINQUENCY_RANGE", action = "CREATE")
|
||||
public class CreateDelinquencyRangeCommandHandler implements NewCommandSourceHandler {
|
||||
|
||||
private final DelinquencyWritePlatformService writePlatformService;
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public CommandProcessingResult processCommand(final JsonCommand command) {
|
||||
return this.writePlatformService.createDelinquencyRange(command);
|
||||
}
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* 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.handler;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.commands.annotation.CommandType;
|
||||
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.portfolio.delinquency.service.DelinquencyWritePlatformService;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@CommandType(entity = "DELINQUENCY_BUCKET", action = "DELETE")
|
||||
public class DeleteDelinquencyBucketCommandHandler implements NewCommandSourceHandler {
|
||||
|
||||
private final DelinquencyWritePlatformService writePlatformService;
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public CommandProcessingResult processCommand(final JsonCommand command) {
|
||||
return this.writePlatformService.deleteDelinquencyBucket(command.entityId(), command);
|
||||
}
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* 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.handler;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.commands.annotation.CommandType;
|
||||
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.portfolio.delinquency.service.DelinquencyWritePlatformService;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@CommandType(entity = "DELINQUENCY_RANGE", action = "DELETE")
|
||||
public class DeleteDelinquencyRangeCommandHandler implements NewCommandSourceHandler {
|
||||
|
||||
private final DelinquencyWritePlatformService writePlatformService;
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public CommandProcessingResult processCommand(final JsonCommand command) {
|
||||
return this.writePlatformService.deleteDelinquencyRange(command.entityId(), command);
|
||||
}
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* 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.handler;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.commands.annotation.CommandType;
|
||||
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.portfolio.delinquency.service.DelinquencyWritePlatformService;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@CommandType(entity = "DELINQUENCY_BUCKET", action = "UPDATE")
|
||||
public class UpdateDelinquencyBucketCommandHandler implements NewCommandSourceHandler {
|
||||
|
||||
private final DelinquencyWritePlatformService writePlatformService;
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public CommandProcessingResult processCommand(final JsonCommand command) {
|
||||
return this.writePlatformService.updateDelinquencyBucket(command.entityId(), command);
|
||||
}
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* 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.handler;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.commands.annotation.CommandType;
|
||||
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.portfolio.delinquency.service.DelinquencyWritePlatformService;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@CommandType(entity = "DELINQUENCY_RANGE", action = "UPDATE")
|
||||
public class UpdateDelinquencyRangeCommandHandler implements NewCommandSourceHandler {
|
||||
|
||||
private final DelinquencyWritePlatformService writePlatformService;
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public CommandProcessingResult processCommand(final JsonCommand command) {
|
||||
return this.writePlatformService.updateDelinquencyRange(command.entityId(), command);
|
||||
}
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* 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.mapper;
|
||||
|
||||
import java.util.List;
|
||||
import org.apache.fineract.portfolio.delinquency.data.DelinquencyBucketData;
|
||||
import org.apache.fineract.portfolio.delinquency.domain.DelinquencyBucket;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.mapstruct.Mappings;
|
||||
|
||||
@Mapper(componentModel = "spring")
|
||||
public interface DelinquencyBucketMapper {
|
||||
|
||||
@Mappings({ @Mapping(target = "id", source = "source.id"), @Mapping(target = "name", source = "source.name") })
|
||||
DelinquencyBucketData map(DelinquencyBucket source);
|
||||
|
||||
List<DelinquencyBucketData> map(List<DelinquencyBucket> sources);
|
||||
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* 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.mapper;
|
||||
|
||||
import java.util.List;
|
||||
import org.apache.fineract.portfolio.delinquency.data.DelinquencyRangeData;
|
||||
import org.apache.fineract.portfolio.delinquency.domain.DelinquencyRange;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.mapstruct.Mappings;
|
||||
|
||||
@Mapper(componentModel = "spring")
|
||||
public interface DelinquencyRangeMapper {
|
||||
|
||||
@Mappings({ @Mapping(target = "id", source = "source.id"), @Mapping(target = "classification", source = "source.classification"),
|
||||
@Mapping(target = "minimumAgeDays", source = "source.minimumAgeDays"),
|
||||
@Mapping(target = "maximumAgeDays", source = "source.maximumAgeDays") })
|
||||
DelinquencyRangeData map(DelinquencyRange source);
|
||||
|
||||
List<DelinquencyRangeData> map(List<DelinquencyRange> sources);
|
||||
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* 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.Collection;
|
||||
import org.apache.fineract.portfolio.delinquency.data.DelinquencyBucketData;
|
||||
import org.apache.fineract.portfolio.delinquency.data.DelinquencyRangeData;
|
||||
|
||||
public interface DelinquencyReadPlatformService {
|
||||
|
||||
Collection<DelinquencyRangeData> retrieveAllDelinquencyRanges();
|
||||
|
||||
DelinquencyRangeData retrieveDelinquencyRange(Long delinquencyRangeId);
|
||||
|
||||
Collection<DelinquencyBucketData> retrieveAllDelinquencyBuckets();
|
||||
|
||||
DelinquencyBucketData retrieveDelinquencyBucket(Long delinquencyBucketId);
|
||||
|
||||
DelinquencyRangeData retrieveCurrentDelinquencyTag(Long loanId);
|
||||
}
|
||||
+125
@@ -0,0 +1,125 @@
|
||||
/**
|
||||
* 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.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.portfolio.delinquency.data.DelinquencyBucketData;
|
||||
import org.apache.fineract.portfolio.delinquency.data.DelinquencyRangeData;
|
||||
import org.apache.fineract.portfolio.delinquency.domain.DelinquencyBucket;
|
||||
import org.apache.fineract.portfolio.delinquency.domain.DelinquencyBucketRepository;
|
||||
import org.apache.fineract.portfolio.delinquency.domain.DelinquencyRange;
|
||||
import org.apache.fineract.portfolio.delinquency.domain.DelinquencyRangeRepository;
|
||||
import org.apache.fineract.portfolio.delinquency.domain.LoanDelinquencyTagHistory;
|
||||
import org.apache.fineract.portfolio.delinquency.domain.LoanDelinquencyTagHistoryRepository;
|
||||
import org.apache.fineract.portfolio.delinquency.exception.DelinquencyBucketNotFoundException;
|
||||
import org.apache.fineract.portfolio.delinquency.mapper.DelinquencyBucketMapper;
|
||||
import org.apache.fineract.portfolio.delinquency.mapper.DelinquencyRangeMapper;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||
import org.apache.fineract.portfolio.loanaccount.service.LoanAssembler;
|
||||
import org.springframework.dao.EmptyResultDataAccessException;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
@Transactional(readOnly = true)
|
||||
public class DelinquencyReadPlatformServiceImpl implements DelinquencyReadPlatformService {
|
||||
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
private final DelinquencyRangeRepository repositoryRange;
|
||||
private final DelinquencyBucketRepository repositoryBucket;
|
||||
private final LoanDelinquencyTagHistoryRepository repositoryLoanDelinquencyTagHistory;
|
||||
private final DelinquencyRangeMapper mapperRange;
|
||||
private final DelinquencyBucketMapper mapperBucket;
|
||||
private final LoanAssembler loanAssembler;
|
||||
|
||||
@Override
|
||||
public Collection<DelinquencyRangeData> retrieveAllDelinquencyRanges() {
|
||||
final List<DelinquencyRange> delinquencyRangeList = repositoryRange.findAll();
|
||||
return mapperRange.map(delinquencyRangeList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DelinquencyRangeData retrieveDelinquencyRange(Long delinquencyRangeId) {
|
||||
DelinquencyRange delinquencyRangeList = repositoryRange.getReferenceById(delinquencyRangeId);
|
||||
return mapperRange.map(delinquencyRangeList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<DelinquencyBucketData> retrieveAllDelinquencyBuckets() {
|
||||
final List<DelinquencyBucket> delinquencyRangeList = repositoryBucket.findAll();
|
||||
return mapperBucket.map(delinquencyRangeList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DelinquencyBucketData retrieveDelinquencyBucket(Long delinquencyBucketId) {
|
||||
try {
|
||||
final DelinquencyBucket delinquencyBucket = repositoryBucket.getReferenceById(delinquencyBucketId);
|
||||
final DelinquencyBucketData delinquencyBucketData = mapperBucket.map(delinquencyBucket);
|
||||
|
||||
final DelinquencyBucketMappingMapper rmMappings = new DelinquencyBucketMappingMapper();
|
||||
final String sql = "select " + rmMappings.schema() + " where buc.id = ? order by dran.min_age_days";
|
||||
List<DelinquencyRangeData> ranges = this.jdbcTemplate.query(sql, rmMappings, delinquencyBucketId); // NOSONAR
|
||||
delinquencyBucketData.setRanges(ranges);
|
||||
|
||||
return delinquencyBucketData;
|
||||
} catch (final EmptyResultDataAccessException e) {
|
||||
throw DelinquencyBucketNotFoundException.notFound(delinquencyBucketId, e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public DelinquencyRangeData retrieveCurrentDelinquencyTag(Long loanId) {
|
||||
final Loan loan = this.loanAssembler.assembleFrom(loanId);
|
||||
Optional<LoanDelinquencyTagHistory> optLoanDelinquencyTag = this.repositoryLoanDelinquencyTagHistory.findByLoanAndLiftedOnDate(loan,
|
||||
null);
|
||||
if (optLoanDelinquencyTag.isPresent()) {
|
||||
return mapperRange.map(optLoanDelinquencyTag.get().getDelinquencyRange());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static final class DelinquencyBucketMappingMapper implements RowMapper<DelinquencyRangeData> {
|
||||
|
||||
public String schema() {
|
||||
return " dran.id as id, dran.classification as classification, dran.min_age_days as minimumAgeDays, dran.max_age_days as maximumAgeDays from m_delinquency_bucket buc "
|
||||
+ " inner join m_delinquency_bucket_mappings dmap on dmap.delinquency_bucket_id = buc.id "
|
||||
+ " inner join m_delinquency_range dran on dran.id = dmap.delinquency_range_id ";
|
||||
}
|
||||
|
||||
@Override
|
||||
public DelinquencyRangeData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
|
||||
|
||||
final Long id = rs.getLong("id");
|
||||
final String classification = rs.getString("classification");
|
||||
final Integer minimumAgeDays = rs.getInt("minimumAgeDays");
|
||||
final Integer maximumAgeDays = rs.getInt("maximumAgeDays");
|
||||
|
||||
return new DelinquencyRangeData(id, classification, minimumAgeDays, maximumAgeDays);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* 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 org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
|
||||
public interface DelinquencyWritePlatformService {
|
||||
|
||||
CommandProcessingResult createDelinquencyRange(JsonCommand command);
|
||||
|
||||
CommandProcessingResult updateDelinquencyRange(Long delinquencyRangeId, JsonCommand command);
|
||||
|
||||
CommandProcessingResult deleteDelinquencyRange(Long delinquencyRangeId, JsonCommand command);
|
||||
|
||||
CommandProcessingResult setLoanDelinquencyTag(Long loanId, Long delinquencyRangeId, JsonCommand command);
|
||||
|
||||
CommandProcessingResult createDelinquencyBucket(JsonCommand command);
|
||||
|
||||
CommandProcessingResult updateDelinquencyBucket(Long delinquencyBucketId, JsonCommand command);
|
||||
|
||||
CommandProcessingResult deleteDelinquencyBucket(Long delinquencyBucketId, JsonCommand command);
|
||||
|
||||
}
|
||||
+278
@@ -0,0 +1,278 @@
|
||||
/**
|
||||
* 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.time.LocalDate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
|
||||
import org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.portfolio.delinquency.api.DelinquencyApiConstants;
|
||||
import org.apache.fineract.portfolio.delinquency.data.DelinquencyBucketData;
|
||||
import org.apache.fineract.portfolio.delinquency.data.DelinquencyRangeData;
|
||||
import org.apache.fineract.portfolio.delinquency.domain.DelinquencyBucket;
|
||||
import org.apache.fineract.portfolio.delinquency.domain.DelinquencyBucketMappings;
|
||||
import org.apache.fineract.portfolio.delinquency.domain.DelinquencyBucketMappingsRepository;
|
||||
import org.apache.fineract.portfolio.delinquency.domain.DelinquencyBucketRepository;
|
||||
import org.apache.fineract.portfolio.delinquency.domain.DelinquencyRange;
|
||||
import org.apache.fineract.portfolio.delinquency.domain.DelinquencyRangeRepository;
|
||||
import org.apache.fineract.portfolio.delinquency.domain.LoanDelinquencyTagHistory;
|
||||
import org.apache.fineract.portfolio.delinquency.domain.LoanDelinquencyTagHistoryRepository;
|
||||
import org.apache.fineract.portfolio.delinquency.exception.DelinquencyBucketAgesOverlapedException;
|
||||
import org.apache.fineract.portfolio.delinquency.exception.DelinquencyRangeInvalidAgesException;
|
||||
import org.apache.fineract.portfolio.delinquency.validator.DelinquencyBucketParseAndValidator;
|
||||
import org.apache.fineract.portfolio.delinquency.validator.DelinquencyRangeParseAndValidator;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper;
|
||||
import org.apache.fineract.portfolio.loanproduct.domain.LoanProductRepository;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class DelinquencyWritePlatformServiceImpl implements DelinquencyWritePlatformService {
|
||||
|
||||
private final DelinquencyBucketParseAndValidator dataValidatorBucket;
|
||||
private final DelinquencyRangeParseAndValidator dataValidatorRange;
|
||||
|
||||
private final DelinquencyRangeRepository repositoryRange;
|
||||
private final DelinquencyBucketRepository repositoryBucket;
|
||||
private final DelinquencyBucketMappingsRepository repositoryBucketMappings;
|
||||
private final LoanDelinquencyTagHistoryRepository loanDelinquencyTagRepository;
|
||||
private final LoanRepositoryWrapper loanRepository;
|
||||
private final LoanProductRepository loanProductRepository;
|
||||
|
||||
@Override
|
||||
public CommandProcessingResult createDelinquencyRange(JsonCommand command) {
|
||||
DelinquencyRangeData data = dataValidatorRange.validateAndParseUpdate(command);
|
||||
Map<String, Object> changes = new HashMap<>();
|
||||
DelinquencyRange delinquencyRange = createDelinquencyRange(data, changes);
|
||||
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(delinquencyRange.getId()).with(changes)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandProcessingResult updateDelinquencyRange(Long delinquencyRangeId, JsonCommand command) {
|
||||
DelinquencyRangeData data = dataValidatorRange.validateAndParseUpdate(command);
|
||||
DelinquencyRange delinquencyRange = this.repositoryRange.getReferenceById(delinquencyRangeId);
|
||||
Map<String, Object> changes = new HashMap<>();
|
||||
delinquencyRange = updateDelinquencyRange(delinquencyRange, data, changes);
|
||||
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(delinquencyRange.getId()).with(changes)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandProcessingResult deleteDelinquencyRange(Long delinquencyRangeId, JsonCommand command) {
|
||||
final DelinquencyRange delinquencyRange = repositoryRange.getReferenceById(delinquencyRangeId);
|
||||
if (delinquencyRange != null) {
|
||||
final Long delinquencyRangeLinked = this.loanDelinquencyTagRepository.countByDelinquencyRange(delinquencyRange);
|
||||
if (delinquencyRangeLinked > 0) {
|
||||
throw new PlatformDataIntegrityException("error.msg.data.integrity.issue.entity.linked",
|
||||
"Data integrity issue with resource: " + delinquencyRange.getId());
|
||||
}
|
||||
repositoryRange.delete(delinquencyRange);
|
||||
}
|
||||
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(delinquencyRange.getId()).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandProcessingResult setLoanDelinquencyTag(Long loanId, Long delinquencyRangeId, JsonCommand command) {
|
||||
setLoanDelinquencyTag(loanId, delinquencyRangeId);
|
||||
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(loanId).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandProcessingResult createDelinquencyBucket(JsonCommand command) {
|
||||
DelinquencyBucketData data = dataValidatorBucket.validateAndParseUpdate(command);
|
||||
Map<String, Object> changes = new HashMap<>();
|
||||
DelinquencyBucket delinquencyBucket = createDelinquencyBucket(data, changes);
|
||||
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(delinquencyBucket.getId()).with(changes)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandProcessingResult updateDelinquencyBucket(Long delinquencyBucketId, JsonCommand command) {
|
||||
DelinquencyBucketData data = dataValidatorBucket.validateAndParseUpdate(command);
|
||||
DelinquencyBucket delinquencyBucket = this.repositoryBucket.getReferenceById(delinquencyBucketId);
|
||||
|
||||
Map<String, Object> changes = new HashMap<>();
|
||||
delinquencyBucket = updateDelinquencyBucket(delinquencyBucket, data, changes);
|
||||
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(delinquencyBucket.getId()).with(changes)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandProcessingResult deleteDelinquencyBucket(Long delinquencyBucketId, JsonCommand command) {
|
||||
final DelinquencyBucket delinquencyBucket = repositoryBucket.getReferenceById(delinquencyBucketId);
|
||||
if (delinquencyBucket != null) {
|
||||
Long delinquencyBucketLinked = this.loanProductRepository.countByDelinquencyBucket(delinquencyBucket);
|
||||
if (delinquencyBucketLinked > 0) {
|
||||
throw new PlatformDataIntegrityException("error.msg.data.integrity.issue.entity.linked",
|
||||
"Data integrity issue with resource: " + delinquencyBucket.getId());
|
||||
}
|
||||
repositoryBucket.delete(delinquencyBucket);
|
||||
}
|
||||
return new CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(delinquencyBucket.getId()).build();
|
||||
}
|
||||
|
||||
private DelinquencyRange createDelinquencyRange(DelinquencyRangeData data, Map<String, Object> changes) {
|
||||
Optional<DelinquencyRange> delinquencyRange = repositoryRange.findByClassification(data.getClassification());
|
||||
|
||||
if (delinquencyRange.isEmpty()) {
|
||||
if (data.getMinimumAgeDays() > data.getMaximumAgeDays()) {
|
||||
final String errorMessage = "The age days values are invalid, the maximum age days can't be lower than minimum age days";
|
||||
throw new DelinquencyRangeInvalidAgesException(errorMessage, data.getMinimumAgeDays(), data.getMaximumAgeDays());
|
||||
}
|
||||
DelinquencyRange newDelinquencyRange = DelinquencyRange.instance(data.getClassification(), data.getMinimumAgeDays(),
|
||||
data.getMaximumAgeDays());
|
||||
return repositoryRange.saveAndFlush(newDelinquencyRange);
|
||||
} else {
|
||||
throw new PlatformDataIntegrityException("error.msg.data.integrity.issue.entity.duplicated",
|
||||
"Data integrity issue with resource: " + delinquencyRange.get().getId());
|
||||
}
|
||||
}
|
||||
|
||||
private DelinquencyRange updateDelinquencyRange(DelinquencyRange delinquencyRange, DelinquencyRangeData data,
|
||||
Map<String, Object> changes) {
|
||||
if (!data.getClassification().equalsIgnoreCase(delinquencyRange.getClassification())) {
|
||||
delinquencyRange.setClassification(data.getClassification());
|
||||
changes.put(DelinquencyApiConstants.CLASSIFICATION_PARAM_NAME, data.getClassification());
|
||||
}
|
||||
if (!data.getMinimumAgeDays().equals(delinquencyRange.getMinimumAgeDays())) {
|
||||
delinquencyRange.setMinimumAgeDays(data.getMinimumAgeDays());
|
||||
changes.put(DelinquencyApiConstants.MINIMUMAGEDAYS_PARAM_NAME, data.getMinimumAgeDays());
|
||||
}
|
||||
if (!data.getMaximumAgeDays().equals(delinquencyRange.getMaximumAgeDays())) {
|
||||
delinquencyRange.setMaximumAgeDays(data.getMaximumAgeDays());
|
||||
changes.put(DelinquencyApiConstants.MAXIMUMAGEDAYS_PARAM_NAME, data.getMaximumAgeDays());
|
||||
}
|
||||
if (!changes.isEmpty()) {
|
||||
delinquencyRange = repositoryRange.saveAndFlush(delinquencyRange);
|
||||
}
|
||||
return delinquencyRange;
|
||||
}
|
||||
|
||||
private DelinquencyBucket createDelinquencyBucket(DelinquencyBucketData data, Map<String, Object> changes) {
|
||||
Optional<DelinquencyBucket> delinquencyBucket = repositoryBucket.findByName(data.getName());
|
||||
|
||||
if (delinquencyBucket.isEmpty()) {
|
||||
DelinquencyBucket newDelinquencyBucket = new DelinquencyBucket(data.getName());
|
||||
repositoryBucket.save(newDelinquencyBucket);
|
||||
setDelinquencyBucketMappings(newDelinquencyBucket, data);
|
||||
return newDelinquencyBucket;
|
||||
} else {
|
||||
throw new PlatformDataIntegrityException("error.msg.data.integrity.issue.entity.duplicated",
|
||||
"Data integrity issue with resource: " + delinquencyBucket.get().getId());
|
||||
}
|
||||
}
|
||||
|
||||
private DelinquencyBucket updateDelinquencyBucket(DelinquencyBucket delinquencyBucket, DelinquencyBucketData data,
|
||||
Map<String, Object> changes) {
|
||||
if (!data.getName().equalsIgnoreCase(delinquencyBucket.getName())) {
|
||||
delinquencyBucket.setName(data.getName());
|
||||
changes.put(DelinquencyApiConstants.NAME_PARAM_NAME, data.getName());
|
||||
}
|
||||
if (!changes.isEmpty()) {
|
||||
delinquencyBucket = repositoryBucket.save(delinquencyBucket);
|
||||
}
|
||||
setDelinquencyBucketMappings(delinquencyBucket, data);
|
||||
return delinquencyBucket;
|
||||
}
|
||||
|
||||
private void setDelinquencyBucketMappings(DelinquencyBucket delinquencyBucket, DelinquencyBucketData data) {
|
||||
List<Long> rangeIds = new ArrayList<>();
|
||||
data.getRanges().forEach(dataRange -> {
|
||||
rangeIds.add(dataRange.getId());
|
||||
});
|
||||
|
||||
List<DelinquencyRange> ranges = repositoryRange.findAllById(rangeIds);
|
||||
validateDelinquencyRanges(ranges);
|
||||
List<DelinquencyBucketMappings> bucketMappings = repositoryBucketMappings.findByDelinquencyBucket(delinquencyBucket);
|
||||
repositoryBucketMappings.deleteAll(bucketMappings);
|
||||
bucketMappings.clear();
|
||||
for (DelinquencyRange delinquencyRange : ranges) {
|
||||
bucketMappings.add(DelinquencyBucketMappings.instance(delinquencyBucket, delinquencyRange));
|
||||
}
|
||||
repositoryBucketMappings.saveAllAndFlush(bucketMappings);
|
||||
}
|
||||
|
||||
private void validateDelinquencyRanges(List<DelinquencyRange> ranges) {
|
||||
// Sort the ranges based on the minAgeDays
|
||||
final Comparator<DelinquencyRange> orderByMinAge = new Comparator<DelinquencyRange>() {
|
||||
|
||||
@Override
|
||||
public int compare(DelinquencyRange o1, DelinquencyRange o2) {
|
||||
return o1.getMinimumAgeDays().compareTo(o2.getMinimumAgeDays());
|
||||
}
|
||||
};
|
||||
Collections.sort(ranges, orderByMinAge);
|
||||
DelinquencyRange prevDelinquencyRange = null;
|
||||
for (DelinquencyRange delinquencyRange : ranges) {
|
||||
if (prevDelinquencyRange != null) {
|
||||
if (isOverlaped(prevDelinquencyRange, delinquencyRange)) {
|
||||
final String errorMessage = "The delinquency ranges age days values are overlaped";
|
||||
throw new DelinquencyBucketAgesOverlapedException(errorMessage, prevDelinquencyRange, delinquencyRange);
|
||||
}
|
||||
}
|
||||
prevDelinquencyRange = delinquencyRange;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isOverlaped(DelinquencyRange o1, DelinquencyRange o2) {
|
||||
return Math.max(o1.getMinimumAgeDays(), o2.getMinimumAgeDays()) <= Math.min(o1.getMaximumAgeDays(), o2.getMaximumAgeDays());
|
||||
}
|
||||
|
||||
public void setLoanDelinquencyTag(Long loanId, Long delinquencyRangeId) {
|
||||
final Loan loan = this.loanRepository.findOneWithNotFoundDetection(loanId);
|
||||
|
||||
final LocalDate transactionDate = DateUtils.getLocalDateOfTenant();
|
||||
List<LoanDelinquencyTagHistory> loanDelinquencyTagHistory = this.loanDelinquencyTagRepository
|
||||
.findByLoanOrderByAddedOnDateDesc(loan);
|
||||
// The delinquencyRangeId in null means just goes out from Delinquency
|
||||
if (delinquencyRangeId == null) {
|
||||
// The Loan will go out from Delinquency
|
||||
if (!loanDelinquencyTagHistory.isEmpty()) {
|
||||
LoanDelinquencyTagHistory loanDelinquencyTagPrev = loanDelinquencyTagHistory.get(0);
|
||||
loanDelinquencyTagPrev.setLiftedOnDate(transactionDate);
|
||||
this.loanDelinquencyTagRepository.saveAndFlush(loanDelinquencyTagPrev);
|
||||
}
|
||||
} else {
|
||||
// The previous Loan Delinquency Tag will set as Lifted
|
||||
if (!loanDelinquencyTagHistory.isEmpty()) {
|
||||
LoanDelinquencyTagHistory loanDelinquencyTagPrev = loanDelinquencyTagHistory.get(0);
|
||||
loanDelinquencyTagPrev.setLiftedOnDate(transactionDate);
|
||||
this.loanDelinquencyTagRepository.save(loanDelinquencyTagPrev);
|
||||
}
|
||||
|
||||
final DelinquencyRange delinquencyRange = repositoryRange.getReferenceById(delinquencyRangeId);
|
||||
LoanDelinquencyTagHistory loanDelinquencyTag = new LoanDelinquencyTagHistory(delinquencyRange, loan, transactionDate, null);
|
||||
loanDelinquencyTagHistory.add(loanDelinquencyTag);
|
||||
this.loanDelinquencyTagRepository.saveAndFlush(loanDelinquencyTag);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
/**
|
||||
* 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.validator;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
|
||||
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
|
||||
import org.apache.fineract.infrastructure.core.validator.ParseAndValidator;
|
||||
import org.apache.fineract.portfolio.delinquency.api.DelinquencyApiConstants;
|
||||
import org.apache.fineract.portfolio.delinquency.data.DelinquencyBucketData;
|
||||
import org.apache.fineract.portfolio.delinquency.data.DelinquencyRangeData;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Component
|
||||
public class DelinquencyBucketParseAndValidator extends ParseAndValidator {
|
||||
|
||||
private final FromJsonHelper jsonHelper;
|
||||
|
||||
public DelinquencyBucketData validateAndParseUpdate(@NotNull final JsonCommand command) {
|
||||
final DataValidatorBuilder dataValidator = new DataValidatorBuilder(new ArrayList<>()).resource("delinquencyBucket.create");
|
||||
JsonObject element = extractJsonObject(jsonHelper, command);
|
||||
|
||||
DelinquencyBucketData result = validateAndParseUpdate(dataValidator, element, jsonHelper);
|
||||
throwExceptionIfValidationWarningsExist(dataValidator);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private DelinquencyBucketData validateAndParseUpdate(final DataValidatorBuilder dataValidator, JsonObject element,
|
||||
FromJsonHelper jsonHelper) {
|
||||
if (element == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
jsonHelper.checkForUnsupportedParameters(element,
|
||||
List.of(DelinquencyApiConstants.NAME_PARAM_NAME, DelinquencyApiConstants.RANGES_PARAM_NAME));
|
||||
|
||||
final String name = jsonHelper.extractStringNamed(DelinquencyApiConstants.NAME_PARAM_NAME, element);
|
||||
|
||||
dataValidator.reset().parameter(DelinquencyApiConstants.NAME_PARAM_NAME).value(name).notBlank();
|
||||
|
||||
final String[] rangeIds = jsonHelper.extractArrayNamed(DelinquencyApiConstants.RANGES_PARAM_NAME, element);
|
||||
dataValidator.reset().parameter(DelinquencyApiConstants.RANGES_PARAM_NAME).value(rangeIds).notNull().arrayNotEmpty();
|
||||
|
||||
ArrayList<DelinquencyRangeData> ranges = new ArrayList<>();
|
||||
if (rangeIds != null) {
|
||||
for (String rangeId : rangeIds) {
|
||||
ranges.add(DelinquencyRangeData.reference(Long.parseLong(rangeId)));
|
||||
}
|
||||
}
|
||||
return dataValidator.hasError() ? null : new DelinquencyBucketData(null, name, ranges);
|
||||
}
|
||||
|
||||
}
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
/**
|
||||
* 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.validator;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
|
||||
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
|
||||
import org.apache.fineract.infrastructure.core.validator.ParseAndValidator;
|
||||
import org.apache.fineract.portfolio.delinquency.api.DelinquencyApiConstants;
|
||||
import org.apache.fineract.portfolio.delinquency.data.DelinquencyRangeData;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Component
|
||||
public class DelinquencyRangeParseAndValidator extends ParseAndValidator {
|
||||
|
||||
private final FromJsonHelper jsonHelper;
|
||||
|
||||
public DelinquencyRangeData validateAndParseUpdate(@NotNull final JsonCommand command) {
|
||||
final DataValidatorBuilder dataValidator = new DataValidatorBuilder(new ArrayList<>()).resource("delinquencyrange.create");
|
||||
JsonObject element = extractJsonObject(jsonHelper, command);
|
||||
|
||||
DelinquencyRangeData result = validateAndParseUpdate(dataValidator, element, jsonHelper);
|
||||
throwExceptionIfValidationWarningsExist(dataValidator);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private DelinquencyRangeData validateAndParseUpdate(final DataValidatorBuilder dataValidator, JsonObject element,
|
||||
FromJsonHelper jsonHelper) {
|
||||
if (element == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
jsonHelper.checkForUnsupportedParameters(element,
|
||||
List.of(DelinquencyApiConstants.CLASSIFICATION_PARAM_NAME, DelinquencyApiConstants.MINIMUMAGEDAYS_PARAM_NAME,
|
||||
DelinquencyApiConstants.MAXIMUMAGEDAYS_PARAM_NAME, DelinquencyApiConstants.LOCALE_PARAM_NAME));
|
||||
|
||||
final String localeValue = jsonHelper.extractStringNamed(DelinquencyApiConstants.LOCALE_PARAM_NAME, element);
|
||||
dataValidator.reset().parameter(DelinquencyApiConstants.LOCALE_PARAM_NAME).value(localeValue).notBlank();
|
||||
final Locale locale = jsonHelper.extractLocaleParameter(element);
|
||||
|
||||
final String classification = jsonHelper.extractStringNamed(DelinquencyApiConstants.CLASSIFICATION_PARAM_NAME, element);
|
||||
final Integer minimumAge = jsonHelper.extractIntegerNamed(DelinquencyApiConstants.MINIMUMAGEDAYS_PARAM_NAME, element, locale);
|
||||
final Integer maximumAge = jsonHelper.extractIntegerNamed(DelinquencyApiConstants.MAXIMUMAGEDAYS_PARAM_NAME, element, locale);
|
||||
dataValidator.reset().parameter(DelinquencyApiConstants.CLASSIFICATION_PARAM_NAME).value(classification).notBlank();
|
||||
dataValidator.reset().parameter(DelinquencyApiConstants.MINIMUMAGEDAYS_PARAM_NAME).value(minimumAge).notBlank()
|
||||
.integerGreaterThanNumber(0);
|
||||
dataValidator.reset().parameter(DelinquencyApiConstants.MAXIMUMAGEDAYS_PARAM_NAME).value(maximumAge).ignoreIfNull()
|
||||
.integerGreaterThanNumber(0);
|
||||
|
||||
return dataValidator.hasError() ? null : DelinquencyRangeData.instance(classification, minimumAge, maximumAge);
|
||||
}
|
||||
|
||||
}
|
||||
+27
-16
@@ -38,6 +38,7 @@ import org.apache.fineract.portfolio.accountdetails.data.LoanAccountSummaryData;
|
||||
import org.apache.fineract.portfolio.calendar.data.CalendarData;
|
||||
import org.apache.fineract.portfolio.charge.data.ChargeData;
|
||||
import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
|
||||
import org.apache.fineract.portfolio.delinquency.data.DelinquencyRangeData;
|
||||
import org.apache.fineract.portfolio.floatingrates.data.InterestRatePeriodData;
|
||||
import org.apache.fineract.portfolio.fund.data.FundData;
|
||||
import org.apache.fineract.portfolio.group.data.GroupGeneralData;
|
||||
@@ -239,6 +240,7 @@ public final class LoanAccountData {
|
||||
private LocalDate expectedDisbursementDate;
|
||||
|
||||
private final CollectionData delinquent;
|
||||
private final DelinquencyRangeData delinquencyRange;
|
||||
|
||||
public static LoanAccountData importInstanceIndividual(EnumOptionData loanTypeEnumOption, Long clientId, Long productId,
|
||||
Long loanOfficerId, LocalDate submittedOnDate, Long fundId, BigDecimal principal, Integer numberOfRepayments,
|
||||
@@ -426,6 +428,7 @@ public final class LoanAccountData {
|
||||
this.isRatesEnabled = false;
|
||||
this.fixedPrincipalPercentagePerInstallment = null;
|
||||
this.delinquent = null;
|
||||
this.delinquencyRange = null;
|
||||
}
|
||||
|
||||
public Integer getRowIndex() {
|
||||
@@ -592,6 +595,7 @@ public final class LoanAccountData {
|
||||
final Boolean isRatesEnabled = false;
|
||||
final BigDecimal fixedPrincipalPercentagePerInstallment = null;
|
||||
final CollectionData delinquent = CollectionData.template();
|
||||
final DelinquencyRangeData delinquencyRange = null;
|
||||
|
||||
return new LoanAccountData(id, accountNo, status, externalId, clientId, clientAccountNo, clientName, clientOfficeId, group,
|
||||
loanType, loanProductId, loanProductName, loanProductDescription, isLoanProductLinkedToFloatingRate, fundId, fundName,
|
||||
@@ -613,7 +617,7 @@ public final class LoanAccountData {
|
||||
interestRecalculationData, originalSchedule, createStandingInstructionAtDisbursement, paidInAdvance, interestRatesPeriods,
|
||||
isVariableInstallmentsAllowed, minimumGap, maximumGap, subStatus, canUseForTopup, clientActiveLoanOptions, isTopup,
|
||||
closureLoanId, closureLoanAccountNo, topupAmount, isEqualAmortization, rates, isRatesEnabled,
|
||||
fixedPrincipalPercentagePerInstallment, delinquent);
|
||||
fixedPrincipalPercentagePerInstallment, delinquent, delinquencyRange);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -738,6 +742,7 @@ public final class LoanAccountData {
|
||||
final Boolean isRatesEnabled = false;
|
||||
final BigDecimal fixedPrincipalPercentagePerInstallment = null;
|
||||
final CollectionData delinquent = CollectionData.template();
|
||||
final DelinquencyRangeData delinquencyRange = null;
|
||||
|
||||
return new LoanAccountData(id, accountNo, status, externalId, clientId, clientAccountNo, clientName, clientOfficeId, group,
|
||||
loanType, loanProductId, loanProductName, loanProductDescription, isLoanProductLinkedToFloatingRate, fundId, fundName,
|
||||
@@ -759,7 +764,7 @@ public final class LoanAccountData {
|
||||
originalSchedule, createStandingInstructionAtDisbursement, paidInAdvance, interestRatesPeriods,
|
||||
isVariableInstallmentsAllowed, minimumGap, maximumGap, subStatus, canUseForTopup, clientActiveLoanOptions, isTopup,
|
||||
closureLoanId, closureLoanAccountNo, topupAmount, isEqualAmortization, rates, isRatesEnabled,
|
||||
fixedPrincipalPercentagePerInstallment, delinquent);
|
||||
fixedPrincipalPercentagePerInstallment, delinquent, delinquencyRange);
|
||||
}
|
||||
|
||||
public static LoanAccountData populateClientDefaults(final LoanAccountData acc, final LoanAccountData clientAcc) {
|
||||
@@ -790,7 +795,7 @@ public final class LoanAccountData {
|
||||
acc.createStandingInstructionAtDisbursement, acc.paidInAdvance, acc.interestRatesPeriods, acc.isVariableInstallmentsAllowed,
|
||||
acc.minimumGap, acc.maximumGap, acc.subStatus, acc.canUseForTopup, acc.clientActiveLoanOptions, acc.isTopup,
|
||||
acc.closureLoanId, acc.closureLoanAccountNo, acc.topupAmount, acc.isEqualAmortization, acc.rates, acc.isRatesEnabled,
|
||||
acc.fixedPrincipalPercentagePerInstallment, acc.delinquent);
|
||||
acc.fixedPrincipalPercentagePerInstallment, acc.delinquent, acc.delinquencyRange);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -917,6 +922,7 @@ public final class LoanAccountData {
|
||||
final Boolean isRatesEnabled = false;
|
||||
final BigDecimal fixedPrincipalPercentagePerInstallment = null;
|
||||
final CollectionData delinquent = CollectionData.template();
|
||||
final DelinquencyRangeData delinquencyRange = null;
|
||||
|
||||
return new LoanAccountData(id, accountNo, status, externalId, clientId, clientAccountNo, clientName, clientOfficeId, group,
|
||||
loanType, loanProductId, loanProductName, loanProductDescription, isLoanProductLinkedToFloatingRate, fundId, fundName,
|
||||
@@ -938,7 +944,7 @@ public final class LoanAccountData {
|
||||
originalSchedule, createStandingInstructionAtDisbursement, paidInAdvance, interestRatesPeriods,
|
||||
isVariableInstallmentsAllowed, minimumGap, maximumGap, subStatus, canUseForTopup, clientActiveLoanOptions, isTopup,
|
||||
closureLoanId, closureLoanAccountNo, topupAmount, isEqualAmortization, rates, isRatesEnabled,
|
||||
fixedPrincipalPercentagePerInstallment, delinquent);
|
||||
fixedPrincipalPercentagePerInstallment, delinquent, delinquencyRange);
|
||||
}
|
||||
|
||||
public static LoanAccountData populateGroupDefaults(final LoanAccountData acc, final LoanAccountData groupAcc) {
|
||||
@@ -968,7 +974,7 @@ public final class LoanAccountData {
|
||||
acc.createStandingInstructionAtDisbursement, acc.paidInAdvance, acc.interestRatesPeriods, acc.isVariableInstallmentsAllowed,
|
||||
acc.minimumGap, acc.maximumGap, acc.subStatus, acc.canUseForTopup, acc.clientActiveLoanOptions, acc.isTopup,
|
||||
acc.closureLoanId, acc.closureLoanAccountNo, acc.topupAmount, acc.isEqualAmortization, acc.rates, acc.isRatesEnabled,
|
||||
acc.fixedPrincipalPercentagePerInstallment, acc.delinquent);
|
||||
acc.fixedPrincipalPercentagePerInstallment, acc.delinquent, acc.delinquencyRange);
|
||||
}
|
||||
|
||||
public static LoanAccountData loanProductWithTemplateDefaults(final LoanProductData product,
|
||||
@@ -1110,6 +1116,7 @@ public final class LoanAccountData {
|
||||
final List<RateData> rates = null;
|
||||
final Boolean isRatesEnabled = false;
|
||||
final CollectionData delinquent = CollectionData.template();
|
||||
final DelinquencyRangeData delinquencyRange = null;
|
||||
|
||||
return new LoanAccountData(id, accountNo, status, externalId, clientId, clientAccountNo, clientName, clientOfficeId, group,
|
||||
loanType, product.getId(), product.getName(), product.getDescription(), product.isLinkedToFloatingInterestRates(),
|
||||
@@ -1136,7 +1143,7 @@ public final class LoanAccountData {
|
||||
product.isVariableInstallmentsAllowed(), product.getMinimumGapBetweenInstallments(),
|
||||
product.getMaximumGapBetweenInstallments(), subStatus, canUseForTopup, clientActiveLoanOptions, isTopup, closureLoanId,
|
||||
closureLoanAccountNo, topupAmount, product.isEqualAmortization(), rates, isRatesEnabled,
|
||||
product.getFixedPrincipalPercentagePerInstallment(), delinquent);
|
||||
product.getFixedPrincipalPercentagePerInstallment(), delinquent, delinquencyRange);
|
||||
}
|
||||
|
||||
public static LoanAccountData populateLoanProductDefaults(final LoanAccountData acc, final LoanProductData product) {
|
||||
@@ -1179,6 +1186,7 @@ public final class LoanAccountData {
|
||||
}
|
||||
}
|
||||
final CollectionData delinquent = CollectionData.template();
|
||||
final DelinquencyRangeData delinquencyRange = null;
|
||||
|
||||
return new LoanAccountData(acc.id, acc.accountNo, acc.status, acc.externalId, acc.clientId, acc.clientAccountNo, acc.clientName,
|
||||
acc.clientOfficeId, acc.group, acc.loanType, product.getId(), product.getName(), product.getDescription(),
|
||||
@@ -1206,7 +1214,7 @@ public final class LoanAccountData {
|
||||
product.isVariableInstallmentsAllowed(), product.getMinimumGapBetweenInstallments(),
|
||||
product.getMaximumGapBetweenInstallments(), acc.subStatus, acc.canUseForTopup, acc.clientActiveLoanOptions, acc.isTopup,
|
||||
acc.closureLoanId, acc.closureLoanAccountNo, acc.topupAmount, product.isEqualAmortization(), acc.rates, acc.isRatesEnabled,
|
||||
product.getFixedPrincipalPercentagePerInstallment(), delinquent);
|
||||
product.getFixedPrincipalPercentagePerInstallment(), delinquent, delinquencyRange);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1237,7 +1245,8 @@ public final class LoanAccountData {
|
||||
final LoanInterestRecalculationData interestRecalculationData, final Boolean createStandingInstructionAtDisbursement,
|
||||
final Boolean isVariableInstallmentsAllowed, Integer minimumGap, Integer maximumGap, final EnumOptionData subStatus,
|
||||
final boolean canUseForTopup, final boolean isTopup, final Long closureLoanId, final String closureLoanAccountNo,
|
||||
final BigDecimal topupAmount, final boolean isEqualAmortization, final BigDecimal fixedPrincipalPercentagePerInstallment) {
|
||||
final BigDecimal topupAmount, final boolean isEqualAmortization, final BigDecimal fixedPrincipalPercentagePerInstallment,
|
||||
final DelinquencyRangeData delinquencyRange) {
|
||||
|
||||
final LoanScheduleData repaymentSchedule = null;
|
||||
final Collection<LoanTransactionData> transactions = null;
|
||||
@@ -1297,7 +1306,7 @@ public final class LoanAccountData {
|
||||
isNPA, daysInMonthType, daysInYearType, isInterestRecalculationEnabled, interestRecalculationData, originalSchedule,
|
||||
createStandingInstructionAtDisbursement, paidInAdvance, interestRatesPeriods, isVariableInstallmentsAllowed, minimumGap,
|
||||
maximumGap, subStatus, canUseForTopup, clientActiveLoanOptions, isTopup, closureLoanId, closureLoanAccountNo, topupAmount,
|
||||
isEqualAmortization, rates, isRatesEnabled, fixedPrincipalPercentagePerInstallment, delinquent);
|
||||
isEqualAmortization, rates, isRatesEnabled, fixedPrincipalPercentagePerInstallment, delinquent, delinquencyRange);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1351,7 +1360,7 @@ public final class LoanAccountData {
|
||||
acc.createStandingInstructionAtDisbursement, paidInAdvance, interestRatesPeriods, acc.isVariableInstallmentsAllowed,
|
||||
acc.minimumGap, acc.maximumGap, acc.subStatus, acc.canUseForTopup, clientActiveLoanOptions, acc.isTopup, acc.closureLoanId,
|
||||
acc.closureLoanAccountNo, acc.topupAmount, acc.isEqualAmortization, rates, isRatesEnabled,
|
||||
acc.fixedPrincipalPercentagePerInstallment, delinquent);
|
||||
acc.fixedPrincipalPercentagePerInstallment, delinquent, acc.delinquencyRange);
|
||||
}
|
||||
|
||||
public static LoanAccountData associationsAndTemplate(final LoanAccountData acc, final Collection<LoanProductData> productOptions,
|
||||
@@ -1394,7 +1403,7 @@ public final class LoanAccountData {
|
||||
acc.createStandingInstructionAtDisbursement, acc.paidInAdvance, acc.interestRatesPeriods, acc.isVariableInstallmentsAllowed,
|
||||
acc.minimumGap, acc.maximumGap, acc.subStatus, acc.canUseForTopup, acc.clientActiveLoanOptions, acc.isTopup,
|
||||
acc.closureLoanId, acc.closureLoanAccountNo, acc.topupAmount, acc.isEqualAmortization, acc.rates, acc.isRatesEnabled,
|
||||
acc.fixedPrincipalPercentagePerInstallment, acc.delinquent);
|
||||
acc.fixedPrincipalPercentagePerInstallment, acc.delinquent, acc.delinquencyRange);
|
||||
}
|
||||
|
||||
public static LoanAccountData associateMemberVariations(final LoanAccountData acc, final Map<Long, Integer> memberLoanCycle) {
|
||||
@@ -1460,7 +1469,7 @@ public final class LoanAccountData {
|
||||
acc.createStandingInstructionAtDisbursement, acc.paidInAdvance, acc.interestRatesPeriods, acc.isVariableInstallmentsAllowed,
|
||||
acc.minimumGap, acc.maximumGap, acc.subStatus, acc.canUseForTopup, acc.clientActiveLoanOptions, acc.isTopup,
|
||||
acc.closureLoanId, acc.closureLoanAccountNo, acc.topupAmount, acc.isEqualAmortization, acc.rates, acc.isRatesEnabled,
|
||||
acc.fixedPrincipalPercentagePerInstallment, acc.delinquent);
|
||||
acc.fixedPrincipalPercentagePerInstallment, acc.delinquent, acc.delinquencyRange);
|
||||
}
|
||||
|
||||
public static LoanAccountData withInterestRecalculationCalendarData(final LoanAccountData acc, final CalendarData calendarData,
|
||||
@@ -1494,7 +1503,7 @@ public final class LoanAccountData {
|
||||
acc.createStandingInstructionAtDisbursement, acc.paidInAdvance, acc.interestRatesPeriods, acc.isVariableInstallmentsAllowed,
|
||||
acc.minimumGap, acc.maximumGap, acc.subStatus, acc.canUseForTopup, acc.clientActiveLoanOptions, acc.isTopup,
|
||||
acc.closureLoanId, acc.closureLoanAccountNo, acc.topupAmount, acc.isEqualAmortization, acc.rates, acc.isRatesEnabled,
|
||||
acc.fixedPrincipalPercentagePerInstallment, acc.delinquent);
|
||||
acc.fixedPrincipalPercentagePerInstallment, acc.delinquent, acc.delinquencyRange);
|
||||
}
|
||||
|
||||
public static LoanAccountData withLoanCalendarData(final LoanAccountData acc, final CalendarData calendarData) {
|
||||
@@ -1523,7 +1532,7 @@ public final class LoanAccountData {
|
||||
acc.createStandingInstructionAtDisbursement, acc.paidInAdvance, acc.interestRatesPeriods, acc.isVariableInstallmentsAllowed,
|
||||
acc.minimumGap, acc.maximumGap, acc.subStatus, acc.canUseForTopup, acc.clientActiveLoanOptions, acc.isTopup,
|
||||
acc.closureLoanId, acc.closureLoanAccountNo, acc.topupAmount, acc.isEqualAmortization, acc.rates, acc.isRatesEnabled,
|
||||
acc.fixedPrincipalPercentagePerInstallment, acc.delinquent);
|
||||
acc.fixedPrincipalPercentagePerInstallment, acc.delinquent, acc.delinquencyRange);
|
||||
}
|
||||
|
||||
public static LoanAccountData withOriginalSchedule(final LoanAccountData acc, final LoanScheduleData originalSchedule) {
|
||||
@@ -1553,7 +1562,7 @@ public final class LoanAccountData {
|
||||
acc.createStandingInstructionAtDisbursement, acc.paidInAdvance, acc.interestRatesPeriods, acc.isVariableInstallmentsAllowed,
|
||||
acc.minimumGap, acc.maximumGap, acc.subStatus, acc.canUseForTopup, acc.clientActiveLoanOptions, acc.isTopup,
|
||||
acc.closureLoanId, acc.closureLoanAccountNo, acc.topupAmount, acc.isEqualAmortization, acc.rates, acc.isRatesEnabled,
|
||||
acc.fixedPrincipalPercentagePerInstallment, acc.delinquent);
|
||||
acc.fixedPrincipalPercentagePerInstallment, acc.delinquent, acc.delinquencyRange);
|
||||
}
|
||||
|
||||
private LoanAccountData(final Long id, //
|
||||
@@ -1606,7 +1615,8 @@ public final class LoanAccountData {
|
||||
final Integer minimumGap, final Integer maximumGap, final EnumOptionData subStatus, final Boolean canUseForTopup,
|
||||
final Collection<LoanAccountSummaryData> clientActiveLoanOptions, final boolean isTopup, final Long closureLoanId,
|
||||
final String closureLoanAccountNo, final BigDecimal topupAmount, final boolean isEqualAmortization, final List<RateData> rates,
|
||||
final Boolean isRatesEnabled, final BigDecimal fixedPrincipalPercentagePerInstallment, final CollectionData delinquent) {
|
||||
final Boolean isRatesEnabled, final BigDecimal fixedPrincipalPercentagePerInstallment, final CollectionData delinquent,
|
||||
final DelinquencyRangeData delinquencyRange) {
|
||||
|
||||
this.id = id;
|
||||
this.accountNo = accountNo;
|
||||
@@ -1794,6 +1804,7 @@ public final class LoanAccountData {
|
||||
this.rates = rates;
|
||||
this.fixedPrincipalPercentagePerInstallment = fixedPrincipalPercentagePerInstallment;
|
||||
this.delinquent = delinquent;
|
||||
this.delinquencyRange = delinquencyRange;
|
||||
}
|
||||
|
||||
public RepaymentScheduleRelatedLoanData repaymentScheduleRelatedData() {
|
||||
|
||||
+1
-1
@@ -151,7 +151,7 @@ public class RecalculateInterestForLoanTasklet implements Tasklet {
|
||||
List<Callable<Void>> posters = new ArrayList<>();
|
||||
int fromIndex = 0;
|
||||
int size = loanIds.size();
|
||||
double toGetCeilValue = size / threadPoolSize;
|
||||
double toGetCeilValue = size / ((double) threadPoolSize);
|
||||
batchSize = (int) Math.ceil(toGetCeilValue);
|
||||
|
||||
if (batchSize == 0) {
|
||||
|
||||
+15
-8
@@ -70,6 +70,8 @@ import org.apache.fineract.portfolio.client.domain.ClientEnumerations;
|
||||
import org.apache.fineract.portfolio.client.service.ClientReadPlatformService;
|
||||
import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
|
||||
import org.apache.fineract.portfolio.common.service.CommonEnumerations;
|
||||
import org.apache.fineract.portfolio.delinquency.data.DelinquencyRangeData;
|
||||
import org.apache.fineract.portfolio.delinquency.service.DelinquencyReadPlatformService;
|
||||
import org.apache.fineract.portfolio.floatingrates.data.InterestRatePeriodData;
|
||||
import org.apache.fineract.portfolio.floatingrates.service.FloatingRatesReadPlatformService;
|
||||
import org.apache.fineract.portfolio.fund.data.FundData;
|
||||
@@ -157,6 +159,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
|
||||
private final AccountDetailsReadPlatformService accountDetailsReadPlatformService;
|
||||
private final ColumnValidator columnValidator;
|
||||
private final DatabaseSpecificSQLGenerator sqlGenerator;
|
||||
private final DelinquencyReadPlatformService delinquencyReadPlatformService;
|
||||
|
||||
@Autowired
|
||||
public LoanReadPlatformServiceImpl(final PlatformSecurityContext context,
|
||||
@@ -170,6 +173,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
|
||||
final LoanRepaymentScheduleTransactionProcessorFactory loanRepaymentScheduleTransactionProcessorFactory,
|
||||
final FloatingRatesReadPlatformService floatingRatesReadPlatformService, final LoanUtilService loanUtilService,
|
||||
final ConfigurationDomainService configurationDomainService,
|
||||
final DelinquencyReadPlatformService delinquencyReadPlatformService,
|
||||
final AccountDetailsReadPlatformService accountDetailsReadPlatformService, final LoanRepositoryWrapper loanRepositoryWrapper,
|
||||
final ColumnValidator columnValidator, DatabaseSpecificSQLGenerator sqlGenerator, PaginationHelper paginationHelper) {
|
||||
this.context = context;
|
||||
@@ -193,9 +197,10 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
|
||||
this.configurationDomainService = configurationDomainService;
|
||||
this.accountDetailsReadPlatformService = accountDetailsReadPlatformService;
|
||||
this.columnValidator = columnValidator;
|
||||
this.loaanLoanMapper = new LoanMapper(sqlGenerator);
|
||||
this.loaanLoanMapper = new LoanMapper(sqlGenerator, delinquencyReadPlatformService);
|
||||
this.sqlGenerator = sqlGenerator;
|
||||
this.paginationHelper = paginationHelper;
|
||||
this.delinquencyReadPlatformService = delinquencyReadPlatformService;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -206,7 +211,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
|
||||
final String hierarchy = currentUser.getOffice().getHierarchy();
|
||||
final String hierarchySearchString = hierarchy + "%";
|
||||
|
||||
final LoanMapper rm = new LoanMapper(sqlGenerator);
|
||||
final LoanMapper rm = new LoanMapper(sqlGenerator, delinquencyReadPlatformService);
|
||||
|
||||
final StringBuilder sqlBuilder = new StringBuilder();
|
||||
sqlBuilder.append("select ");
|
||||
@@ -226,7 +231,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
|
||||
|
||||
// final AppUser currentUser = this.context.authenticatedUser();
|
||||
this.context.authenticatedUser();
|
||||
final LoanMapper rm = new LoanMapper(sqlGenerator);
|
||||
final LoanMapper rm = new LoanMapper(sqlGenerator, delinquencyReadPlatformService);
|
||||
|
||||
final String sql = "select " + rm.loanSchema() + " where l.account_no=?";
|
||||
|
||||
@@ -237,7 +242,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
|
||||
@Override
|
||||
public List<LoanAccountData> retrieveGLIMChildLoansByGLIMParentAccount(String parentloanAccountNumber) {
|
||||
this.context.authenticatedUser();
|
||||
final LoanMapper rm = new LoanMapper(sqlGenerator);
|
||||
final LoanMapper rm = new LoanMapper(sqlGenerator, delinquencyReadPlatformService);
|
||||
|
||||
final String sql = "select " + rm.loanSchema()
|
||||
+ " left join glim_parent_child_mapping as glim on glim.glim_child_account_id=l.account_no "
|
||||
@@ -490,8 +495,6 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
|
||||
@Override
|
||||
public LoanTransactionData retrieveWaiveInterestDetails(final Long loanId) {
|
||||
|
||||
AppUser currentUser = this.context.authenticatedUser();
|
||||
|
||||
// TODO - KW -OPTIMIZE - write simple sql query to fetch back overdue
|
||||
// interest that can be waived along with the date of repayment period
|
||||
// interest is overdue.
|
||||
@@ -582,9 +585,11 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
|
||||
private static final class LoanMapper implements RowMapper<LoanAccountData> {
|
||||
|
||||
private final DatabaseSpecificSQLGenerator sqlGenerator;
|
||||
private final DelinquencyReadPlatformService delinquencyReadPlatformService;
|
||||
|
||||
LoanMapper(DatabaseSpecificSQLGenerator sqlGenerator) {
|
||||
LoanMapper(DatabaseSpecificSQLGenerator sqlGenerator, DelinquencyReadPlatformService delinquencyReadPlatformService) {
|
||||
this.sqlGenerator = sqlGenerator;
|
||||
this.delinquencyReadPlatformService = delinquencyReadPlatformService;
|
||||
}
|
||||
|
||||
public String loanSchema() {
|
||||
@@ -989,6 +994,8 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
|
||||
final Long closureLoanId = rs.getLong("closureLoanId");
|
||||
final String closureLoanAccountNo = rs.getString("closureLoanAccountNo");
|
||||
final BigDecimal topupAmount = rs.getBigDecimal("topupAmount");
|
||||
// Current Delinquency Range Data
|
||||
DelinquencyRangeData delinquencyRange = this.delinquencyReadPlatformService.retrieveCurrentDelinquencyTag(id);
|
||||
|
||||
return LoanAccountData.basicLoanDetails(id, accountNo, status, externalId, clientId, clientAccountNo, clientName,
|
||||
clientOfficeId, groupData, loanType, loanProductId, loanProductName, loanProductDescription,
|
||||
@@ -1004,7 +1011,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService {
|
||||
isNPA, daysInMonthType, daysInYearType, isInterestRecalculationEnabled, interestRecalculationData,
|
||||
createStandingInstructionAtDisbursement, isvariableInstallmentsAllowed, minimumGap, maximumGap, loanSubStatus,
|
||||
canUseForTopup, isTopup, closureLoanId, closureLoanAccountNo, topupAmount, isEqualAmortization,
|
||||
fixedPrincipalPercentagePerInstallment);
|
||||
fixedPrincipalPercentagePerInstallment, delinquencyRange);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
@@ -141,5 +141,6 @@ public interface LoanProductConstants {
|
||||
String ALLOW_APPROVED_DISBURSED_AMOUNTS_OVER_APPLIED = "allowApprovedDisbursedAmountsOverApplied";
|
||||
String OVER_APPLIED_CALCULATION_TYPE = "overAppliedCalculationType";
|
||||
String OVER_APPLIED_NUMBER = "overAppliedNumber";
|
||||
String DELINQUENCY_BUCKET_PARAM_NAME = "delinquencyBucketId";
|
||||
|
||||
}
|
||||
|
||||
+13
-2
@@ -65,6 +65,8 @@ import org.apache.fineract.organisation.monetary.service.CurrencyReadPlatformSer
|
||||
import org.apache.fineract.portfolio.charge.data.ChargeData;
|
||||
import org.apache.fineract.portfolio.charge.service.ChargeReadPlatformService;
|
||||
import org.apache.fineract.portfolio.common.service.DropdownReadPlatformService;
|
||||
import org.apache.fineract.portfolio.delinquency.data.DelinquencyBucketData;
|
||||
import org.apache.fineract.portfolio.delinquency.service.DelinquencyReadPlatformService;
|
||||
import org.apache.fineract.portfolio.floatingrates.data.FloatingRateData;
|
||||
import org.apache.fineract.portfolio.floatingrates.service.FloatingRatesReadPlatformService;
|
||||
import org.apache.fineract.portfolio.fund.data.FundData;
|
||||
@@ -130,6 +132,7 @@ public class LoanProductsApiResource {
|
||||
private final FloatingRatesReadPlatformService floatingRateReadPlatformService;
|
||||
private final RateReadService rateReadService;
|
||||
private final ConfigurationDomainService configurationDomainService;
|
||||
private final DelinquencyReadPlatformService delinquencyReadPlatformService;
|
||||
|
||||
@Autowired
|
||||
public LoanProductsApiResource(final PlatformSecurityContext context, final LoanProductReadPlatformService readPlatformService,
|
||||
@@ -145,7 +148,8 @@ public class LoanProductsApiResource {
|
||||
final DropdownReadPlatformService commonDropdownReadPlatformService,
|
||||
PaymentTypeReadPlatformService paymentTypeReadPlatformService,
|
||||
final FloatingRatesReadPlatformService floatingRateReadPlatformService, final RateReadService rateReadService,
|
||||
final ConfigurationDomainService configurationDomainService) {
|
||||
final ConfigurationDomainService configurationDomainService,
|
||||
final DelinquencyReadPlatformService delinquencyReadPlatformService) {
|
||||
this.context = context;
|
||||
this.loanProductReadPlatformService = readPlatformService;
|
||||
this.chargeReadPlatformService = chargeReadPlatformService;
|
||||
@@ -164,6 +168,7 @@ public class LoanProductsApiResource {
|
||||
this.floatingRateReadPlatformService = floatingRateReadPlatformService;
|
||||
this.rateReadService = rateReadService;
|
||||
this.configurationDomainService = configurationDomainService;
|
||||
this.delinquencyReadPlatformService = delinquencyReadPlatformService;
|
||||
}
|
||||
|
||||
@POST
|
||||
@@ -339,6 +344,12 @@ public class LoanProductsApiResource {
|
||||
if (fundOptions.isEmpty()) {
|
||||
fundOptions = null;
|
||||
}
|
||||
|
||||
Collection<DelinquencyBucketData> delinquencyBucketOptions = this.delinquencyReadPlatformService.retrieveAllDelinquencyBuckets();
|
||||
if (delinquencyBucketOptions.isEmpty()) {
|
||||
delinquencyBucketOptions = null;
|
||||
}
|
||||
|
||||
final Collection<TransactionProcessingStrategyData> transactionProcessingStrategyOptions = this.dropdownReadPlatformService
|
||||
.retreiveTransactionProcessingStrategies();
|
||||
|
||||
@@ -372,7 +383,7 @@ public class LoanProductsApiResource {
|
||||
loanCycleValueConditionTypeOptions, daysInMonthTypeOptions, daysInYearTypeOptions,
|
||||
interestRecalculationCompoundingTypeOptions, rescheduleStrategyTypeOptions, interestRecalculationFrequencyTypeOptions,
|
||||
preCloseInterestCalculationStrategyOptions, floatingRateOptions, interestRecalculationNthDayTypeOptions,
|
||||
interestRecalculationDayOfWeekTypeOptions, isRatesEnabled);
|
||||
interestRecalculationDayOfWeekTypeOptions, isRatesEnabled, delinquencyBucketOptions);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+31
-22
@@ -39,6 +39,7 @@ import org.apache.fineract.portfolio.common.domain.DaysInMonthType;
|
||||
import org.apache.fineract.portfolio.common.domain.DaysInYearType;
|
||||
import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
|
||||
import org.apache.fineract.portfolio.common.service.CommonEnumerations;
|
||||
import org.apache.fineract.portfolio.delinquency.data.DelinquencyBucketData;
|
||||
import org.apache.fineract.portfolio.floatingrates.data.FloatingRateData;
|
||||
import org.apache.fineract.portfolio.fund.data.FundData;
|
||||
import org.apache.fineract.portfolio.loanaccount.data.LoanInterestRecalculationData;
|
||||
@@ -51,6 +52,7 @@ import org.apache.fineract.portfolio.paymenttype.data.PaymentTypeData;
|
||||
import org.apache.fineract.portfolio.rate.data.RateData;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
/**
|
||||
* Immutable data object to represent loan products.
|
||||
*/
|
||||
@@ -140,9 +142,7 @@ public class LoanProductData implements Serializable {
|
||||
|
||||
// template related
|
||||
private final Collection<FundData> fundOptions;
|
||||
@SuppressWarnings("unused")
|
||||
private final Collection<PaymentTypeData> paymentTypeOptions;
|
||||
@SuppressWarnings("unused")
|
||||
private final Collection<CurrencyData> currencyOptions;
|
||||
private final List<EnumOptionData> repaymentFrequencyTypeOptions;
|
||||
private final List<EnumOptionData> interestRateFrequencyTypeOptions;
|
||||
@@ -152,32 +152,19 @@ public class LoanProductData implements Serializable {
|
||||
private final Collection<TransactionProcessingStrategyData> transactionProcessingStrategyOptions;
|
||||
private final Collection<ChargeData> chargeOptions;
|
||||
private final Collection<RateData> rateOptions;
|
||||
@SuppressWarnings("unused")
|
||||
private final Collection<ChargeData> penaltyOptions;
|
||||
@SuppressWarnings("unused")
|
||||
private final List<EnumOptionData> accountingRuleOptions;
|
||||
@SuppressWarnings("unused")
|
||||
private final Map<String, List<GLAccountData>> accountingMappingOptions;
|
||||
@SuppressWarnings("unused")
|
||||
private final List<EnumOptionData> valueConditionTypeOptions;
|
||||
@SuppressWarnings("unused")
|
||||
private final List<EnumOptionData> daysInMonthTypeOptions;
|
||||
@SuppressWarnings("unused")
|
||||
private final List<EnumOptionData> daysInYearTypeOptions;
|
||||
@SuppressWarnings("unused")
|
||||
private final List<EnumOptionData> interestRecalculationCompoundingTypeOptions;
|
||||
@SuppressWarnings("unused")
|
||||
private final List<EnumOptionData> interestRecalculationNthDayTypeOptions;
|
||||
@SuppressWarnings("unused")
|
||||
private final List<EnumOptionData> interestRecalculationDayOfWeekTypeOptions;
|
||||
@SuppressWarnings("unused")
|
||||
private final List<EnumOptionData> rescheduleStrategyTypeOptions;
|
||||
@SuppressWarnings("unused")
|
||||
private final List<EnumOptionData> preClosureInterestCalculationStrategyOptions;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private final List<EnumOptionData> interestRecalculationFrequencyTypeOptions;
|
||||
@SuppressWarnings("unused")
|
||||
private final List<FloatingRateData> floatingRateOptions;
|
||||
|
||||
private final Boolean multiDisburseLoan;
|
||||
@@ -198,6 +185,10 @@ public class LoanProductData implements Serializable {
|
||||
private final boolean isEqualAmortization;
|
||||
private final BigDecimal fixedPrincipalPercentagePerInstallment;
|
||||
|
||||
// Delinquency Buckets
|
||||
private final Collection<DelinquencyBucketData> delinquencyBucketOptions;
|
||||
private final DelinquencyBucketData delinquencyBucket;
|
||||
|
||||
/**
|
||||
* Used when returning lookup information about loan product for dropdowns.
|
||||
*/
|
||||
@@ -282,6 +273,9 @@ public class LoanProductData implements Serializable {
|
||||
final Collection<RateData> rateOptions = null;
|
||||
final Collection<RateData> rates = null;
|
||||
final boolean isRatesEnabled = false;
|
||||
final Collection<DelinquencyBucketData> delinquencyBucketOptions = null;
|
||||
final DelinquencyBucketData delinquencyBucket = null;
|
||||
|
||||
return new LoanProductData(id, name, shortName, description, currency, principal, minPrincipal, maxPrincipal, tolerance,
|
||||
numberOfRepayments, minNumberOfRepayments, maxNumberOfRepayments, repaymentEvery, interestRatePerPeriod,
|
||||
minInterestRatePerPeriod, maxInterestRatePerPeriod, annualInterestRate, repaymentFrequencyType, interestRateFrequencyType,
|
||||
@@ -298,7 +292,7 @@ public class LoanProductData implements Serializable {
|
||||
floatingRateName, interestRateDifferential, minDifferentialLendingRate, defaultDifferentialLendingRate,
|
||||
maxDifferentialLendingRate, isFloatingInterestRateCalculationAllowed, isVariableInstallmentsAllowed, minimumGap, maximumGap,
|
||||
syncExpectedWithDisbursementDate, canUseForTopup, isEqualAmortization, rateOptions, rates, isRatesEnabled,
|
||||
fixedPrincipalPercentagePerInstallment);
|
||||
fixedPrincipalPercentagePerInstallment, delinquencyBucketOptions, delinquencyBucket);
|
||||
|
||||
}
|
||||
|
||||
@@ -384,6 +378,8 @@ public class LoanProductData implements Serializable {
|
||||
final Collection<RateData> rateOptions = null;
|
||||
final Collection<RateData> rates = null;
|
||||
final boolean isRatesEnabled = false;
|
||||
final Collection<DelinquencyBucketData> delinquencyBucketOptions = null;
|
||||
final DelinquencyBucketData delinquencyBucket = null;
|
||||
|
||||
return new LoanProductData(id, name, shortName, description, currency, principal, minPrincipal, maxPrincipal, tolerance,
|
||||
numberOfRepayments, minNumberOfRepayments, maxNumberOfRepayments, repaymentEvery, interestRatePerPeriod,
|
||||
@@ -401,7 +397,7 @@ public class LoanProductData implements Serializable {
|
||||
floatingRateName, interestRateDifferential, minDifferentialLendingRate, defaultDifferentialLendingRate,
|
||||
maxDifferentialLendingRate, isFloatingInterestRateCalculationAllowed, isVariableInstallmentsAllowed, minimumGap, maximumGap,
|
||||
syncExpectedWithDisbursementDate, canUseForTopup, isEqualAmortization, rateOptions, rates, isRatesEnabled,
|
||||
fixedPrincipalPercentagePerInstallment);
|
||||
fixedPrincipalPercentagePerInstallment, delinquencyBucketOptions, delinquencyBucket);
|
||||
|
||||
}
|
||||
|
||||
@@ -494,6 +490,8 @@ public class LoanProductData implements Serializable {
|
||||
final Collection<RateData> rateOptions = null;
|
||||
final Collection<RateData> rates = null;
|
||||
final boolean isRatesEnabled = false;
|
||||
final Collection<DelinquencyBucketData> delinquencyBucketOptions = null;
|
||||
final DelinquencyBucketData delinquencyBucket = null;
|
||||
|
||||
return new LoanProductData(id, name, shortName, description, currency, principal, minPrincipal, maxPrincipal, tolerance,
|
||||
numberOfRepayments, minNumberOfRepayments, maxNumberOfRepayments, repaymentEvery, interestRatePerPeriod,
|
||||
@@ -511,7 +509,7 @@ public class LoanProductData implements Serializable {
|
||||
floatingRateName, interestRateDifferential, minDifferentialLendingRate, defaultDifferentialLendingRate,
|
||||
maxDifferentialLendingRate, isFloatingInterestRateCalculationAllowed, isVariableInstallmentsAllowed, minimumGap, maximumGap,
|
||||
syncExpectedWithDisbursementDate, canUseForTopup, isEqualAmortization, rateOptions, rates, isRatesEnabled,
|
||||
fixedPrincipalPercentagePerInstallment);
|
||||
fixedPrincipalPercentagePerInstallment, delinquencyBucketOptions, delinquencyBucket);
|
||||
|
||||
}
|
||||
|
||||
@@ -598,6 +596,8 @@ public class LoanProductData implements Serializable {
|
||||
final Collection<RateData> rateOptions = null;
|
||||
final Collection<RateData> rates = null;
|
||||
final boolean isRatesEnabled = false;
|
||||
final Collection<DelinquencyBucketData> delinquencyBucketOptions = null;
|
||||
final DelinquencyBucketData delinquencyBucket = null;
|
||||
|
||||
return new LoanProductData(id, name, shortName, description, currency, principal, minPrincipal, maxPrincipal, tolerance,
|
||||
numberOfRepayments, minNumberOfRepayments, maxNumberOfRepayments, repaymentEvery, interestRatePerPeriod,
|
||||
@@ -615,7 +615,7 @@ public class LoanProductData implements Serializable {
|
||||
floatingRateName, interestRateDifferential, minDifferentialLendingRate, defaultDifferentialLendingRate,
|
||||
maxDifferentialLendingRate, isFloatingInterestRateCalculationAllowed, isVariableInstallmentsAllowed, minimumGap, maximumGap,
|
||||
syncExpectedWithDisbursementDate, canUseForTopup, isEqualAmortization, rateOptions, rates, isRatesEnabled,
|
||||
fixedPrincipalPercentagePerInstallment);
|
||||
fixedPrincipalPercentagePerInstallment, delinquencyBucketOptions, delinquencyBucket);
|
||||
|
||||
}
|
||||
|
||||
@@ -660,7 +660,8 @@ public class LoanProductData implements Serializable {
|
||||
final Integer minimumGapBetweenInstallments, final Integer maximumGapBetweenInstallments,
|
||||
final boolean syncExpectedWithDisbursementDate, final boolean canUseForTopup, final boolean isEqualAmortization,
|
||||
Collection<RateData> rateOptions, Collection<RateData> rates, final boolean isRatesEnabled,
|
||||
final BigDecimal fixedPrincipalPercentagePerInstallment) {
|
||||
final BigDecimal fixedPrincipalPercentagePerInstallment, final Collection<DelinquencyBucketData> delinquencyBucketOptions,
|
||||
final DelinquencyBucketData delinquencyBucket) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.shortName = shortName;
|
||||
@@ -774,7 +775,8 @@ public class LoanProductData implements Serializable {
|
||||
this.syncExpectedWithDisbursementDate = syncExpectedWithDisbursementDate;
|
||||
this.canUseForTopup = canUseForTopup;
|
||||
this.isEqualAmortization = isEqualAmortization;
|
||||
|
||||
this.delinquencyBucketOptions = delinquencyBucketOptions;
|
||||
this.delinquencyBucket = delinquencyBucket;
|
||||
}
|
||||
|
||||
public LoanProductData(final LoanProductData productData, final Collection<ChargeData> chargeOptions,
|
||||
@@ -790,7 +792,8 @@ public class LoanProductData implements Serializable {
|
||||
final List<EnumOptionData> rescheduleStrategyTypeOptions, final List<EnumOptionData> interestRecalculationFrequencyTypeOptions,
|
||||
final List<EnumOptionData> preCloseInterestCalculationStrategyOptions, final List<FloatingRateData> floatingRateOptions,
|
||||
final List<EnumOptionData> interestRecalculationNthDayTypeOptions,
|
||||
final List<EnumOptionData> interestRecalculationDayOfWeekTypeOptions, final boolean isRatesEnabled) {
|
||||
final List<EnumOptionData> interestRecalculationDayOfWeekTypeOptions, final boolean isRatesEnabled,
|
||||
final Collection<DelinquencyBucketData> delinquencyBucketOptions) {
|
||||
this.id = productData.id;
|
||||
this.name = productData.name;
|
||||
this.shortName = productData.shortName;
|
||||
@@ -921,6 +924,8 @@ public class LoanProductData implements Serializable {
|
||||
this.isEqualAmortization = productData.isEqualAmortization;
|
||||
this.rates = productData.rates;
|
||||
this.isRatesEnabled = isRatesEnabled;
|
||||
this.delinquencyBucketOptions = delinquencyBucketOptions;
|
||||
this.delinquencyBucket = productData.delinquencyBucket;
|
||||
}
|
||||
|
||||
private Collection<ChargeData> nullIfEmpty(final Collection<ChargeData> charges) {
|
||||
@@ -1051,6 +1056,10 @@ public class LoanProductData implements Serializable {
|
||||
return this.fundOptions;
|
||||
}
|
||||
|
||||
public Collection<DelinquencyBucketData> getDelinquencyBucketOptions() {
|
||||
return delinquencyBucketOptions;
|
||||
}
|
||||
|
||||
public List<EnumOptionData> getAmortizationTypeOptions() {
|
||||
return this.amortizationTypeOptions;
|
||||
}
|
||||
|
||||
+22
@@ -54,6 +54,7 @@ import org.apache.fineract.portfolio.charge.domain.Charge;
|
||||
import org.apache.fineract.portfolio.common.domain.DaysInMonthType;
|
||||
import org.apache.fineract.portfolio.common.domain.DaysInYearType;
|
||||
import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
|
||||
import org.apache.fineract.portfolio.delinquency.domain.DelinquencyBucket;
|
||||
import org.apache.fineract.portfolio.floatingrates.data.FloatingRateDTO;
|
||||
import org.apache.fineract.portfolio.floatingrates.data.FloatingRatePeriodData;
|
||||
import org.apache.fineract.portfolio.floatingrates.domain.FloatingRate;
|
||||
@@ -195,6 +196,10 @@ public class LoanProduct extends AbstractPersistableCustom {
|
||||
@Column(name = "over_applied_number", nullable = true)
|
||||
private Integer overAppliedNumber;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "delinquency_bucket_id", nullable = true)
|
||||
private DelinquencyBucket delinquencyBucket;
|
||||
|
||||
public static LoanProduct assembleFromJson(final Fund fund, final LoanTransactionProcessingStrategy loanTransactionProcessingStrategy,
|
||||
final List<Charge> productCharges, final JsonCommand command, final AprCalculator aprCalculator, FloatingRate floatingRate,
|
||||
final List<Rate> productRates) {
|
||||
@@ -1001,6 +1006,15 @@ public class LoanProduct extends AbstractPersistableCustom {
|
||||
this.syncExpectedWithDisbursementDate = newValue;
|
||||
}
|
||||
|
||||
Long delinquencyBucketId = null;
|
||||
if (this.delinquencyBucket != null) {
|
||||
delinquencyBucketId = this.delinquencyBucket.getId();
|
||||
}
|
||||
if (command.isChangeInLongParameterNamed(LoanProductConstants.DELINQUENCY_BUCKET_PARAM_NAME, delinquencyBucketId)) {
|
||||
final Long newValue = command.longValueOfParameterNamed(LoanProductConstants.DELINQUENCY_BUCKET_PARAM_NAME);
|
||||
actualChanges.put(LoanProductConstants.DELINQUENCY_BUCKET_PARAM_NAME, newValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update interest recalculation settings
|
||||
*/
|
||||
@@ -1578,4 +1592,12 @@ public class LoanProduct extends AbstractPersistableCustom {
|
||||
this.loanProducTrancheDetails = loanProducTrancheDetails;
|
||||
}
|
||||
|
||||
public DelinquencyBucket getDelinquencyBucket() {
|
||||
return delinquencyBucket;
|
||||
}
|
||||
|
||||
public void setDelinquencyBucket(DelinquencyBucket delinquencyBucket) {
|
||||
this.delinquencyBucket = delinquencyBucket;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+3
@@ -19,6 +19,7 @@
|
||||
package org.apache.fineract.portfolio.loanproduct.domain;
|
||||
|
||||
import java.util.List;
|
||||
import org.apache.fineract.portfolio.delinquency.domain.DelinquencyBucket;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
@@ -28,4 +29,6 @@ public interface LoanProductRepository extends JpaRepository<LoanProduct, Long>,
|
||||
|
||||
@Query("select loanProduct from LoanProduct loanProduct, IN(loanProduct.charges) charge where charge.id = :chargeId")
|
||||
List<LoanProduct> retrieveLoanProductsByChargeId(@Param("chargeId") Long chargeId);
|
||||
|
||||
Long countByDelinquencyBucket(DelinquencyBucket delinquencyBucket);
|
||||
}
|
||||
|
||||
+15
-1
@@ -111,7 +111,7 @@ public final class LoanProductDataValidator {
|
||||
LoanProductConstants.CAN_USE_FOR_TOPUP, LoanProductConstants.IS_EQUAL_AMORTIZATION_PARAM, LoanProductConstants.RATES_PARAM_NAME,
|
||||
LoanProductConstants.fixedPrincipalPercentagePerInstallmentParamName, LoanProductConstants.DISALLOW_EXPECTED_DISBURSEMENTS,
|
||||
LoanProductConstants.ALLOW_APPROVED_DISBURSED_AMOUNTS_OVER_APPLIED, LoanProductConstants.OVER_APPLIED_CALCULATION_TYPE,
|
||||
LoanProductConstants.OVER_APPLIED_NUMBER));
|
||||
LoanProductConstants.OVER_APPLIED_NUMBER, LoanProductConstants.DELINQUENCY_BUCKET_PARAM_NAME));
|
||||
|
||||
private static final String[] supportedloanConfigurableAttributes = { LoanProductConstants.amortizationTypeParamName,
|
||||
LoanProductConstants.interestTypeParamName, LoanProductConstants.transactionProcessingStrategyIdParamName,
|
||||
@@ -274,6 +274,13 @@ public final class LoanProductDataValidator {
|
||||
baseDataValidator.reset().parameter("transactionProcessingStrategyId").value(transactionProcessingStrategyId).notNull()
|
||||
.integerGreaterThanZero();
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(LoanProductConstants.DELINQUENCY_BUCKET_PARAM_NAME, element)) {
|
||||
final Long delinquencyBucketId = this.fromApiJsonHelper.extractLongNamed(LoanProductConstants.DELINQUENCY_BUCKET_PARAM_NAME,
|
||||
element);
|
||||
baseDataValidator.reset().parameter(LoanProductConstants.DELINQUENCY_BUCKET_PARAM_NAME).value(delinquencyBucketId)
|
||||
.ignoreIfNull().integerGreaterThanZero();
|
||||
}
|
||||
|
||||
// grace validation
|
||||
final Integer graceOnPrincipalPayment = this.fromApiJsonHelper.extractIntegerWithLocaleNamed("graceOnPrincipalPayment", element);
|
||||
baseDataValidator.reset().parameter("graceOnPrincipalPayment").value(graceOnPrincipalPayment).zeroOrPositiveAmount();
|
||||
@@ -1087,6 +1094,13 @@ public final class LoanProductDataValidator {
|
||||
.integerZeroOrGreater();
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(LoanProductConstants.DELINQUENCY_BUCKET_PARAM_NAME, element)) {
|
||||
final Long delinquencyBucketId = this.fromApiJsonHelper.extractLongNamed(LoanProductConstants.DELINQUENCY_BUCKET_PARAM_NAME,
|
||||
element);
|
||||
baseDataValidator.reset().parameter(LoanProductConstants.DELINQUENCY_BUCKET_PARAM_NAME).value(delinquencyBucketId)
|
||||
.ignoreIfNull().integerGreaterThanZero();
|
||||
}
|
||||
|
||||
Integer amortizationType = null;
|
||||
if (this.fromApiJsonHelper.parameterExists("amortizationType", element)) {
|
||||
amortizationType = this.fromApiJsonHelper.extractIntegerNamed("amortizationType", element, Locale.getDefault());
|
||||
|
||||
+24
-7
@@ -36,6 +36,8 @@ import org.apache.fineract.organisation.monetary.data.CurrencyData;
|
||||
import org.apache.fineract.portfolio.charge.data.ChargeData;
|
||||
import org.apache.fineract.portfolio.charge.service.ChargeReadPlatformService;
|
||||
import org.apache.fineract.portfolio.common.service.CommonEnumerations;
|
||||
import org.apache.fineract.portfolio.delinquency.data.DelinquencyBucketData;
|
||||
import org.apache.fineract.portfolio.delinquency.service.DelinquencyReadPlatformService;
|
||||
import org.apache.fineract.portfolio.loanproduct.data.LoanProductBorrowerCycleVariationData;
|
||||
import org.apache.fineract.portfolio.loanproduct.data.LoanProductData;
|
||||
import org.apache.fineract.portfolio.loanproduct.data.LoanProductGuaranteeData;
|
||||
@@ -60,18 +62,20 @@ public class LoanProductReadPlatformServiceImpl implements LoanProductReadPlatfo
|
||||
private final RateReadService rateReadService;
|
||||
private final DatabaseSpecificSQLGenerator sqlGenerator;
|
||||
private final FineractEntityAccessUtil fineractEntityAccessUtil;
|
||||
private final DelinquencyReadPlatformService delinquencyReadPlatformService;
|
||||
|
||||
@Autowired
|
||||
public LoanProductReadPlatformServiceImpl(final PlatformSecurityContext context,
|
||||
final ChargeReadPlatformService chargeReadPlatformService, final JdbcTemplate jdbcTemplate,
|
||||
final FineractEntityAccessUtil fineractEntityAccessUtil, final RateReadService rateReadService,
|
||||
DatabaseSpecificSQLGenerator sqlGenerator) {
|
||||
final DelinquencyReadPlatformService delinquencyReadPlatformService, final DatabaseSpecificSQLGenerator sqlGenerator) {
|
||||
this.context = context;
|
||||
this.chargeReadPlatformService = chargeReadPlatformService;
|
||||
this.jdbcTemplate = jdbcTemplate;
|
||||
this.fineractEntityAccessUtil = fineractEntityAccessUtil;
|
||||
this.rateReadService = rateReadService;
|
||||
this.sqlGenerator = sqlGenerator;
|
||||
this.delinquencyReadPlatformService = delinquencyReadPlatformService;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -82,7 +86,9 @@ public class LoanProductReadPlatformServiceImpl implements LoanProductReadPlatfo
|
||||
final Collection<RateData> rates = this.rateReadService.retrieveProductLoanRates(loanProductId);
|
||||
final Collection<LoanProductBorrowerCycleVariationData> borrowerCycleVariationDatas = retrieveLoanProductBorrowerCycleVariations(
|
||||
loanProductId);
|
||||
final LoanProductMapper rm = new LoanProductMapper(charges, borrowerCycleVariationDatas, rates);
|
||||
final Collection<DelinquencyBucketData> delinquencyBucketOptions = this.delinquencyReadPlatformService
|
||||
.retrieveAllDelinquencyBuckets();
|
||||
final LoanProductMapper rm = new LoanProductMapper(charges, borrowerCycleVariationDatas, rates, delinquencyBucketOptions);
|
||||
final String sql = "select " + rm.loanProductSchema() + " where lp.id = ?";
|
||||
|
||||
return this.jdbcTemplate.queryForObject(sql, rm, new Object[] { loanProductId }); // NOSONAR
|
||||
@@ -104,7 +110,7 @@ public class LoanProductReadPlatformServiceImpl implements LoanProductReadPlatfo
|
||||
|
||||
this.context.authenticatedUser();
|
||||
|
||||
final LoanProductMapper rm = new LoanProductMapper(null, null, null);
|
||||
final LoanProductMapper rm = new LoanProductMapper(null, null, null, null);
|
||||
|
||||
String sql = "select " + rm.loanProductSchema();
|
||||
|
||||
@@ -183,11 +189,15 @@ public class LoanProductReadPlatformServiceImpl implements LoanProductReadPlatfo
|
||||
|
||||
private final Collection<RateData> rates;
|
||||
|
||||
private final Collection<DelinquencyBucketData> delinquencyBucketOptions;
|
||||
|
||||
LoanProductMapper(final Collection<ChargeData> charges,
|
||||
final Collection<LoanProductBorrowerCycleVariationData> borrowerCycleVariationDatas, final Collection<RateData> rates) {
|
||||
final Collection<LoanProductBorrowerCycleVariationData> borrowerCycleVariationDatas, final Collection<RateData> rates,
|
||||
final Collection<DelinquencyBucketData> delinquencyBucketOptions) {
|
||||
this.charges = charges;
|
||||
this.borrowerCycleVariationDatas = borrowerCycleVariationDatas;
|
||||
this.rates = rates;
|
||||
this.delinquencyBucketOptions = delinquencyBucketOptions;
|
||||
}
|
||||
|
||||
public String loanProductSchema() {
|
||||
@@ -235,7 +245,7 @@ public class LoanProductReadPlatformServiceImpl implements LoanProductReadPlatfo
|
||||
+ "lfr.max_differential_lending_rate as maxDifferentialLendingRate, "
|
||||
+ "lfr.is_floating_interest_rate_calculation_allowed as isFloatingInterestRateCalculationAllowed, "
|
||||
+ "lp.allow_variabe_installments as isVariableIntallmentsAllowed, " + "lvi.minimum_gap as minimumGap, "
|
||||
+ "lvi.maximum_gap as maximumGap, "
|
||||
+ "lvi.maximum_gap as maximumGap, dbuc.id as delinquencyBucketId, dbuc.name as delinquencyBucketName, "
|
||||
+ "lp.can_use_for_topup as canUseForTopup, lp.is_equal_amortization as isEqualAmortization "
|
||||
+ " from m_product_loan lp " + " left join m_fund f on f.id = lp.fund_id "
|
||||
+ " left join m_product_loan_recalculation_details lpr on lpr.product_id=lp.id "
|
||||
@@ -245,6 +255,7 @@ public class LoanProductReadPlatformServiceImpl implements LoanProductReadPlatfo
|
||||
+ " left join m_product_loan_floating_rates as lfr on lfr.loan_product_id = lp.id "
|
||||
+ " left join m_floating_rates as fr on lfr.floating_rates_id = fr.id "
|
||||
+ " left join m_product_loan_variable_installment_config as lvi on lvi.loan_product_id = lp.id "
|
||||
+ " left join m_delinquency_bucket as dbuc on dbuc.id = lp.delinquency_bucket_id "
|
||||
+ " join m_currency curr on curr.code = lp.currency_code";
|
||||
|
||||
}
|
||||
@@ -465,6 +476,12 @@ public class LoanProductReadPlatformServiceImpl implements LoanProductReadPlatfo
|
||||
final Collection<RateData> rateOptions = null;
|
||||
final boolean isRatesEnabled = false;
|
||||
|
||||
// Delinquency Buckets
|
||||
final Long delinquencyBucketId = rs.getLong("delinquencyBucketId");
|
||||
final String delinquencyBucketName = rs.getString("delinquencyBucketName");
|
||||
final DelinquencyBucketData delinquencyBucket = new DelinquencyBucketData(delinquencyBucketId, delinquencyBucketName,
|
||||
new ArrayList<>());
|
||||
|
||||
return new LoanProductData(id, name, shortName, description, currency, principal, minPrincipal, maxPrincipal, tolerance,
|
||||
numberOfRepayments, minNumberOfRepayments, maxNumberOfRepayments, repaymentEvery, interestRatePerPeriod,
|
||||
minInterestRatePerPeriod, maxInterestRatePerPeriod, annualInterestRate, repaymentFrequencyType,
|
||||
@@ -482,7 +499,7 @@ public class LoanProductReadPlatformServiceImpl implements LoanProductReadPlatfo
|
||||
floatingRateName, interestRateDifferential, minDifferentialLendingRate, defaultDifferentialLendingRate,
|
||||
maxDifferentialLendingRate, isFloatingInterestRateCalculationAllowed, isVariableIntallmentsAllowed, minimumGap,
|
||||
maximumGap, syncExpectedWithDisbursementDate, canUseForTopup, isEqualAmortization, rateOptions, this.rates,
|
||||
isRatesEnabled, fixedPrincipalPercentagePerInstallment);
|
||||
isRatesEnabled, fixedPrincipalPercentagePerInstallment, delinquencyBucketOptions, delinquencyBucket);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -558,7 +575,7 @@ public class LoanProductReadPlatformServiceImpl implements LoanProductReadPlatfo
|
||||
public Collection<LoanProductData> retrieveAllLoanProductsForCurrency(String currencyCode) {
|
||||
this.context.authenticatedUser();
|
||||
|
||||
final LoanProductMapper rm = new LoanProductMapper(null, null, null);
|
||||
final LoanProductMapper rm = new LoanProductMapper(null, null, null, null);
|
||||
|
||||
String sql = "select " + rm.loanProductSchema() + " where lp.currency_code= ? ";
|
||||
|
||||
|
||||
+12
-1
@@ -38,6 +38,8 @@ import org.apache.fineract.portfolio.businessevent.domain.loan.product.LoanProdu
|
||||
import org.apache.fineract.portfolio.businessevent.service.BusinessEventNotifierService;
|
||||
import org.apache.fineract.portfolio.charge.domain.Charge;
|
||||
import org.apache.fineract.portfolio.charge.domain.ChargeRepositoryWrapper;
|
||||
import org.apache.fineract.portfolio.delinquency.domain.DelinquencyBucket;
|
||||
import org.apache.fineract.portfolio.delinquency.domain.DelinquencyBucketRepository;
|
||||
import org.apache.fineract.portfolio.floatingrates.domain.FloatingRate;
|
||||
import org.apache.fineract.portfolio.floatingrates.domain.FloatingRateRepositoryWrapper;
|
||||
import org.apache.fineract.portfolio.fund.domain.Fund;
|
||||
@@ -83,6 +85,7 @@ public class LoanProductWritePlatformServiceJpaRepositoryImpl implements LoanPro
|
||||
private final FloatingRateRepositoryWrapper floatingRateRepository;
|
||||
private final LoanRepositoryWrapper loanRepositoryWrapper;
|
||||
private final BusinessEventNotifierService businessEventNotifierService;
|
||||
private final DelinquencyBucketRepository delinquencyBucketRepository;
|
||||
|
||||
@Autowired
|
||||
public LoanProductWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context,
|
||||
@@ -92,7 +95,8 @@ public class LoanProductWritePlatformServiceJpaRepositoryImpl implements LoanPro
|
||||
final ChargeRepositoryWrapper chargeRepository, final RateRepositoryWrapper rateRepository,
|
||||
final ProductToGLAccountMappingWritePlatformService accountMappingWritePlatformService,
|
||||
final FineractEntityAccessUtil fineractEntityAccessUtil, final FloatingRateRepositoryWrapper floatingRateRepository,
|
||||
final LoanRepositoryWrapper loanRepositoryWrapper, final BusinessEventNotifierService businessEventNotifierService) {
|
||||
final LoanRepositoryWrapper loanRepositoryWrapper, final BusinessEventNotifierService businessEventNotifierService,
|
||||
final DelinquencyBucketRepository delinquencyBucketRepository) {
|
||||
this.context = context;
|
||||
this.fromApiJsonDeserializer = fromApiJsonDeserializer;
|
||||
this.loanProductRepository = loanProductRepository;
|
||||
@@ -106,6 +110,7 @@ public class LoanProductWritePlatformServiceJpaRepositoryImpl implements LoanPro
|
||||
this.floatingRateRepository = floatingRateRepository;
|
||||
this.loanRepositoryWrapper = loanRepositoryWrapper;
|
||||
this.businessEventNotifierService = businessEventNotifierService;
|
||||
this.delinquencyBucketRepository = delinquencyBucketRepository;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@@ -215,6 +220,12 @@ public class LoanProductWritePlatformServiceJpaRepositoryImpl implements LoanPro
|
||||
product.update(fund);
|
||||
}
|
||||
|
||||
if (changes.containsKey("delinquencyBucketId")) {
|
||||
final Long delinquencyBucketId = (Long) changes.get("delinquencyBucketId");
|
||||
final DelinquencyBucket delinquencyBucket = this.delinquencyBucketRepository.getReferenceById(delinquencyBucketId);
|
||||
product.setDelinquencyBucket(delinquencyBucket);
|
||||
}
|
||||
|
||||
if (changes.containsKey("transactionProcessingStrategyId")) {
|
||||
final Long transactionProcessingStrategyId = (Long) changes.get("transactionProcessingStrategyId");
|
||||
final LoanTransactionProcessingStrategy loanTransactionProcessingStrategy = findStrategyByIdIfProvided(
|
||||
|
||||
+1
-1
@@ -72,7 +72,7 @@ public class GenerateAdhocClientScheduleTasklet implements Tasklet {
|
||||
run = Math.toIntExact(ChronoUnit.YEARS.between(start, end)) >= 1;
|
||||
}
|
||||
case CUSTOM -> {
|
||||
next = start.plusDays((int) (long) adhoc.getReportRunEvery());
|
||||
next = start.plusDays((long) adhoc.getReportRunEvery());
|
||||
run = Math.toIntExact(ChronoUnit.DAYS.between(start, end)) >= adhoc.getReportRunEvery();
|
||||
}
|
||||
}
|
||||
|
||||
+4
@@ -560,6 +560,10 @@ public class AppUser extends AbstractPersistableCustom implements PlatformUser {
|
||||
validateHasPermission("UPDATE", resourceType);
|
||||
}
|
||||
|
||||
public void validateHasDeletePermission(final String resourceType) {
|
||||
validateHasPermission("DELETE", resourceType);
|
||||
}
|
||||
|
||||
private void validateHasPermission(final String prefix, final String resourceType) {
|
||||
final String authorizationMessage = "User has no authority to " + prefix + " " + resourceType.toLowerCase() + "s";
|
||||
final String matchPermission = prefix + "_" + resourceType.toUpperCase();
|
||||
|
||||
@@ -48,4 +48,5 @@
|
||||
<include file="parts/0026_reversals_for_reversed_transactions.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0027_add_charge_refund_permission.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0028_add_charge_refund_charge_type_to_loan_transaction.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0029_add_delinquency_buckets.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
|
||||
+325
@@ -0,0 +1,325 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
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.
|
||||
|
||||
-->
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.1.xsd">
|
||||
<changeSet author="fineract" id="1" context="mysql">
|
||||
<createTable tableName="m_delinquency_range">
|
||||
<column autoIncrement="true" name="id" type="BIGINT">
|
||||
<constraints nullable="false" primaryKey="true"/>
|
||||
</column>
|
||||
<column name="classification" type="VARCHAR(100)">
|
||||
<constraints unique="true" nullable="false"/>
|
||||
</column>
|
||||
<column name="min_age_days" type="BIGINT">
|
||||
<constraints nullable="false" />
|
||||
</column>
|
||||
<column name="max_age_days" type="BIGINT">
|
||||
<constraints nullable="true" />
|
||||
</column>
|
||||
<column name="created_by" type="BIGINT">
|
||||
<constraints nullable="false" />
|
||||
</column>
|
||||
<column name="created_on_utc" type="DATETIME">
|
||||
<constraints nullable="false" />
|
||||
</column>
|
||||
<column name="version" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="last_modified_by" type="BIGINT">
|
||||
<constraints nullable="false" />
|
||||
</column>
|
||||
<column name="last_modified_on_utc" type="DATETIME">
|
||||
<constraints nullable="false" />
|
||||
</column>
|
||||
</createTable>
|
||||
<createTable tableName="m_delinquency_bucket">
|
||||
<column autoIncrement="true" name="id" type="BIGINT">
|
||||
<constraints nullable="false" primaryKey="true"/>
|
||||
</column>
|
||||
<column name="name" type="VARCHAR(100)">
|
||||
<constraints unique="true" nullable="false"/>
|
||||
</column>
|
||||
<column name="created_by" type="BIGINT">
|
||||
<constraints nullable="false" />
|
||||
</column>
|
||||
<column name="created_on_utc" type="DATETIME">
|
||||
<constraints nullable="false" />
|
||||
</column>
|
||||
<column name="version" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="last_modified_by" type="BIGINT">
|
||||
<constraints nullable="false" />
|
||||
</column>
|
||||
<column name="last_modified_on_utc" type="DATETIME">
|
||||
<constraints nullable="false" />
|
||||
</column>
|
||||
</createTable>
|
||||
<createTable tableName="m_delinquency_bucket_mappings">
|
||||
<column autoIncrement="true" name="id" type="BIGINT">
|
||||
<constraints nullable="false" primaryKey="true"/>
|
||||
</column>
|
||||
<column name="delinquency_range_id" type="BIGINT">
|
||||
<constraints nullable="false" />
|
||||
</column>
|
||||
<column name="delinquency_bucket_id" type="BIGINT">
|
||||
<constraints nullable="false" />
|
||||
</column>
|
||||
<column name="created_by" type="BIGINT">
|
||||
<constraints nullable="false" />
|
||||
</column>
|
||||
<column name="created_on_utc" type="DATETIME">
|
||||
<constraints nullable="false" />
|
||||
</column>
|
||||
<column name="version" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="last_modified_by" type="BIGINT">
|
||||
<constraints nullable="false" />
|
||||
</column>
|
||||
<column name="last_modified_on_utc" type="DATETIME">
|
||||
<constraints nullable="false" />
|
||||
</column>
|
||||
</createTable>
|
||||
<createTable tableName="m_loan_delinquency_tag_history">
|
||||
<column autoIncrement="true" name="id" type="BIGINT">
|
||||
<constraints nullable="false" primaryKey="true"/>
|
||||
</column>
|
||||
<column name="delinquency_range_id" type="BIGINT">
|
||||
<constraints nullable="false" />
|
||||
</column>
|
||||
<column name="loan_id" type="BIGINT">
|
||||
<constraints nullable="false" />
|
||||
</column>
|
||||
<column name="addedon_date" type="DATE">
|
||||
<constraints nullable="false" />
|
||||
</column>
|
||||
<column defaultValueComputed="NULL" name="liftedon_date" type="DATE" />
|
||||
<column name="created_by" type="BIGINT">
|
||||
<constraints nullable="false" />
|
||||
</column>
|
||||
<column name="created_on_utc" type="DATETIME">
|
||||
<constraints nullable="false" />
|
||||
</column>
|
||||
<column name="version" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="last_modified_by" type="BIGINT">
|
||||
<constraints nullable="false" />
|
||||
</column>
|
||||
<column name="last_modified_on_utc" type="DATETIME">
|
||||
<constraints nullable="false" />
|
||||
</column>
|
||||
</createTable>
|
||||
</changeSet>
|
||||
<changeSet author="fineract" id="1" context="postgresql">
|
||||
<createTable tableName="m_delinquency_range">
|
||||
<column autoIncrement="true" name="id" type="BIGINT">
|
||||
<constraints nullable="false" primaryKey="true"/>
|
||||
</column>
|
||||
<column name="classification" type="VARCHAR(100)">
|
||||
<constraints unique="true" nullable="false"/>
|
||||
</column>
|
||||
<column name="min_age_days" type="BIGINT">
|
||||
<constraints nullable="false" />
|
||||
</column>
|
||||
<column name="max_age_days" type="BIGINT">
|
||||
<constraints nullable="true" />
|
||||
</column>
|
||||
<column name="created_by" type="BIGINT">
|
||||
<constraints nullable="false" />
|
||||
</column>
|
||||
<column name="created_on_utc" type="TIMESTAMP WITH TIME ZONE">
|
||||
<constraints nullable="false" />
|
||||
</column>
|
||||
<column name="version" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="last_modified_by" type="BIGINT">
|
||||
<constraints nullable="false" />
|
||||
</column>
|
||||
<column name="last_modified_on_utc" type="TIMESTAMP WITH TIME ZONE">
|
||||
<constraints nullable="false" />
|
||||
</column>
|
||||
</createTable>
|
||||
<createTable tableName="m_delinquency_bucket">
|
||||
<column autoIncrement="true" name="id" type="BIGINT">
|
||||
<constraints nullable="false" primaryKey="true"/>
|
||||
</column>
|
||||
<column name="name" type="VARCHAR(100)">
|
||||
<constraints unique="true" nullable="false"/>
|
||||
</column>
|
||||
<column name="created_by" type="BIGINT">
|
||||
<constraints nullable="false" />
|
||||
</column>
|
||||
<column name="created_on_utc" type="TIMESTAMP WITH TIME ZONE">
|
||||
<constraints nullable="false" />
|
||||
</column>
|
||||
<column name="version" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="last_modified_by" type="BIGINT">
|
||||
<constraints nullable="false" />
|
||||
</column>
|
||||
<column name="last_modified_on_utc" type="TIMESTAMP WITH TIME ZONE">
|
||||
<constraints nullable="false" />
|
||||
</column>
|
||||
</createTable>
|
||||
<createTable tableName="m_delinquency_bucket_mappings">
|
||||
<column autoIncrement="true" name="id" type="BIGINT">
|
||||
<constraints nullable="false" primaryKey="true"/>
|
||||
</column>
|
||||
<column name="delinquency_range_id" type="BIGINT">
|
||||
<constraints nullable="false" />
|
||||
</column>
|
||||
<column name="delinquency_bucket_id" type="BIGINT">
|
||||
<constraints nullable="false" />
|
||||
</column>
|
||||
<column name="created_by" type="BIGINT">
|
||||
<constraints nullable="false" />
|
||||
</column>
|
||||
<column name="created_on_utc" type="TIMESTAMP WITH TIME ZONE">
|
||||
<constraints nullable="false" />
|
||||
</column>
|
||||
<column name="version" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="last_modified_by" type="BIGINT">
|
||||
<constraints nullable="false" />
|
||||
</column>
|
||||
<column name="last_modified_on_utc" type="TIMESTAMP WITH TIME ZONE">
|
||||
<constraints nullable="false" />
|
||||
</column>
|
||||
</createTable>
|
||||
<createTable tableName="m_loan_delinquency_tag_history">
|
||||
<column autoIncrement="true" name="id" type="BIGINT">
|
||||
<constraints nullable="false" primaryKey="true"/>
|
||||
</column>
|
||||
<column name="delinquency_range_id" type="BIGINT">
|
||||
<constraints nullable="false" />
|
||||
</column>
|
||||
<column name="loan_id" type="BIGINT">
|
||||
<constraints nullable="false" />
|
||||
</column>
|
||||
<column name="addedon_date" type="DATE">
|
||||
<constraints nullable="false" />
|
||||
</column>
|
||||
<column defaultValueComputed="NULL" name="liftedon_date" type="DATE" />
|
||||
<column name="created_by" type="BIGINT">
|
||||
<constraints nullable="false" />
|
||||
</column>
|
||||
<column name="created_on_utc" type="TIMESTAMP WITH TIME ZONE">
|
||||
<constraints nullable="false" />
|
||||
</column>
|
||||
<column name="version" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="last_modified_by" type="BIGINT">
|
||||
<constraints nullable="false" />
|
||||
</column>
|
||||
<column name="last_modified_on_utc" type="TIMESTAMP WITH TIME ZONE">
|
||||
<constraints nullable="false" />
|
||||
</column>
|
||||
</createTable>
|
||||
</changeSet>
|
||||
<changeSet author="fineract" id="2">
|
||||
<addForeignKeyConstraint baseColumnNames="delinquency_range_id" baseTableName="m_delinquency_bucket_mappings"
|
||||
constraintName="FK_m_delinquency_range_mapping" deferrable="false"
|
||||
initiallyDeferred="false" onDelete="RESTRICT" onUpdate="RESTRICT"
|
||||
referencedColumnNames="id" referencedTableName="m_delinquency_range" validate="true"/>
|
||||
<addForeignKeyConstraint baseColumnNames="delinquency_bucket_id" baseTableName="m_delinquency_bucket_mappings"
|
||||
constraintName="FK_m_delinquency_bucket_mapping" deferrable="false"
|
||||
initiallyDeferred="false" onDelete="RESTRICT" onUpdate="RESTRICT"
|
||||
referencedColumnNames="id" referencedTableName="m_delinquency_bucket" validate="true"/>
|
||||
</changeSet>
|
||||
<changeSet author="fineract" id="3">
|
||||
<addColumn tableName="m_product_loan">
|
||||
<column name="delinquency_bucket_id" type="BIGINT" defaultValueComputed="NULL"/>
|
||||
</addColumn>
|
||||
<addForeignKeyConstraint baseColumnNames="delinquency_bucket_id" baseTableName="m_product_loan"
|
||||
constraintName="FK_m_product_loan_m_delinquency_bucket" deferrable="false"
|
||||
initiallyDeferred="false" onDelete="RESTRICT" onUpdate="RESTRICT"
|
||||
referencedColumnNames="id" referencedTableName="m_delinquency_bucket" validate="true"/>
|
||||
</changeSet>
|
||||
<changeSet author="fineract" id="4">
|
||||
<addForeignKeyConstraint baseColumnNames="delinquency_range_id" baseTableName="m_loan_delinquency_tag_history"
|
||||
constraintName="FK_m_delinquency_tags_range" deferrable="false"
|
||||
initiallyDeferred="false" onDelete="RESTRICT" onUpdate="RESTRICT"
|
||||
referencedColumnNames="id" referencedTableName="m_delinquency_range" validate="true"/>
|
||||
<addForeignKeyConstraint baseColumnNames="loan_id" baseTableName="m_loan_delinquency_tag_history"
|
||||
constraintName="FK_m_delinquency_tags_loan" deferrable="false"
|
||||
initiallyDeferred="false" onDelete="RESTRICT" onUpdate="RESTRICT"
|
||||
referencedColumnNames="id" referencedTableName="m_loan" validate="true"/>
|
||||
</changeSet>
|
||||
<changeSet author="fineract" id="5">
|
||||
<insert tableName="m_permission">
|
||||
<column name="grouping" value="organisation"/>
|
||||
<column name="code" value="READ_DELINQUENCY_BUCKET"/>
|
||||
<column name="entity_name" value="DELINQUENCY_BUCKET"/>
|
||||
<column name="action_name" value="READ"/>
|
||||
<column name="can_maker_checker" valueBoolean="false"/>
|
||||
</insert>
|
||||
<insert tableName="m_permission">
|
||||
<column name="grouping" value="organisation"/>
|
||||
<column name="code" value="CREATE_DELINQUENCY_BUCKET"/>
|
||||
<column name="entity_name" value="DELINQUENCY_BUCKET"/>
|
||||
<column name="action_name" value="CREATE"/>
|
||||
<column name="can_maker_checker" valueBoolean="false"/>
|
||||
</insert>
|
||||
<insert tableName="m_permission">
|
||||
<column name="grouping" value="organisation"/>
|
||||
<column name="code" value="UPDATE_DELINQUENCY_BUCKET"/>
|
||||
<column name="entity_name" value="DELINQUENCY_BUCKET"/>
|
||||
<column name="action_name" value="UPDATE"/>
|
||||
<column name="can_maker_checker" valueBoolean="false"/>
|
||||
</insert>
|
||||
<insert tableName="m_permission">
|
||||
<column name="grouping" value="organisation"/>
|
||||
<column name="code" value="DELETE_DELINQUENCY_BUCKET"/>
|
||||
<column name="entity_name" value="DELINQUENCY_BUCKET"/>
|
||||
<column name="action_name" value="DELETE"/>
|
||||
<column name="can_maker_checker" valueBoolean="false"/>
|
||||
</insert>
|
||||
<insert tableName="m_permission">
|
||||
<column name="grouping" value="organisation"/>
|
||||
<column name="code" value="CREATE_DELINQUENCY_RANGE"/>
|
||||
<column name="entity_name" value="DELINQUENCY_RANGE"/>
|
||||
<column name="action_name" value="CREATE"/>
|
||||
<column name="can_maker_checker" valueBoolean="false"/>
|
||||
</insert>
|
||||
<insert tableName="m_permission">
|
||||
<column name="grouping" value="organisation"/>
|
||||
<column name="code" value="UPDATE_DELINQUENCY_RANGE"/>
|
||||
<column name="entity_name" value="DELINQUENCY_RANGE"/>
|
||||
<column name="action_name" value="UPDATE"/>
|
||||
<column name="can_maker_checker" valueBoolean="false"/>
|
||||
</insert>
|
||||
<insert tableName="m_permission">
|
||||
<column name="grouping" value="organisation"/>
|
||||
<column name="code" value="DELETE_DELINQUENCY_RANGE"/>
|
||||
<column name="entity_name" value="DELINQUENCY_RANGE"/>
|
||||
<column name="action_name" value="DELETE"/>
|
||||
<column name="can_maker_checker" valueBoolean="false"/>
|
||||
</insert>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
+211
@@ -0,0 +1,211 @@
|
||||
/**
|
||||
* 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.integrationtests;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
import io.restassured.builder.RequestSpecBuilder;
|
||||
import io.restassured.builder.ResponseSpecBuilder;
|
||||
import io.restassured.http.ContentType;
|
||||
import io.restassured.specification.RequestSpecification;
|
||||
import io.restassured.specification.ResponseSpecification;
|
||||
import java.util.ArrayList;
|
||||
import org.apache.fineract.client.models.DeleteDelinquencyBucketResponse;
|
||||
import org.apache.fineract.client.models.DeleteDelinquencyRangeResponse;
|
||||
import org.apache.fineract.client.models.GetDelinquencyBucketsResponse;
|
||||
import org.apache.fineract.client.models.GetDelinquencyRangesResponse;
|
||||
import org.apache.fineract.client.models.PostDelinquencyBucketResponse;
|
||||
import org.apache.fineract.client.models.PostDelinquencyRangeResponse;
|
||||
import org.apache.fineract.client.models.PutDelinquencyBucketResponse;
|
||||
import org.apache.fineract.client.models.PutDelinquencyRangeResponse;
|
||||
import org.apache.fineract.integrationtests.common.Utils;
|
||||
import org.apache.fineract.integrationtests.common.products.DelinquencyBucketsHelper;
|
||||
import org.apache.fineract.integrationtests.common.products.DelinquencyRangesHelper;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class DelinquencyBucketsIntegrationTest {
|
||||
|
||||
private ResponseSpecification responseSpec;
|
||||
private RequestSpecification requestSpec;
|
||||
|
||||
@BeforeEach
|
||||
public void setup() {
|
||||
Utils.initializeRESTAssured();
|
||||
|
||||
requestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build();
|
||||
requestSpec.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey());
|
||||
responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateDelinquencyRanges() {
|
||||
// given
|
||||
final String jsonRange = DelinquencyRangesHelper.getAsJSON(1, 3);
|
||||
|
||||
// when
|
||||
final PostDelinquencyRangeResponse delinquencyRangeResponse01 = DelinquencyRangesHelper.createDelinquencyRange(requestSpec,
|
||||
responseSpec, jsonRange);
|
||||
final ArrayList<GetDelinquencyRangesResponse> ranges = DelinquencyRangesHelper.getDelinquencyRanges(requestSpec, responseSpec);
|
||||
|
||||
// then
|
||||
assertNotNull(delinquencyRangeResponse01);
|
||||
assertNotNull(ranges);
|
||||
assertEquals(1, ranges.get(0).getMinimumAgeDays(), "Expected Min Age Days to 1");
|
||||
assertEquals(3, ranges.get(0).getMaximumAgeDays(), "Expected Max Age Days to 3");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateDelinquencyRanges() {
|
||||
// given
|
||||
String jsonRange = DelinquencyRangesHelper.getAsJSON(1, 3);
|
||||
final PostDelinquencyRangeResponse delinquencyRangeResponse01 = DelinquencyRangesHelper.createDelinquencyRange(requestSpec,
|
||||
responseSpec, jsonRange);
|
||||
jsonRange = DelinquencyRangesHelper.getAsJSON(1, 7);
|
||||
assertNotNull(delinquencyRangeResponse01);
|
||||
|
||||
// when
|
||||
final PutDelinquencyRangeResponse delinquencyRangeResponse02 = DelinquencyRangesHelper.updateDelinquencyRange(requestSpec,
|
||||
responseSpec, delinquencyRangeResponse01.getResourceId(), jsonRange);
|
||||
final GetDelinquencyRangesResponse range = DelinquencyRangesHelper.getDelinquencyRange(requestSpec, responseSpec,
|
||||
delinquencyRangeResponse01.getResourceId());
|
||||
final DeleteDelinquencyRangeResponse deleteDelinquencyRangeResponse = DelinquencyRangesHelper.deleteDelinquencyRange(requestSpec,
|
||||
responseSpec, delinquencyRangeResponse01.getResourceId());
|
||||
|
||||
// then
|
||||
assertNotNull(delinquencyRangeResponse02);
|
||||
assertNotNull(deleteDelinquencyRangeResponse);
|
||||
assertNotNull(range);
|
||||
assertNotEquals(3, range.getMaximumAgeDays());
|
||||
assertEquals(1, range.getMinimumAgeDays());
|
||||
assertEquals(7, range.getMaximumAgeDays());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDelinquencyBuckets() {
|
||||
// given
|
||||
ArrayList<Integer> rangeIds = new ArrayList<>();
|
||||
String jsonRange = DelinquencyRangesHelper.getAsJSON(1, 3);
|
||||
PostDelinquencyRangeResponse delinquencyRangeResponse = DelinquencyRangesHelper.createDelinquencyRange(requestSpec, responseSpec,
|
||||
jsonRange);
|
||||
rangeIds.add(delinquencyRangeResponse.getResourceId());
|
||||
jsonRange = DelinquencyRangesHelper.getAsJSON(4, 30);
|
||||
// Create
|
||||
delinquencyRangeResponse = DelinquencyRangesHelper.createDelinquencyRange(requestSpec, responseSpec, jsonRange);
|
||||
rangeIds.add(delinquencyRangeResponse.getResourceId());
|
||||
String jsonBucket = DelinquencyBucketsHelper.getAsJSON(rangeIds);
|
||||
PostDelinquencyBucketResponse delinquencyBucketResponse = DelinquencyBucketsHelper.createDelinquencyBucket(requestSpec,
|
||||
responseSpec, jsonBucket);
|
||||
// Update
|
||||
jsonRange = DelinquencyRangesHelper.getAsJSON(31, 60);
|
||||
rangeIds.add(delinquencyRangeResponse.getResourceId());
|
||||
jsonBucket = DelinquencyBucketsHelper.getAsJSON(rangeIds);
|
||||
PutDelinquencyBucketResponse updateDelinquencyBucketResponse = DelinquencyBucketsHelper.updateDelinquencyBucket(requestSpec,
|
||||
responseSpec, delinquencyBucketResponse.getResourceId(), jsonBucket);
|
||||
delinquencyRangeResponse = DelinquencyRangesHelper.createDelinquencyRange(requestSpec, responseSpec, jsonRange);
|
||||
rangeIds.add(delinquencyRangeResponse.getResourceId());
|
||||
// Read
|
||||
final GetDelinquencyBucketsResponse delinquencyBucket = DelinquencyBucketsHelper.getDelinquencyBucket(requestSpec, responseSpec,
|
||||
delinquencyBucketResponse.getResourceId());
|
||||
|
||||
// when
|
||||
final ArrayList<GetDelinquencyBucketsResponse> bucketList = DelinquencyBucketsHelper.getDelinquencyBuckets(requestSpec,
|
||||
responseSpec);
|
||||
|
||||
// then
|
||||
assertNotNull(bucketList);
|
||||
assertNotNull(delinquencyBucket);
|
||||
assertEquals(2, delinquencyBucket.getRanges().size());
|
||||
assertNotNull(delinquencyBucketResponse);
|
||||
assertNotNull(updateDelinquencyBucketResponse);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDelinquencyBucketDelete() {
|
||||
// given
|
||||
ArrayList<Integer> rangeIds = new ArrayList<>();
|
||||
String jsonRange = DelinquencyRangesHelper.getAsJSON(1, 3);
|
||||
PostDelinquencyRangeResponse delinquencyRangeResponse = DelinquencyRangesHelper.createDelinquencyRange(requestSpec, responseSpec,
|
||||
jsonRange);
|
||||
rangeIds.add(delinquencyRangeResponse.getResourceId());
|
||||
jsonRange = DelinquencyRangesHelper.getAsJSON(4, 30);
|
||||
// Create
|
||||
delinquencyRangeResponse = DelinquencyRangesHelper.createDelinquencyRange(requestSpec, responseSpec, jsonRange);
|
||||
rangeIds.add(delinquencyRangeResponse.getResourceId());
|
||||
String jsonBucket = DelinquencyBucketsHelper.getAsJSON(rangeIds);
|
||||
PostDelinquencyBucketResponse delinquencyBucketResponse = DelinquencyBucketsHelper.createDelinquencyBucket(requestSpec,
|
||||
responseSpec, jsonBucket);
|
||||
// Delete
|
||||
DeleteDelinquencyBucketResponse deleteDelinquencyBucketResponse = DelinquencyBucketsHelper.deleteDelinquencyBucket(requestSpec,
|
||||
responseSpec, delinquencyBucketResponse.getResourceId());
|
||||
|
||||
// when
|
||||
final ArrayList<GetDelinquencyBucketsResponse> bucketList = DelinquencyBucketsHelper.getDelinquencyBuckets(requestSpec,
|
||||
responseSpec);
|
||||
|
||||
// then
|
||||
assertNotNull(bucketList);
|
||||
assertNotNull(delinquencyBucketResponse);
|
||||
assertNotNull(deleteDelinquencyBucketResponse);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDelinquencyBucketsRangeAgeOverlaped() {
|
||||
// Given
|
||||
ArrayList<Integer> rangeIds = new ArrayList<>();
|
||||
String jsonRange = DelinquencyRangesHelper.getAsJSON(1, 3);
|
||||
PostDelinquencyRangeResponse delinquencyRangeResponse = DelinquencyRangesHelper.createDelinquencyRange(requestSpec, responseSpec,
|
||||
jsonRange);
|
||||
rangeIds.add(delinquencyRangeResponse.getResourceId());
|
||||
jsonRange = DelinquencyRangesHelper.getAsJSON(3, 30);
|
||||
// Create
|
||||
delinquencyRangeResponse = DelinquencyRangesHelper.createDelinquencyRange(requestSpec, responseSpec, jsonRange);
|
||||
rangeIds.add(delinquencyRangeResponse.getResourceId());
|
||||
String jsonBucket = DelinquencyBucketsHelper.getAsJSON(rangeIds);
|
||||
final ResponseSpecification response403Spec = new ResponseSpecBuilder().expectStatusCode(403).build();
|
||||
|
||||
// When
|
||||
DelinquencyBucketsHelper.createDelinquencyBucket(requestSpec, response403Spec, jsonBucket);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDelinquencyBucketsNameDuplication() {
|
||||
// Given
|
||||
ArrayList<Integer> rangeIds = new ArrayList<>();
|
||||
String jsonRange = DelinquencyRangesHelper.getAsJSON(1, 3);
|
||||
PostDelinquencyRangeResponse delinquencyRangeResponse = DelinquencyRangesHelper.createDelinquencyRange(requestSpec, responseSpec,
|
||||
jsonRange);
|
||||
rangeIds.add(delinquencyRangeResponse.getResourceId());
|
||||
jsonRange = DelinquencyRangesHelper.getAsJSON(4, 30);
|
||||
// Create
|
||||
delinquencyRangeResponse = DelinquencyRangesHelper.createDelinquencyRange(requestSpec, responseSpec, jsonRange);
|
||||
rangeIds.add(delinquencyRangeResponse.getResourceId());
|
||||
String jsonBucket = DelinquencyBucketsHelper.getAsJSON(rangeIds);
|
||||
final ResponseSpecification response403Spec = new ResponseSpecBuilder().expectStatusCode(403).build();
|
||||
|
||||
// When
|
||||
DelinquencyBucketsHelper.createDelinquencyBucket(requestSpec, responseSpec, jsonBucket);
|
||||
|
||||
// Then
|
||||
DelinquencyBucketsHelper.createDelinquencyBucket(requestSpec, response403Spec, jsonBucket);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -338,4 +338,9 @@ public final class Utils {
|
||||
.spec(responseSpec).log().ifError().when().get(getURL).andReturn().asString();
|
||||
return templateLocation.substring(1, templateLocation.length() - 1);
|
||||
}
|
||||
|
||||
public static String emptyJson() {
|
||||
return "{}";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
/**
|
||||
* 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.integrationtests.common.products;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.linecorp.armeria.internal.shaded.guava.reflect.TypeToken;
|
||||
import io.restassured.specification.RequestSpecification;
|
||||
import io.restassured.specification.ResponseSpecification;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import org.apache.fineract.client.models.DeleteDelinquencyBucketResponse;
|
||||
import org.apache.fineract.client.models.GetDelinquencyBucketsResponse;
|
||||
import org.apache.fineract.client.models.PostDelinquencyBucketResponse;
|
||||
import org.apache.fineract.client.models.PutDelinquencyBucketResponse;
|
||||
import org.apache.fineract.client.util.JSON;
|
||||
import org.apache.fineract.integrationtests.common.Utils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class DelinquencyBucketsHelper {
|
||||
|
||||
private static final String DELINQUENCY_BUCKETS_URL = "/fineract-provider/api/v1/delinquency/buckets";
|
||||
private static final Gson GSON = new JSON().getGson();
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(DelinquencyBucketsHelper.class);
|
||||
|
||||
protected DelinquencyBucketsHelper() {}
|
||||
|
||||
public static ArrayList<GetDelinquencyBucketsResponse> getDelinquencyBuckets(final RequestSpecification requestSpec,
|
||||
final ResponseSpecification responseSpec) {
|
||||
String response = Utils.performServerGet(requestSpec, responseSpec, DELINQUENCY_BUCKETS_URL + "?" + Utils.TENANT_IDENTIFIER);
|
||||
|
||||
Type delinquencyBucketListType = new TypeToken<ArrayList<GetDelinquencyBucketsResponse>>() {}.getType();
|
||||
return GSON.fromJson(response, delinquencyBucketListType);
|
||||
}
|
||||
|
||||
public static GetDelinquencyBucketsResponse getDelinquencyBucket(final RequestSpecification requestSpec,
|
||||
final ResponseSpecification responseSpec, final Integer resourceId) {
|
||||
String response = Utils.performServerGet(requestSpec, responseSpec,
|
||||
DELINQUENCY_BUCKETS_URL + "/" + resourceId + "?" + Utils.TENANT_IDENTIFIER);
|
||||
return GSON.fromJson(response, GetDelinquencyBucketsResponse.class);
|
||||
}
|
||||
|
||||
public static PostDelinquencyBucketResponse createDelinquencyBucket(final RequestSpecification requestSpec,
|
||||
final ResponseSpecification responseSpec, final String json) {
|
||||
LOG.info("JSON: {}", json);
|
||||
final String response = Utils.performServerPost(requestSpec, responseSpec, DELINQUENCY_BUCKETS_URL + "?" + Utils.TENANT_IDENTIFIER,
|
||||
json, null);
|
||||
return GSON.fromJson(response, PostDelinquencyBucketResponse.class);
|
||||
}
|
||||
|
||||
public static PutDelinquencyBucketResponse updateDelinquencyBucket(final RequestSpecification requestSpec,
|
||||
final ResponseSpecification responseSpec, final Integer resourceId, final String json) {
|
||||
LOG.info("JSON: {}", json);
|
||||
final String response = Utils.performServerPut(requestSpec, responseSpec,
|
||||
DELINQUENCY_BUCKETS_URL + "/" + resourceId + "?" + Utils.TENANT_IDENTIFIER, json, null);
|
||||
return GSON.fromJson(response, PutDelinquencyBucketResponse.class);
|
||||
}
|
||||
|
||||
public static DeleteDelinquencyBucketResponse deleteDelinquencyBucket(final RequestSpecification requestSpec,
|
||||
final ResponseSpecification responseSpec, final Integer resourceId) {
|
||||
final String response = Utils.performServerDelete(requestSpec, responseSpec,
|
||||
DELINQUENCY_BUCKETS_URL + "/" + resourceId + "?" + Utils.TENANT_IDENTIFIER, Utils.emptyJson(), null);
|
||||
return GSON.fromJson(response, DeleteDelinquencyBucketResponse.class);
|
||||
}
|
||||
|
||||
public static String getAsJSON(final ArrayList<Integer> rangeIds) {
|
||||
final HashMap<String, Object> map = new HashMap<>();
|
||||
map.put("name", Utils.randomNameGenerator("Delinquency_Bucket_", 4));
|
||||
map.put("ranges", rangeIds.toArray());
|
||||
return new Gson().toJson(map);
|
||||
}
|
||||
|
||||
}
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
/**
|
||||
* 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.integrationtests.common.products;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.linecorp.armeria.internal.shaded.guava.reflect.TypeToken;
|
||||
import io.restassured.specification.RequestSpecification;
|
||||
import io.restassured.specification.ResponseSpecification;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import org.apache.fineract.client.models.DeleteDelinquencyRangeResponse;
|
||||
import org.apache.fineract.client.models.GetDelinquencyRangesResponse;
|
||||
import org.apache.fineract.client.models.PostDelinquencyRangeResponse;
|
||||
import org.apache.fineract.client.models.PutDelinquencyRangeResponse;
|
||||
import org.apache.fineract.client.util.JSON;
|
||||
import org.apache.fineract.integrationtests.common.Utils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class DelinquencyRangesHelper {
|
||||
|
||||
private static final String DELINQUENCY_RANGES_URL = "/fineract-provider/api/v1/delinquency/ranges";
|
||||
private static final Gson GSON = new JSON().getGson();
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(DelinquencyRangesHelper.class);
|
||||
|
||||
protected DelinquencyRangesHelper() {}
|
||||
|
||||
public static ArrayList<GetDelinquencyRangesResponse> getDelinquencyRanges(final RequestSpecification requestSpec,
|
||||
final ResponseSpecification responseSpec) {
|
||||
String response = Utils.performServerGet(requestSpec, responseSpec, DELINQUENCY_RANGES_URL + "?" + Utils.TENANT_IDENTIFIER);
|
||||
|
||||
Type delinquencyRangeListType = new TypeToken<ArrayList<GetDelinquencyRangesResponse>>() {}.getType();
|
||||
return GSON.fromJson(response, delinquencyRangeListType);
|
||||
}
|
||||
|
||||
public static GetDelinquencyRangesResponse getDelinquencyRange(final RequestSpecification requestSpec,
|
||||
final ResponseSpecification responseSpec, final Integer resourceId) {
|
||||
String response = Utils.performServerGet(requestSpec, responseSpec,
|
||||
DELINQUENCY_RANGES_URL + "/" + resourceId + "?" + Utils.TENANT_IDENTIFIER);
|
||||
LOG.info("----- {}", response);
|
||||
return GSON.fromJson(response, GetDelinquencyRangesResponse.class);
|
||||
}
|
||||
|
||||
public static PostDelinquencyRangeResponse createDelinquencyRange(final RequestSpecification requestSpec,
|
||||
final ResponseSpecification responseSpec, final String json) {
|
||||
final String response = Utils.performServerPost(requestSpec, responseSpec, DELINQUENCY_RANGES_URL + "?" + Utils.TENANT_IDENTIFIER,
|
||||
json, null);
|
||||
LOG.info("----- {}", response);
|
||||
return GSON.fromJson(response, PostDelinquencyRangeResponse.class);
|
||||
}
|
||||
|
||||
public static PutDelinquencyRangeResponse updateDelinquencyRange(final RequestSpecification requestSpec,
|
||||
final ResponseSpecification responseSpec, final Integer resourceId, final String json) {
|
||||
final String response = Utils.performServerPut(requestSpec, responseSpec,
|
||||
DELINQUENCY_RANGES_URL + "/" + resourceId + "?" + Utils.TENANT_IDENTIFIER, json, null);
|
||||
LOG.info("----- {}", response);
|
||||
return GSON.fromJson(response, PutDelinquencyRangeResponse.class);
|
||||
}
|
||||
|
||||
public static DeleteDelinquencyRangeResponse deleteDelinquencyRange(final RequestSpecification requestSpec,
|
||||
final ResponseSpecification responseSpec, final Integer resourceId) {
|
||||
final String response = Utils.performServerDelete(requestSpec, responseSpec,
|
||||
DELINQUENCY_RANGES_URL + "/" + resourceId + "?" + Utils.TENANT_IDENTIFIER, Utils.emptyJson(), null);
|
||||
LOG.info("----- {}", response);
|
||||
return GSON.fromJson(response, DeleteDelinquencyRangeResponse.class);
|
||||
}
|
||||
|
||||
public static String getAsJSON(int minimumAgeDays, int maximumAgeDays) {
|
||||
final HashMap<String, Object> map = new HashMap<>();
|
||||
map.put("classification", Utils.randomNameGenerator("Delinquency_", 4));
|
||||
map.put("minimumAgeDays", minimumAgeDays);
|
||||
map.put("maximumAgeDays", maximumAgeDays);
|
||||
map.put("locale", "en");
|
||||
return new Gson().toJson(map);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user