Skip to content

Commit 8571fd6

Browse files
FINERACT-2256: New command processing - Product Mix
1 parent 83021ce commit 8571fd6

13 files changed

Lines changed: 217 additions & 246 deletions

fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/productmix/api/ProductMixApiResource.java

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

2121
import io.swagger.v3.oas.annotations.tags.Tag;
22+
import jakarta.validation.Valid;
2223
import jakarta.ws.rs.Consumes;
2324
import jakarta.ws.rs.DELETE;
2425
import jakarta.ws.rs.GET;
@@ -34,18 +35,21 @@
3435
import java.util.Collection;
3536
import java.util.HashSet;
3637
import java.util.Set;
38+
import java.util.function.Supplier;
3739
import lombok.RequiredArgsConstructor;
38-
import org.apache.fineract.commands.domain.CommandWrapper;
39-
import org.apache.fineract.commands.service.CommandWrapperBuilder;
40-
import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
40+
import org.apache.fineract.command.core.CommandPipeline;
4141
import org.apache.fineract.infrastructure.core.api.ApiRequestParameterHelper;
42-
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
4342
import org.apache.fineract.infrastructure.core.serialization.ApiRequestJsonSerializationSettings;
4443
import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSerializer;
4544
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
4645
import org.apache.fineract.portfolio.loanproduct.data.LoanProductData;
46+
import org.apache.fineract.portfolio.loanproduct.productmix.command.CreateProductMixCommand;
47+
import org.apache.fineract.portfolio.loanproduct.productmix.command.DeleteProductMixCommand;
48+
import org.apache.fineract.portfolio.loanproduct.productmix.command.UpdateProductMixCommand;
4749
import org.apache.fineract.portfolio.loanproduct.productmix.data.ProductMixData;
50+
import org.apache.fineract.portfolio.loanproduct.productmix.data.ProductMixDeleteRequest;
4851
import org.apache.fineract.portfolio.loanproduct.productmix.data.ProductMixRequest;
52+
import org.apache.fineract.portfolio.loanproduct.productmix.data.ProductMixResponse;
4953
import org.apache.fineract.portfolio.loanproduct.productmix.service.ProductMixReadPlatformService;
5054
import org.apache.fineract.portfolio.loanproduct.service.LoanProductReadPlatformService;
5155
import org.springframework.stereotype.Component;
@@ -62,7 +66,7 @@ public class ProductMixApiResource {
6266
Arrays.asList("productId", "productName", "restrictedProducts", "allowedProducts", "productOptions"));
6367

6468
private final PlatformSecurityContext context;
65-
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
69+
private final CommandPipeline commandPipeline;
6670
private final ApiRequestParameterHelper apiRequestParameterHelper;
6771
private final DefaultToApiJsonSerializer<ProductMixData> toApiJsonSerializer;
6872

