Skip to content

Commit 101b72a

Browse files
committed
FINERACT-2287: New command processing for interest rate charts and deposit products
1 parent 84e2dde commit 101b72a

108 files changed

Lines changed: 4286 additions & 3584 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/SecurityConfig.java

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,50 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
335335
.hasAnyAuthority(ALL_FUNCTIONS, ALL_FUNCTIONS_READ, "READ_WORKING_DAYS")
336336
.requestMatchers(API_MATCHER.matcher(HttpMethod.PUT, "/api/*/workingdays"))
337337
.hasAnyAuthority(ALL_FUNCTIONS, ALL_FUNCTIONS_WRITE, "UPDATE_WORKING_DAYS")
338+
// interest rate chart slabs (before charts for specificity)
339+
.requestMatchers(API_MATCHER.matcher(HttpMethod.GET, "/api/*/interestratecharts/*/chartslabs"))
340+
.hasAnyAuthority(ALL_FUNCTIONS, ALL_FUNCTIONS_READ, "READ_CHARTSLAB")
341+
.requestMatchers(API_MATCHER.matcher(HttpMethod.GET, "/api/*/interestratecharts/*/chartslabs/*"))
342+
.hasAnyAuthority(ALL_FUNCTIONS, ALL_FUNCTIONS_READ, "READ_CHARTSLAB")
343+
.requestMatchers(API_MATCHER.matcher(HttpMethod.POST, "/api/*/interestratecharts/*/chartslabs"))
344+
.hasAnyAuthority(ALL_FUNCTIONS, ALL_FUNCTIONS_WRITE, "CREATE_CHARTSLAB")
345+
.requestMatchers(API_MATCHER.matcher(HttpMethod.PUT, "/api/*/interestratecharts/*/chartslabs/*"))
346+
.hasAnyAuthority(ALL_FUNCTIONS, ALL_FUNCTIONS_WRITE, "UPDATE_CHARTSLAB")
347+
.requestMatchers(API_MATCHER.matcher(HttpMethod.DELETE, "/api/*/interestratecharts/*/chartslabs/*"))
348+
.hasAnyAuthority(ALL_FUNCTIONS, ALL_FUNCTIONS_WRITE, "DELETE_CHARTSLAB")
349+
// interest rate chart
350+
.requestMatchers(API_MATCHER.matcher(HttpMethod.GET, "/api/*/interestratecharts"))
351+
.hasAnyAuthority(ALL_FUNCTIONS, ALL_FUNCTIONS_READ, "READ_INTERESTRATECHART")
352+
.requestMatchers(API_MATCHER.matcher(HttpMethod.GET, "/api/*/interestratecharts/*"))
353+
.hasAnyAuthority(ALL_FUNCTIONS, ALL_FUNCTIONS_READ, "READ_INTERESTRATECHART")
354+
.requestMatchers(API_MATCHER.matcher(HttpMethod.POST, "/api/*/interestratecharts"))
355+
.hasAnyAuthority(ALL_FUNCTIONS, ALL_FUNCTIONS_WRITE, "CREATE_INTERESTRATECHART")
356+
.requestMatchers(API_MATCHER.matcher(HttpMethod.PUT, "/api/*/interestratecharts/*"))
357+
.hasAnyAuthority(ALL_FUNCTIONS, ALL_FUNCTIONS_WRITE, "UPDATE_INTERESTRATECHART")
358+
.requestMatchers(API_MATCHER.matcher(HttpMethod.DELETE, "/api/*/interestratecharts/*"))
359+
.hasAnyAuthority(ALL_FUNCTIONS, ALL_FUNCTIONS_WRITE, "DELETE_INTERESTRATECHART")
360+
// fixed deposit products
361+
.requestMatchers(API_MATCHER.matcher(HttpMethod.GET, "/api/*/fixeddepositproducts"))
362+
.hasAnyAuthority(ALL_FUNCTIONS, ALL_FUNCTIONS_READ, "READ_FIXEDDEPOSITPRODUCT")
363+
.requestMatchers(API_MATCHER.matcher(HttpMethod.GET, "/api/*/fixeddepositproducts/*"))
364+
.hasAnyAuthority(ALL_FUNCTIONS, ALL_FUNCTIONS_READ, "READ_FIXEDDEPOSITPRODUCT")
365+
.requestMatchers(API_MATCHER.matcher(HttpMethod.POST, "/api/*/fixeddepositproducts"))
366+
.hasAnyAuthority(ALL_FUNCTIONS, ALL_FUNCTIONS_WRITE, "CREATE_FIXEDDEPOSITPRODUCT")
367+
.requestMatchers(API_MATCHER.matcher(HttpMethod.PUT, "/api/*/fixeddepositproducts/*"))
368+
.hasAnyAuthority(ALL_FUNCTIONS, ALL_FUNCTIONS_WRITE, "UPDATE_FIXEDDEPOSITPRODUCT")
369+
.requestMatchers(API_MATCHER.matcher(HttpMethod.DELETE, "/api/*/fixeddepositproducts/*"))
370+
.hasAnyAuthority(ALL_FUNCTIONS, ALL_FUNCTIONS_WRITE, "DELETE_FIXEDDEPOSITPRODUCT")
371+
// recurring deposit products
372+
.requestMatchers(API_MATCHER.matcher(HttpMethod.GET, "/api/*/recurringdepositproducts"))
373+
.hasAnyAuthority(ALL_FUNCTIONS, ALL_FUNCTIONS_READ, "READ_RECURRINGDEPOSITPRODUCT")
374+
.requestMatchers(API_MATCHER.matcher(HttpMethod.GET, "/api/*/recurringdepositproducts/*"))
375+
.hasAnyAuthority(ALL_FUNCTIONS, ALL_FUNCTIONS_READ, "READ_RECURRINGDEPOSITPRODUCT")
376+
.requestMatchers(API_MATCHER.matcher(HttpMethod.POST, "/api/*/recurringdepositproducts"))
377+
.hasAnyAuthority(ALL_FUNCTIONS, ALL_FUNCTIONS_WRITE, "CREATE_RECURRINGDEPOSITPRODUCT")
378+
.requestMatchers(API_MATCHER.matcher(HttpMethod.PUT, "/api/*/recurringdepositproducts/*"))
379+
.hasAnyAuthority(ALL_FUNCTIONS, ALL_FUNCTIONS_WRITE, "UPDATE_RECURRINGDEPOSITPRODUCT")
380+
.requestMatchers(API_MATCHER.matcher(HttpMethod.DELETE, "/api/*/recurringdepositproducts/*"))
381+
.hasAnyAuthority(ALL_FUNCTIONS, ALL_FUNCTIONS_WRITE, "DELETE_RECURRINGDEPOSITPRODUCT")
338382

