Skip to content

Commit a48c506

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

107 files changed

Lines changed: 4196 additions & 3444 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 & 62 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;
@@ -39,114 +33,98 @@
3933
import jakarta.ws.rs.core.MediaType;
4034
import jakarta.ws.rs.core.UriInfo;
4135
import java.util.List;
36+
import java.util.function.Supplier;
4237
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;
38+
import org.apache.fineract.command.core.CommandPipeline;
4639
import org.apache.fineract.infrastructure.core.api.ApiRequestParameterHelper;
47-
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
4840
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;
41+
import org.apache.fineract.portfolio.interestratechart.command.InterestRateChartSlabsCreateCommand;
42+
import org.apache.fineract.portfolio.interestratechart.command.InterestRateChartSlabsDeleteCommand;
43+
import org.apache.fineract.portfolio.interestratechart.command.InterestRateChartSlabsUpdateCommand;
5144
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;
45+
import org.apache.fineract.portfolio.interestratechart.data.InterestRateChartSlabsCreateRequest;
46+
import org.apache.fineract.portfolio.interestratechart.data.InterestRateChartSlabsCreateResponse;
47+
import org.apache.fineract.portfolio.interestratechart.data.InterestRateChartSlabsDeleteRequest;
48+
import org.apache.fineract.portfolio.interestratechart.data.InterestRateChartSlabsDeleteResponse;
49+
import org.apache.fineract.portfolio.interestratechart.data.InterestRateChartSlabsUpdateRequest;
50+
import org.apache.fineract.portfolio.interestratechart.data.InterestRateChartSlabsUpdateResponse;
51+
import org.apache.fineract.portfolio.interestratechart.service.InterestRateChartSlabsReadService;
5452
import org.springframework.stereotype.Component;
5553

5654
@Path("/v1/interestratecharts/{chartId}/chartslabs")
5755
@Component
56+
@Consumes({ MediaType.APPLICATION_JSON })
57+
@Produces({ MediaType.APPLICATION_JSON })
5858
@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.")
5959
@RequiredArgsConstructor
6060
public class InterestRateChartSlabsApiResource {
6161

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

6866
@GET
6967
@Path("template")
70-
@Consumes({ MediaType.APPLICATION_JSON })
71-
@Produces({ MediaType.APPLICATION_JSON })
7268
public InterestRateChartSlabData template(@PathParam("chartId") @Parameter(description = "chartId") final Long chartId) {
73-
return this.interestRateChartSlabReadPlatformService.retrieveTemplate();
69+
return this.interestRateChartSlabsReadService.retrieveTemplate();
7470
}
7571

7672
@GET
77-
@Consumes({ MediaType.APPLICATION_JSON })
78-
@Produces({ MediaType.APPLICATION_JSON })
7973
@Operation(summary = "Retrieve all Slabs", description = "Retrieve list of slabs associated with a chart\n" + "\n"
8074
+ "Example Requests:\n" + "\n" + "interestratecharts/1/chartslabs")
8175
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);
76+
return this.interestRateChartSlabsReadService.retrieveAll(chartId);
8577
}
8678

8779
@GET
8880
@Path("{chartSlabId}")
89-
@Consumes({ MediaType.APPLICATION_JSON })
90-
@Produces({ MediaType.APPLICATION_JSON })
9181
@Operation(summary = "Retrieve a Slab", description = "Retrieve a slab associated with an Interest rate chart\n" + "\n"
9282
+ "Example Requests:\n" + "\n" + "interestratecharts/1/chartslabs/1\n")
9383
public InterestRateChartSlabData retrieveOne(@PathParam("chartId") @Parameter(description = "chartId") final Long chartId,
9484
@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);
85+
InterestRateChartSlabData chartSlab = this.interestRateChartSlabsReadService.retrieveOne(chartId, chartSlabId);
9986
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
10087
if (settings.isTemplate()) {
101-
chartSlab = this.interestRateChartSlabReadPlatformService.retrieveWithTemplate(chartSlab);
88+
chartSlab = this.interestRateChartSlabsReadService.retrieveWithTemplate(chartSlab);
10289
}
103-
10490
return chartSlab;
10591
}
10692

10793
@POST
108-
@Consumes({ MediaType.APPLICATION_JSON })
109-
@Produces({ MediaType.APPLICATION_JSON })
11094
@Operation(summary = "Create a Slab", description = "Creates a new interest rate slab for an interest rate chart.\n"
11195
+ "Mandatory Fields\n" + "periodType, fromPeriod, annualInterestRate\n" + "Optional Fields\n" + "toPeriod and description\n"
11296
+ "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);
97+
public InterestRateChartSlabsCreateResponse create(@PathParam("chartId") @Parameter(description = "chartId") final Long chartId,
98+
@Parameter(hidden = true) final InterestRateChartSlabsCreateRequest request) {
99+
request.setChartId(chartId);
100+
final var command = new InterestRateChartSlabsCreateCommand();
101+
command.setPayload(request);
102+
final Supplier<InterestRateChartSlabsCreateResponse> responseSupplier = commandPipeline.send(command);
103+
return responseSupplier.get();
122104
}
123105

124106
@PUT
125107
@Path("{chartSlabId}")
126-
@Consumes({ MediaType.APPLICATION_JSON })
127-
@Produces({ MediaType.APPLICATION_JSON })
128108
@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,
109+
public InterestRateChartSlabsUpdateResponse update(@PathParam("chartId") @Parameter(description = "chartId") final Long chartId,
132110
@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);
111+
@Parameter(hidden = true) final InterestRateChartSlabsUpdateRequest request) {
112+
request.setChartId(chartId);
113+
request.setChartSlabId(chartSlabId);
114+
final var command = new InterestRateChartSlabsUpdateCommand();
115+
command.setPayload(request);
116+
final Supplier<InterestRateChartSlabsUpdateResponse> responseSupplier = commandPipeline.send(command);
117+
return responseSupplier.get();
139118
}
140119

141120
@DELETE
142121
@Path("{chartSlabId}")
143-
@Consumes({ MediaType.APPLICATION_JSON })
144-
@Produces({ MediaType.APPLICATION_JSON })
145122
@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,
123+
public InterestRateChartSlabsDeleteResponse delete(@PathParam("chartId") @Parameter(description = "chartId") final Long chartId,
148124
@PathParam("chartSlabId") @Parameter(description = "chartSlabId") final Long chartSlabId) {
149-
final CommandWrapper commandRequest = new CommandWrapperBuilder().deleteInterestRateChartSlab(chartId, chartSlabId).build();
150-
return this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
125+
final var command = new InterestRateChartSlabsDeleteCommand();
126+
command.setPayload(InterestRateChartSlabsDeleteRequest.builder().chartId(chartId).chartSlabId(chartSlabId).build());
127+
final Supplier<InterestRateChartSlabsDeleteResponse> responseSupplier = commandPipeline.send(command);
128+
return responseSupplier.get();
151129
}
152130
}

0 commit comments

Comments
 (0)