@@ -89,35 +93,41 @@ public String retrieveTemplate(@PathParam("productId") final Long productId, @Co
8993
@POST
9094
@Consumes({ MediaType.APPLICATION_JSON })
9195
@Produces({ MediaType.APPLICATION_JSON })
92-
public CommandProcessingResult createProductMix(@PathParam("productId") final Long productId,
93-
final ProductMixRequest productMixRequest) {
96+
public ProductMixResponse createProductMix(@PathParam("productId") final Long productId, @Valid final ProductMixRequest request) {
9497

95-
final CommandWrapper commandRequest = new CommandWrapperBuilder().createProductMix(productId)
96-
.withJson(toApiJsonSerializer.serialize(productMixRequest)).build();
98+
final var payload = new ProductMixRequest(productId, request.restrictedProducts());
9799

98-
return this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
100+
final var command = new CreateProductMixCommand();
101+
command.setPayload(payload);
102+
103+
final Supplier<ProductMixResponse> response = commandPipeline.send(command);
104+
return response.get();
99105
}
100106

101107
@PUT
102108
@Consumes({ MediaType.APPLICATION_JSON })
103109
@Produces({ MediaType.APPLICATION_JSON })
104-
public CommandProcessingResult updateProductMix(@PathParam("productId") final Long productId,
105-
final ProductMixRequest productMixRequest) {
110+
public ProductMixResponse updateProductMix(@PathParam("productId") final Long productId, @Valid final ProductMixRequest request) {
111+
112+
final var payload = new ProductMixRequest(productId, request.restrictedProducts());
106113

107-
final CommandWrapper commandRequest = new CommandWrapperBuilder().updateProductMix(productId)
108-
.withJson(toApiJsonSerializer.serialize(productMixRequest)).build();
114+
final var command = new UpdateProductMixCommand();
115+
command.setPayload(payload);
109116

110-
return this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
117+
final Supplier<ProductMixResponse> response = commandPipeline.send(command);
118+
return response.get();
111119
}
112120

113121
@DELETE
114122
@Consumes({ MediaType.APPLICATION_JSON })
115123
@Produces({ MediaType.APPLICATION_JSON })
116-
public CommandProcessingResult deleteProductMix(@PathParam("productId") final Long productId) {
124+
public ProductMixResponse deleteProductMix(@PathParam("productId") final Long productId) {
117125

118-
final CommandWrapper commandRequest = new CommandWrapperBuilder().deleteProductMix(productId).build();
126+
final var command = new DeleteProductMixCommand();
127+
command.setPayload(ProductMixDeleteRequest.builder().productId(productId).build());
119128

120-
return this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
129+
final Supplier<ProductMixResponse> response = commandPipeline.send(command);
130+
return response.get();
121131
}
122132

123133
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package org.apache.fineract.portfolio.loanproduct.productmix.command;
2+
3+
import lombok.Data;
4+
import lombok.EqualsAndHashCode;
5+
import org.apache.fineract.command.core.Command;
6+
import org.apache.fineract.portfolio.loanproduct.productmix.data.ProductMixRequest;
7+
8+
@Data
9+
@EqualsAndHashCode(callSuper = true)
10+
public class CreateProductMixCommand extends Command<ProductMixRequest> {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package org.apache.fineract.portfolio.loanproduct.productmix.command;
2+
3+
import lombok.Data;
4+
import lombok.EqualsAndHashCode;
5+
import org.apache.fineract.command.core.Command;
6+
import org.apache.fineract.portfolio.loanproduct.productmix.data.ProductMixDeleteRequest;
7+
8+
@Data
9+
@EqualsAndHashCode(callSuper = true)
10+
public class DeleteProductMixCommand extends Command<ProductMixDeleteRequest> {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package org.apache.fineract.portfolio.loanproduct.productmix.command;
2+
3+
import lombok.Data;
4+
import lombok.EqualsAndHashCode;
5+
import org.apache.fineract.command.core.Command;
6+
import org.apache.fineract.portfolio.loanproduct.productmix.data.ProductMixRequest;
7+
8+
@Data
9+
@EqualsAndHashCode(callSuper = true)
10+
public class UpdateProductMixCommand extends Command<ProductMixRequest> {}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package org.apache.fineract.portfolio.loanproduct.productmix.data;
2+
3+
import java.io.Serial;
4+
import java.io.Serializable;
5+
import lombok.Builder;
6+
7+
@Builder
8+
public record ProductMixDeleteRequest(Long productId) implements Serializable {
9+
10+
@Serial
11+
private static final long serialVersionUID = 1L;
12+
}

fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/productmix/data/ProductMixRequest.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,13 @@
1818
*/
1919
package org.apache.fineract.portfolio.loanproduct.productmix.data;
2020

21+
import jakarta.validation.constraints.NotNull;
22+
import jakarta.validation.constraints.Positive;
2123
import java.io.Serial;
2224
import java.io.Serializable;
2325
import java.util.List;
2426

25-
public record ProductMixRequest(List<Long> restrictedProducts) implements Serializable {
27+
public record ProductMixRequest(Long productId, @NotNull List<@NotNull @Positive Long> restrictedProducts) implements Serializable {
2628

2729
@Serial
2830
private static final long serialVersionUID = 1L;
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package org.apache.fineract.portfolio.loanproduct.productmix.data;
2+
3+
import java.io.Serial;
4+
import java.io.Serializable;
5+
import java.util.List;
6+
import java.util.Map;
7+
import lombok.Builder;
8+
9+
@Builder
10+
public record ProductMixResponse(Long productId, List<Long> restrictedProductsForMix, List<Long> removedProductsForMix,
11+
Map<String, Object> changes) implements Serializable {
12+
13+
@Serial
14+
private static final long serialVersionUID = 1L;
15+
}

fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/productmix/handler/CreateProductMixCommandHandler.java

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -18,32 +18,33 @@
1818
*/
1919
package org.apache.fineract.portfolio.loanproduct.productmix.handler;
2020

21-
import org.apache.fineract.commands.annotation.CommandType;
22-
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
23-
import org.apache.fineract.infrastructure.core.api.JsonCommand;
24-
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
21+
import io.github.resilience4j.retry.annotation.Retry;
22+
import lombok.RequiredArgsConstructor;
23+
import lombok.extern.slf4j.Slf4j;
24+
import org.apache.fineract.command.core.Command;
25+
import org.apache.fineract.command.core.CommandHandler;
26+
import org.apache.fineract.portfolio.loanproduct.productmix.data.ProductMixRequest;
27+
import org.apache.fineract.portfolio.loanproduct.productmix.data.ProductMixResponse;
2528
import org.apache.fineract.portfolio.loanproduct.productmix.service.ProductMixWritePlatformService;
26-
import org.springframework.beans.factory.annotation.Autowired;
27-
import org.springframework.stereotype.Service;
29+
import org.springframework.stereotype.Component;
2830
import org.springframework.transaction.annotation.Transactional;
2931

30-
@Service
31-
@CommandType(entity = "PRODUCTMIX", action = "CREATE")
32-
public class CreateProductMixCommandHandler implements NewCommandSourceHandler {
32+
@Slf4j
33+
@Component
34+
@RequiredArgsConstructor
35+
public class CreateProductMixCommandHandler implements CommandHandler<ProductMixRequest, ProductMixResponse> {
3336

34-
private final ProductMixWritePlatformService productMixWritePlatformService;
37+
private final ProductMixWritePlatformService writePlatformService;
3538

36-
@Autowired
37-
public CreateProductMixCommandHandler(final ProductMixWritePlatformService productMixWritePlatformService) {
38-
39-
this.productMixWritePlatformService = productMixWritePlatformService;
39+
@Retry(name = "commandCreateProductMix", fallbackMethod = "fallback")
40+
@Override
41+
@Transactional
42+
public ProductMixResponse handle(Command<ProductMixRequest> command) {
43+
return writePlatformService.createProductMix(command.getPayload());
4044
}
4145

42-
@Transactional
4346
@Override
44-
public CommandProcessingResult processCommand(final JsonCommand command) {
45-
46-
return this.productMixWritePlatformService.createProductMix(command.getProductId(), command);
47+
public ProductMixResponse fallback(Command<ProductMixRequest> command, Throwable t) {
48+
return CommandHandler.super.fallback(command, t);
4749
}
48-
4950
}

fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/productmix/handler/DeleteProductMixCommandHandler.java

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -18,32 +18,33 @@
1818
*/
1919
package org.apache.fineract.portfolio.loanproduct.productmix.handler;
2020

21-
import org.apache.fineract.commands.annotation.CommandType;
22-
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
23-
import org.apache.fineract.infrastructure.core.api.JsonCommand;
24-
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
21+
import io.github.resilience4j.retry.annotation.Retry;
22+
import lombok.RequiredArgsConstructor;
23+
import lombok.extern.slf4j.Slf4j;
24+
import org.apache.fineract.command.core.Command;
25+
import org.apache.fineract.command.core.CommandHandler;
26+
import org.apache.fineract.portfolio.loanproduct.productmix.data.ProductMixDeleteRequest;
27+
import org.apache.fineract.portfolio.loanproduct.productmix.data.ProductMixResponse;
2528
import org.apache.fineract.portfolio.loanproduct.productmix.service.ProductMixWritePlatformService;
26-
import org.springframework.beans.factory.annotation.Autowired;
27-
import org.springframework.stereotype.Service;
29+
import org.springframework.stereotype.Component;
2830
import org.springframework.transaction.annotation.Transactional;
2931

30-
@Service
31-
@CommandType(entity = "PRODUCTMIX", action = "DELETE")
32-
public class DeleteProductMixCommandHandler implements NewCommandSourceHandler {
32+
@Slf4j
33+
@Component
34+
@RequiredArgsConstructor
35+
public class DeleteProductMixCommandHandler implements CommandHandler<ProductMixDeleteRequest, ProductMixResponse> {
3336

34-
private final ProductMixWritePlatformService productMixWritePlatformService;
37+
private final ProductMixWritePlatformService writePlatformService;
3538

36-
@Autowired
37-
public DeleteProductMixCommandHandler(final ProductMixWritePlatformService productMixWritePlatformService) {
38-
39-
this.productMixWritePlatformService = productMixWritePlatformService;
39+
@Retry(name = "commandDeleteProductMix", fallbackMethod = "fallback")
40+
@Override
41+
@Transactional
42+
public ProductMixResponse handle(Command<ProductMixDeleteRequest> command) {
43+
return writePlatformService.deleteProductMix(command.getPayload());
4044
}
4145

42-
@Transactional
4346
@Override
44-
public CommandProcessingResult processCommand(final JsonCommand command) {
45-
46-
return this.productMixWritePlatformService.deleteProductMix(command.getProductId());
47+
public ProductMixResponse fallback(Command<ProductMixDeleteRequest> command, Throwable t) {
48+
return CommandHandler.super.fallback(command, t);
4749
}
48-
4950
}

fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/productmix/handler/UpdateProductMixCommandHandler.java

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -18,32 +18,33 @@
1818
*/
1919
package org.apache.fineract.portfolio.loanproduct.productmix.handler;
2020

21-
import org.apache.fineract.commands.annotation.CommandType;
22-
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
23-
import org.apache.fineract.infrastructure.core.api.JsonCommand;
24-
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
21+
import io.github.resilience4j.retry.annotation.Retry;
22+
import lombok.RequiredArgsConstructor;
23+
import lombok.extern.slf4j.Slf4j;
24+
import org.apache.fineract.command.core.Command;
25+
import org.apache.fineract.command.core.CommandHandler;
26+
import org.apache.fineract.portfolio.loanproduct.productmix.data.ProductMixRequest;
27+
import org.apache.fineract.portfolio.loanproduct.productmix.data.ProductMixResponse;
2528
import org.apache.fineract.portfolio.loanproduct.productmix.service.ProductMixWritePlatformService;
26-
import org.springframework.beans.factory.annotation.Autowired;
27-
import org.springframework.stereotype.Service;
29+
import org.springframework.stereotype.Component;
2830
import org.springframework.transaction.annotation.Transactional;
2931

30-
@Service
31-
@CommandType(entity = "PRODUCTMIX", action = "UPDATE")
32-
public class UpdateProductMixCommandHandler implements NewCommandSourceHandler {
32+
@Slf4j
33+
@Component
34+
@RequiredArgsConstructor
35+
public class UpdateProductMixCommandHandler implements CommandHandler<ProductMixRequest, ProductMixResponse> {
3336

34-
private final ProductMixWritePlatformService productMixWritePlatformService;
37+
private final ProductMixWritePlatformService writePlatformService;
3538

36-
@Autowired
37-
public UpdateProductMixCommandHandler(final ProductMixWritePlatformService productMixWritePlatformService) {
38-
39-
this.productMixWritePlatformService = productMixWritePlatformService;
39+
@Retry(name = "commandUpdateProductMix", fallbackMethod = "fallback")
40+
@Override
41+
@Transactional
42+
public ProductMixResponse handle(Command<ProductMixRequest> command) {
43+
return writePlatformService.updateProductMix(command.getPayload());
4044
}
4145

42-
@Transactional
4346
@Override
44-
public CommandProcessingResult processCommand(final JsonCommand command) {
45-
46-
return this.productMixWritePlatformService.updateProductMix(command.getProductId(), command);
47+
public ProductMixResponse fallback(Command<ProductMixRequest> command, Throwable t) {
48+
return CommandHandler.super.fallback(command, t);
4749
}
48-
4950
}

0 commit comments

Comments
 (0)