339383
.requestMatchers(API_MATCHER.matcher(HttpMethod.POST, "/api/*/twofactor/validate")).fullyAuthenticated()
340384
.requestMatchers(API_MATCHER.matcher("/api/*/twofactor")).fullyAuthenticated()

fineract-provider/src/main/java/org/apache/fineract/portfolio/interestratechart/api/InterestRateChartSlabsApiResource.java

Lines changed: 40 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,8 @@
1818
*/
1919
package org.apache.fineract.portfolio.interestratechart.api;
2020

21-
import static org.apache.fineract.portfolio.interestratechart.InterestRateChartSlabApiConstants.INTERESTRATE_CHART_SLAB_RESOURCE_NAME;
22-
2321
import io.swagger.v3.oas.annotations.Operation;
2422
import io.swagger.v3.oas.annotations.Parameter;
25-
import io.swagger.v3.oas.annotations.media.Content;
26-
import io.swagger.v3.oas.annotations.media.Schema;
27-
import io.swagger.v3.oas.annotations.parameters.RequestBody;
28-
import io.swagger.v3.oas.annotations.responses.ApiResponse;
2923
import io.swagger.v3.oas.annotations.tags.Tag;
3024
import jakarta.ws.rs.Consumes;
3125
import jakarta.ws.rs.DELETE;
@@ -35,118 +29,92 @@
3529
import jakarta.ws.rs.Path;
3630
import jakarta.ws.rs.PathParam;
3731
import jakarta.ws.rs.Produces;
38-
import jakarta.ws.rs.core.Context;
3932
import jakarta.ws.rs.core.MediaType;
40-
import jakarta.ws.rs.core.UriInfo;
4133
import java.util.List;
34+
import java.util.function.Supplier;
4235
import lombok.RequiredArgsConstructor;
43-
import org.apache.fineract.commands.domain.CommandWrapper;
44-
import org.apache.fineract.commands.service.CommandWrapperBuilder;
45-
import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
46-
import org.apache.fineract.infrastructure.core.api.ApiRequestParameterHelper;
47-
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
48-
import org.apache.fineract.infrastructure.core.serialization.ApiRequestJsonSerializationSettings;
49-
import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSerializer;
50-
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
36+
import org.apache.fineract.command.core.CommandPipeline;
37+
import org.apache.fineract.portfolio.interestratechart.command.InterestRateChartSlabsCreateCommand;
38+
import org.apache.fineract.portfolio.interestratechart.command.InterestRateChartSlabsDeleteCommand;
39+
import org.apache.fineract.portfolio.interestratechart.command.InterestRateChartSlabsUpdateCommand;
5140
import org.apache.fineract.portfolio.interestratechart.data.InterestRateChartSlabData;
52-
import org.apache.fineract.portfolio.interestratechart.data.InterestRateChartStabRequest;
53-
import org.apache.fineract.portfolio.interestratechart.service.InterestRateChartSlabReadPlatformService;
41+
import org.apache.fineract.portfolio.interestratechart.data.InterestRateChartSlabsCreateRequest;
42+
import org.apache.fineract.portfolio.interestratechart.data.InterestRateChartSlabsCreateResponse;
43+
import org.apache.fineract.portfolio.interestratechart.data.InterestRateChartSlabsDeleteRequest;
44+
import org.apache.fineract.portfolio.interestratechart.data.InterestRateChartSlabsDeleteResponse;
45+
import org.apache.fineract.portfolio.interestratechart.data.InterestRateChartSlabsUpdateRequest;
46+
import org.apache.fineract.portfolio.interestratechart.data.InterestRateChartSlabsUpdateResponse;
47+
import org.apache.fineract.portfolio.interestratechart.service.InterestRateChartSlabsReadService;
5448
import org.springframework.stereotype.Component;
5549

5650
@Path("/v1/interestratecharts/{chartId}/chartslabs")
5751
@Component
52+
@Consumes({ MediaType.APPLICATION_JSON })
53+
@Produces({ MediaType.APPLICATION_JSON })
5854
@Tag(name = "Interest Rate Slab (A.K.A interest bands)", description = "The slabs a.k.a interest bands are associated with Interest Rate Chart. These bands allow to define different interest rates for different deposit term periods.")
5955
@RequiredArgsConstructor
6056
public class InterestRateChartSlabsApiResource {
6157

62-
private final InterestRateChartSlabReadPlatformService interestRateChartSlabReadPlatformService;
63-
private final PlatformSecurityContext context;
64-
private final DefaultToApiJsonSerializer<InterestRateChartSlabData> toApiJsonSerializer;
65-
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
66-
private final ApiRequestParameterHelper apiRequestParameterHelper;
58+
private final InterestRateChartSlabsReadService interestRateChartSlabsReadService;
59+
private final CommandPipeline commandPipeline;
6760

6861
@GET
6962
@Path("template")
70-
@Consumes({ MediaType.APPLICATION_JSON })
71-
@Produces({ MediaType.APPLICATION_JSON })
7263
public InterestRateChartSlabData template(@PathParam("chartId") @Parameter(description = "chartId") final Long chartId) {
73-
return this.interestRateChartSlabReadPlatformService.retrieveTemplate();
64+
return interestRateChartSlabsReadService.retrieveTemplate();
7465
}
7566

7667
@GET
77-
@Consumes({ MediaType.APPLICATION_JSON })
78-
@Produces({ MediaType.APPLICATION_JSON })
7968
@Operation(summary = "Retrieve all Slabs", description = "Retrieve list of slabs associated with a chart\n" + "\n"
8069
+ "Example Requests:\n" + "\n" + "interestratecharts/1/chartslabs")
8170
public List<InterestRateChartSlabData> retrieveAll(@PathParam("chartId") @Parameter(description = "chartId") final Long chartId) {
82-
83-
this.context.authenticatedUser().validateHasReadPermission(INTERESTRATE_CHART_SLAB_RESOURCE_NAME);
84-
return this.interestRateChartSlabReadPlatformService.retrieveAll(chartId);
71+
return interestRateChartSlabsReadService.retrieveAll(chartId);
8572
}
8673

8774
@GET
8875
@Path("{chartSlabId}")
89-
@Consumes({ MediaType.APPLICATION_JSON })
90-
@Produces({ MediaType.APPLICATION_JSON })
9176
@Operation(summary = "Retrieve a Slab", description = "Retrieve a slab associated with an Interest rate chart\n" + "\n"
9277
+ "Example Requests:\n" + "\n" + "interestratecharts/1/chartslabs/1\n")
9378
public InterestRateChartSlabData retrieveOne(@PathParam("chartId") @Parameter(description = "chartId") final Long chartId,
94-
@PathParam("chartSlabId") @Parameter(description = "chartSlabId") final Long chartSlabId, @Context final UriInfo uriInfo) {
95-
96-
this.context.authenticatedUser().validateHasReadPermission(INTERESTRATE_CHART_SLAB_RESOURCE_NAME);
97-
98-
InterestRateChartSlabData chartSlab = this.interestRateChartSlabReadPlatformService.retrieveOne(chartId, chartSlabId);
99-
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
100-
if (settings.isTemplate()) {
101-
chartSlab = this.interestRateChartSlabReadPlatformService.retrieveWithTemplate(chartSlab);
102-
}
103-
104-
return chartSlab;
79+
@PathParam("chartSlabId") @Parameter(description = "chartSlabId") final Long chartSlabId) {
80+
return interestRateChartSlabsReadService.retrieveOne(chartId, chartSlabId);
10581
}
10682

10783
@POST
108-
@Consumes({ MediaType.APPLICATION_JSON })
109-
@Produces({ MediaType.APPLICATION_JSON })
11084
@Operation(summary = "Create a Slab", description = "Creates a new interest rate slab for an interest rate chart.\n"
11185
+ "Mandatory Fields\n" + "periodType, fromPeriod, annualInterestRate\n" + "Optional Fields\n" + "toPeriod and description\n"
11286
+ "Example Requests:\n" + "\n" + "interestratecharts/1/chartslabs")
113-
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = InterestRateChartStabRequest.class)))
114-
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = InterestRateChartSlabsApiResourceSwagger.PostInterestRateChartsChartIdChartSlabsResponse.class)))
115-
public CommandProcessingResult create(@PathParam("chartId") @Parameter(description = "chartId") final Long chartId,
116-
@Parameter(hidden = true) InterestRateChartStabRequest interestRateChartStabRequest) {
117-
118-
final CommandWrapper commandRequest = new CommandWrapperBuilder().createInterestRateChartSlab(chartId)
119-
.withJson(toApiJsonSerializer.serialize(interestRateChartStabRequest)).build();
120-
121-
return this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
87+
public InterestRateChartSlabsCreateResponse create(@PathParam("chartId") @Parameter(description = "chartId") final Long chartId,
88+
@Parameter(hidden = true) final InterestRateChartSlabsCreateRequest request) {
89+
request.setChartId(chartId);
90+
final var command = new InterestRateChartSlabsCreateCommand();
91+
command.setPayload(request);
92+
final Supplier<InterestRateChartSlabsCreateResponse> responseSupplier = commandPipeline.send(command);
93+
return responseSupplier.get();
12294
}
12395

12496
@PUT
12597
@Path("{chartSlabId}")
126-
@Consumes({ MediaType.APPLICATION_JSON })
127-
@Produces({ MediaType.APPLICATION_JSON })
12898
@Operation(summary = "Update a Slab", description = "It updates the Slab from chart")
129-
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = InterestRateChartStabRequest.class)))
130-
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = InterestRateChartSlabsApiResourceSwagger.PutInterestRateChartsChartIdChartSlabsChartSlabIdResponse.class)))
131-
public CommandProcessingResult update(@PathParam("chartId") @Parameter(description = "chartId") final Long chartId,
99+
public InterestRateChartSlabsUpdateResponse update(@PathParam("chartId") @Parameter(description = "chartId") final Long chartId,
132100
@PathParam("chartSlabId") @Parameter(description = "chartSlabId") final Long chartSlabId,
133-
@Parameter(hidden = true) InterestRateChartStabRequest request) {
134-
135-
final CommandWrapper commandRequest = new CommandWrapperBuilder().updateInterestRateChartSlab(chartId, chartSlabId)
136-
.withJson(toApiJsonSerializer.serialize(request)).build();
137-
138-
return this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
101+
@Parameter(hidden = true) final InterestRateChartSlabsUpdateRequest request) {
102+
request.setChartId(chartId);
103+
request.setChartSlabId(chartSlabId);
104+
final var command = new InterestRateChartSlabsUpdateCommand();
105+
command.setPayload(request);
106+
final Supplier<InterestRateChartSlabsUpdateResponse> responseSupplier = commandPipeline.send(command);
107+
return responseSupplier.get();
139108
}
140109

141110
@DELETE
142111
@Path("{chartSlabId}")
143-
@Consumes({ MediaType.APPLICATION_JSON })
144-
@Produces({ MediaType.APPLICATION_JSON })
145112
@Operation(summary = "Delete a Slab", description = "Delete a Slab from a chart")
146-
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = InterestRateChartSlabsApiResourceSwagger.DeleteInterestRateChartsChartIdChartSlabsResponse.class)))
147-
public CommandProcessingResult delete(@PathParam("chartId") @Parameter(description = "chartId") final Long chartId,
113+
public InterestRateChartSlabsDeleteResponse delete(@PathParam("chartId") @Parameter(description = "chartId") final Long chartId,
148114
@PathParam("chartSlabId") @Parameter(description = "chartSlabId") final Long chartSlabId) {
149-
final CommandWrapper commandRequest = new CommandWrapperBuilder().deleteInterestRateChartSlab(chartId, chartSlabId).build();
150-
return this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
115+
final var command = new InterestRateChartSlabsDeleteCommand();
116+
command.setPayload(InterestRateChartSlabsDeleteRequest.builder().chartId(chartId).chartSlabId(chartSlabId).build());
117+
final Supplier<InterestRateChartSlabsDeleteResponse> responseSupplier = commandPipeline.send(command);
118+
return responseSupplier.get();
151119
}
152120
}

0 commit comments

Comments
 (0)