diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/api/ConfigureBusinessStepResource.java b/fineract-provider/src/main/java/org/apache/fineract/cob/api/ConfigureBusinessStepResource.java new file mode 100644 index 000000000..9febbfd9c --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/cob/api/ConfigureBusinessStepResource.java @@ -0,0 +1,122 @@ +/** + * 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.cob.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.Arrays; +import java.util.HashSet; +import java.util.Set; +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +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.cob.data.JobBusinessStepConfigData; +import org.apache.fineract.cob.data.JobBusinessStepDetail; +import org.apache.fineract.cob.service.ConfigJobParameterService; +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.springframework.stereotype.Component; + +@Path("/jobs") +@Component +@Tag(name = "Business Step Configuration", description = "") +@RequiredArgsConstructor +public class ConfigureBusinessStepResource { + + private static final Set BUSINESS_STEP_CONFIG_RESPONSE_DATA_PARAMETERS = new HashSet<>( + Arrays.asList("jobName", "businessSteps")); + private static final Set BUSINESS_STEP_DETAIL_RESPONSE_DATA_PARAMETERS = new HashSet<>( + Arrays.asList("jobName", "availableBusinessSteps")); + + private final DefaultToApiJsonSerializer businessStepConfigSerializeService; + private final DefaultToApiJsonSerializer businessStepDetailSerializeService; + private final ApiRequestParameterHelper apiRequestParameterHelper; + private final ConfigJobParameterService configJobParameterService; + private final PortfolioCommandSourceWritePlatformService commandWritePlatformService; + + @GET + @Path("{jobName}/steps") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + @Operation(summary = "List Business Step Configurations for a Job", description = "Returns the configured Business Steps for a job") + @ApiResponses({ + @ApiResponse(responseCode = "200", description = "OK", content = @Content(array = @ArraySchema(schema = @Schema(implementation = ConfigureBusinessStepResourceSwagger.GetBusinessStepConfigResponse.class)))) }) + public String retrieveAllConfiguredBusinessStep(@Context final UriInfo uriInfo, + @PathParam("jobName") @Parameter(description = "jobName") final String jobName) { + + JobBusinessStepConfigData jobBusinessStepConfigData = configJobParameterService.getBusinessStepConfigByJobName(jobName); + + final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters()); + return businessStepConfigSerializeService.serialize(settings, jobBusinessStepConfigData, + BUSINESS_STEP_CONFIG_RESPONSE_DATA_PARAMETERS); + } + + @PUT + @Path("{jobName}/steps") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + @Operation(summary = "List Business Step Configurations for a Job", description = "Updates the Business steps execution order for a job") + @RequestBody(content = @Content(schema = @Schema(implementation = ConfigureBusinessStepResourceSwagger.UpdateBusinessStepConfigRequest.class))) + @ApiResponses({ + @ApiResponse(responseCode = "204", description = "OK", content = @Content(array = @ArraySchema(schema = @Schema(implementation = ConfigureBusinessStepResourceSwagger.GetBusinessStepConfigResponse.class)))) }) + public String updateJobBusinessStepConfig(@PathParam("jobName") @Parameter(description = "jobName") final String jobName, + @Parameter(hidden = true) final String jsonRequestBody) { + + final CommandWrapper commandRequest = new CommandWrapperBuilder().updateBusinessStepConfig(jobName).withJson(jsonRequestBody) + .build(); + CommandProcessingResult result = commandWritePlatformService.logCommandSource(commandRequest); + return businessStepConfigSerializeService.serialize(result); + } + + @GET + @Path("{jobName}/available-steps") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + @Operation(summary = "List Business Step Configurations for a Job", description = "Returns the available Business Steps for a job") + @ApiResponses({ + @ApiResponse(responseCode = "200", description = "OK", content = @Content(array = @ArraySchema(schema = @Schema(implementation = ConfigureBusinessStepResourceSwagger.GetBusinessStepConfigResponse.class)))) }) + public String retrieveAllAvailableBusinessStep(@Context final UriInfo uriInfo, + @PathParam("jobName") @Parameter(description = "jobName") final String jobName) { + + JobBusinessStepDetail availableBusinessStepsByJobName = configJobParameterService.getAvailableBusinessStepsByJobName(jobName); + + final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters()); + return businessStepDetailSerializeService.serialize(settings, availableBusinessStepsByJobName, + BUSINESS_STEP_DETAIL_RESPONSE_DATA_PARAMETERS); + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/api/ConfigureBusinessStepResourceSwagger.java b/fineract-provider/src/main/java/org/apache/fineract/cob/api/ConfigureBusinessStepResourceSwagger.java new file mode 100644 index 000000000..e01a0884e --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/cob/api/ConfigureBusinessStepResourceSwagger.java @@ -0,0 +1,61 @@ +/** + * 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.cob.api; + +import io.swagger.v3.oas.annotations.media.Schema; +import java.util.List; + +final class ConfigureBusinessStepResourceSwagger { + + private ConfigureBusinessStepResourceSwagger() { + + } + + @Schema(description = "GetBusinessStepConfigResponse") + public static final class GetBusinessStepConfigResponse { + + private GetBusinessStepConfigResponse() {} + + @Schema(example = "CLOSE_OF_BUSINESS") + public String jobName; + public List businessSteps; + + } + + @Schema(description = "BusinessStep") + public static final class BusinessStep { + + private BusinessStep() {} + + @Schema(example = "APPLY_PENALTY_FOR_OVERDUE_LOANS") + public String stepName; + @Schema(example = "1") + public Long order; + + } + + @Schema(description = "UpdateBusinessStepConfigRequest") + public static final class UpdateBusinessStepConfigRequest { + + private UpdateBusinessStepConfigRequest() {} + + public List businessSteps; + + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/data/BusinessStep.java b/fineract-provider/src/main/java/org/apache/fineract/cob/data/BusinessStep.java new file mode 100644 index 000000000..17e9d6ca1 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/cob/data/BusinessStep.java @@ -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.cob.data; + +import lombok.Data; + +@Data +public class BusinessStep { + + private String stepName; + private Long order; +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/data/BusinessStepDetail.java b/fineract-provider/src/main/java/org/apache/fineract/cob/data/BusinessStepDetail.java new file mode 100644 index 000000000..4a3fbd855 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/cob/data/BusinessStepDetail.java @@ -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.cob.data; + +import lombok.Data; + +@Data +public class BusinessStepDetail { + + private String stepName; + private String stepDescription; +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/data/JobBusinessStepConfigData.java b/fineract-provider/src/main/java/org/apache/fineract/cob/data/JobBusinessStepConfigData.java new file mode 100644 index 000000000..65c803596 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/cob/data/JobBusinessStepConfigData.java @@ -0,0 +1,29 @@ +/** + * 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.cob.data; + +import java.util.List; +import lombok.Data; + +@Data +public class JobBusinessStepConfigData { + + private String jobName; + private List businessSteps; +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/data/JobBusinessStepDetail.java b/fineract-provider/src/main/java/org/apache/fineract/cob/data/JobBusinessStepDetail.java new file mode 100644 index 000000000..c77c73f92 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/cob/data/JobBusinessStepDetail.java @@ -0,0 +1,29 @@ +/** + * 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.cob.data; + +import java.util.List; +import lombok.Data; + +@Data +public class JobBusinessStepDetail { + + private String jobName; + private List availableBusinessSteps; +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/domain/BatchBusinessStep.java b/fineract-provider/src/main/java/org/apache/fineract/cob/domain/BatchBusinessStep.java index 7876e56fb..43b3511df 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/cob/domain/BatchBusinessStep.java +++ b/fineract-provider/src/main/java/org/apache/fineract/cob/domain/BatchBusinessStep.java @@ -23,6 +23,7 @@ import javax.persistence.Entity; import javax.persistence.Table; import lombok.Getter; import lombok.NoArgsConstructor; +import lombok.Setter; import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom; @Entity @@ -34,9 +35,11 @@ public class BatchBusinessStep extends AbstractPersistableCustom { @Column(name = "job_name", nullable = false) private String jobName; + @Setter @Column(name = "step_name", nullable = false) private String stepName; + @Setter @Column(name = "step_order", nullable = false) private Long stepOrder; diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/exceptions/BusinessStepNotBelongsToJobException.java b/fineract-provider/src/main/java/org/apache/fineract/cob/exceptions/BusinessStepNotBelongsToJobException.java new file mode 100644 index 000000000..34854bd30 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/cob/exceptions/BusinessStepNotBelongsToJobException.java @@ -0,0 +1,21 @@ +/** + * 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.cob.exceptions; + +public class BusinessStepNotBelongsToJobException extends RuntimeException {} diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/service/BusinessStepCategory.java b/fineract-provider/src/main/java/org/apache/fineract/cob/service/BusinessStepCategory.java new file mode 100644 index 000000000..b044e7dbd --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/cob/service/BusinessStepCategory.java @@ -0,0 +1,44 @@ +/** + * 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.cob.service; + +import java.util.Arrays; +import java.util.Optional; + +public enum BusinessStepCategory { + + LOAN("LOAN"); + + private final String name; + + BusinessStepCategory(String name) { + this.name = name; + } + + public static BusinessStepCategory getCategoryName(String categoryName) { + Optional optionalCategory = Arrays.stream(BusinessStepCategory.values()) + .filter(jn -> categoryName.equals(jn.name)).findAny(); + return optionalCategory.orElseThrow(() -> new IllegalArgumentException("Category not found by name: " + categoryName)); + } + + @Override + public String toString() { + return this.name; + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/service/BusinessStepCategoryService.java b/fineract-provider/src/main/java/org/apache/fineract/cob/service/BusinessStepCategoryService.java new file mode 100644 index 000000000..247e46af9 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/cob/service/BusinessStepCategoryService.java @@ -0,0 +1,26 @@ +/** + * 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.cob.service; + +import org.apache.fineract.cob.COBBusinessStep; + +public interface BusinessStepCategoryService { + + Class getBusinessStepByCategory(String category); +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/service/BusinessStepCategoryServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/cob/service/BusinessStepCategoryServiceImpl.java new file mode 100644 index 000000000..87f7b8964 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/cob/service/BusinessStepCategoryServiceImpl.java @@ -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.cob.service; + +import java.util.Map; +import org.apache.fineract.cob.COBBusinessStep; +import org.apache.fineract.cob.loan.LoanCOBBusinessStep; +import org.springframework.stereotype.Service; + +@Service +public class BusinessStepCategoryServiceImpl implements BusinessStepCategoryService { + + private final Map> businessSteps = Map.of(BusinessStepCategory.LOAN, + LoanCOBBusinessStep.class); + + @Override + public Class getBusinessStepByCategory(String category) { + Map.Entry> businessStepCategoryClassEntry = businessSteps.entrySet().stream() + .filter(businessStep -> businessStep.getKey().name().equals(category.toUpperCase())).findFirst().orElse(null); + return businessStepCategoryClassEntry != null ? businessStepCategoryClassEntry.getValue() : null; + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/service/BusinessStepConfigDataParser.java b/fineract-provider/src/main/java/org/apache/fineract/cob/service/BusinessStepConfigDataParser.java new file mode 100644 index 000000000..9c9a7b713 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/cob/service/BusinessStepConfigDataParser.java @@ -0,0 +1,64 @@ +/** + * 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.cob.service; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import java.util.ArrayList; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.apache.commons.lang3.StringUtils; +import org.apache.fineract.cob.data.BusinessStep; +import org.apache.fineract.infrastructure.core.api.JsonCommand; +import org.apache.fineract.infrastructure.core.exception.InvalidJsonException; +import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper; +import org.springframework.stereotype.Component; + +@Component +@RequiredArgsConstructor +public class BusinessStepConfigDataParser { + + private final FromJsonHelper jsonHelper; + + public List parseUpdate(JsonCommand command) { + JsonObject element = extractJsonObject(command); + List businessSteps = new ArrayList<>(); + JsonArray jsonArray = jsonHelper.extractJsonArrayNamed("businessSteps", element); + for (final JsonElement businessStepConfig : jsonArray) { + final String stepName = jsonHelper.extractStringNamed("stepName", businessStepConfig); + final Long order = jsonHelper.extractLongNamed("order", businessStepConfig); + BusinessStep businessStep = new BusinessStep(); + businessStep.setStepName(stepName); + businessStep.setOrder(order); + businessSteps.add(businessStep); + } + return businessSteps; + } + + private JsonObject extractJsonObject(JsonCommand command) { + String json = command.json(); + if (StringUtils.isBlank(json)) { + throw new InvalidJsonException(); + } + + final JsonElement element = jsonHelper.parse(json); + return element.getAsJsonObject(); + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/service/BusinessStepConfigUpdateHandler.java b/fineract-provider/src/main/java/org/apache/fineract/cob/service/BusinessStepConfigUpdateHandler.java new file mode 100644 index 000000000..a59199179 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/cob/service/BusinessStepConfigUpdateHandler.java @@ -0,0 +1,48 @@ +/** + * 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.cob.service; + +import com.google.common.base.Splitter; +import java.util.List; +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.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@RequiredArgsConstructor +@Service +@CommandType(entity = "BATCH_BUSINESS_STEP", action = "UPDATE") +public class BusinessStepConfigUpdateHandler implements NewCommandSourceHandler { + + private final ConfigJobParameterService configJobParameterService; + + @Override + @Transactional + public CommandProcessingResult processCommand(JsonCommand command) { + List split = Splitter.on("/").splitToList(command.getUrl()); + String jobName = split.get(split.size() - 2); + if ("null".equals(jobName)) { + jobName = null; + } + return configJobParameterService.updateStepConfigByJobName(command, jobName); + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/service/BusinessStepMapper.java b/fineract-provider/src/main/java/org/apache/fineract/cob/service/BusinessStepMapper.java new file mode 100644 index 000000000..030c29e7e --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/cob/service/BusinessStepMapper.java @@ -0,0 +1,35 @@ +/** + * 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.cob.service; + +import java.util.List; +import org.apache.fineract.cob.data.BusinessStep; +import org.apache.fineract.cob.domain.BatchBusinessStep; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.Mappings; + +@Mapper(componentModel = "spring") +public interface BusinessStepMapper { + + @Mappings({ @Mapping(target = "order", source = "source.stepOrder") }) + BusinessStep map(BatchBusinessStep source); + + List map(List source); +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/service/ConfigJobParameterService.java b/fineract-provider/src/main/java/org/apache/fineract/cob/service/ConfigJobParameterService.java new file mode 100644 index 000000000..25e082a34 --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/cob/service/ConfigJobParameterService.java @@ -0,0 +1,33 @@ +/** + * 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.cob.service; + +import org.apache.fineract.cob.data.JobBusinessStepConfigData; +import org.apache.fineract.cob.data.JobBusinessStepDetail; +import org.apache.fineract.infrastructure.core.api.JsonCommand; +import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; + +public interface ConfigJobParameterService { + + JobBusinessStepConfigData getBusinessStepConfigByJobName(String jobName); + + CommandProcessingResult updateStepConfigByJobName(JsonCommand command, String jobName); + + JobBusinessStepDetail getAvailableBusinessStepsByJobName(String jobName); +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/service/ConfigJobParameterServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/cob/service/ConfigJobParameterServiceImpl.java new file mode 100644 index 000000000..71c87911b --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/cob/service/ConfigJobParameterServiceImpl.java @@ -0,0 +1,94 @@ +/** + * 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.cob.service; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.apache.fineract.cob.COBBusinessStep; +import org.apache.fineract.cob.data.BusinessStep; +import org.apache.fineract.cob.data.BusinessStepDetail; +import org.apache.fineract.cob.data.JobBusinessStepConfigData; +import org.apache.fineract.cob.data.JobBusinessStepDetail; +import org.apache.fineract.cob.domain.BatchBusinessStep; +import org.apache.fineract.cob.domain.BatchBusinessStepRepository; +import org.apache.fineract.cob.exceptions.BusinessStepNotBelongsToJobException; +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.springframework.context.ApplicationContext; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class ConfigJobParameterServiceImpl implements ConfigJobParameterService { + + private final BatchBusinessStepRepository batchBusinessStepRepository; + private final BusinessStepConfigDataParser dataParser; + private final BusinessStepCategoryService businessStepCategoryService; + private final ApplicationContext applicationContext; + private final BusinessStepMapper mapper; + + @Override + public JobBusinessStepConfigData getBusinessStepConfigByJobName(String jobName) { + List batchBusinessSteps = batchBusinessStepRepository.findAllByJobName(jobName); + JobBusinessStepConfigData jobBusinessStepConfigData = new JobBusinessStepConfigData(); + jobBusinessStepConfigData.setJobName(jobName); + jobBusinessStepConfigData.setBusinessSteps(mapper.map(batchBusinessSteps)); + return jobBusinessStepConfigData; + } + + @Override + public CommandProcessingResult updateStepConfigByJobName(JsonCommand command, String jobName) + throws BusinessStepNotBelongsToJobException { + List businessSteps = dataParser.parseUpdate(command); + List batchBusinessSteps = batchBusinessStepRepository.findAllByJobName(jobName); + businessSteps.forEach(newBusinessStepConfig -> { + BatchBusinessStep batchBusinessStep = batchBusinessSteps.stream() + .filter(oldBusinessStepConfig -> oldBusinessStepConfig.getStepName().equals(newBusinessStepConfig.getStepName())) + .findFirst().orElseThrow(BusinessStepNotBelongsToJobException::new); + batchBusinessStep.setStepName(newBusinessStepConfig.getStepName()); + batchBusinessStep.setStepOrder(newBusinessStepConfig.getOrder()); + batchBusinessStepRepository.save(batchBusinessStep); + }); + return new CommandProcessingResultBuilder().withCommandId(command.commandId()).build(); + } + + @Override + public JobBusinessStepDetail getAvailableBusinessStepsByJobName(String jobName) { + Class businessStepClass = businessStepCategoryService.getBusinessStepByCategory(jobName); + if (businessStepClass == null) { + return null; + } + List businessStepBeanNames = Arrays.stream(applicationContext.getBeanNamesForType(businessStepClass)).toList(); + JobBusinessStepDetail jobBusinessStepDetail = new JobBusinessStepDetail(); + List availableBusinessSteps = new ArrayList<>(); + for (String businessStepBean : businessStepBeanNames) { + COBBusinessStep businessStep = (COBBusinessStep) applicationContext.getBean(businessStepBean); + BusinessStepDetail businessStepDetail = new BusinessStepDetail(); + businessStepDetail.setStepName(businessStep.getEnumStyledName()); + businessStepDetail.setStepDescription(businessStep.getHumanReadableName()); + availableBusinessSteps.add(businessStepDetail); + } + jobBusinessStepDetail.setJobName(jobName); + jobBusinessStepDetail.setAvailableBusinessSteps(availableBusinessSteps); + return jobBusinessStepDetail; + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java b/fineract-provider/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java index 2612ae931..952da0cec 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java +++ b/fineract-provider/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java @@ -3549,4 +3549,11 @@ public class CommandWrapperBuilder { return this; } + public CommandWrapperBuilder updateBusinessStepConfig(String jobName) { + this.actionName = "UPDATE"; + this.entityName = "BATCH_BUSINESS_STEP"; + this.href = "/jobs/" + jobName + "/steps"; + return this; + } + } diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/changelog-tenant.xml b/fineract-provider/src/main/resources/db/changelog/tenant/changelog-tenant.xml index 206e4d4bf..1630472f8 100644 --- a/fineract-provider/src/main/resources/db/changelog/tenant/changelog-tenant.xml +++ b/fineract-provider/src/main/resources/db/changelog/tenant/changelog-tenant.xml @@ -60,4 +60,5 @@ + diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/parts/0041_add_update_business_step_permission.xml b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0041_add_update_business_step_permission.xml new file mode 100644 index 000000000..2b0d2565b --- /dev/null +++ b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0041_add_update_business_step_permission.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + diff --git a/fineract-provider/src/test/java/org/apache/fineract/cob/service/BusinessStepConfigUpdateHandlerTest.java b/fineract-provider/src/test/java/org/apache/fineract/cob/service/BusinessStepConfigUpdateHandlerTest.java new file mode 100644 index 000000000..c20ab8948 --- /dev/null +++ b/fineract-provider/src/test/java/org/apache/fineract/cob/service/BusinessStepConfigUpdateHandlerTest.java @@ -0,0 +1,80 @@ +/** + * 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.cob.service; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +import org.apache.fineract.infrastructure.core.api.JsonCommand; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.junit.jupiter.MockitoSettings; +import org.mockito.quality.Strictness; + +@ExtendWith(MockitoExtension.class) +@MockitoSettings(strictness = Strictness.LENIENT) +class BusinessStepConfigUpdateHandlerTest { + + @InjectMocks + private BusinessStepConfigUpdateHandler testObj; + + @Mock + private ConfigJobParameterService configJobParameterService; + + @Captor + private ArgumentCaptor argumentCaptor; + + @Test + void shouldProcessCommandGetsJobName() { + JsonCommand command = mock(JsonCommand.class); + given(command.getUrl()).willReturn("/jobs/jobName/steps"); + testObj.processCommand(command); + + verify(configJobParameterService).updateStepConfigByJobName(eq(command), argumentCaptor.capture()); + assertEquals("jobName", argumentCaptor.getValue()); + } + + @Test + void shouldProcessCommandGetsJobNameEmptyString() { + JsonCommand command = mock(JsonCommand.class); + given(command.getUrl()).willReturn("/jobs//steps"); + testObj.processCommand(command); + + verify(configJobParameterService).updateStepConfigByJobName(eq(command), argumentCaptor.capture()); + assertEquals("", argumentCaptor.getValue()); + } + + @Test + void shouldProcessCommandGetsJobNameNull() { + JsonCommand command = mock(JsonCommand.class); + given(command.getUrl()).willReturn("/jobs/" + null + "/steps"); + testObj.processCommand(command); + + verify(configJobParameterService).updateStepConfigByJobName(eq(command), argumentCaptor.capture()); + assertEquals(null, argumentCaptor.getValue()); + } +} diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/BusinessConfigurationApiTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/BusinessConfigurationApiTest.java new file mode 100644 index 000000000..0e10b2253 --- /dev/null +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/BusinessConfigurationApiTest.java @@ -0,0 +1,112 @@ +/** + * 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.assertTrue; + +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 java.util.List; +import org.apache.fineract.cob.data.BusinessStep; +import org.apache.fineract.cob.data.JobBusinessStepConfigData; +import org.apache.fineract.cob.data.JobBusinessStepDetail; +import org.apache.fineract.integrationtests.common.BusinessStepConfigurationHelper; +import org.apache.fineract.integrationtests.common.Utils; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +public class BusinessConfigurationApiTest { + + private ResponseSpecification responseSpec; + private RequestSpecification requestSpec; + private static final String LOAN_JOB_NAME = "LOAN_CLOSE_OF_BUSINESS"; + private static final String LOAN_CATEGORY_NAME = "loan"; + private static final String APPLY_CHARGE_TO_OVERDUE_LOANS = "APPLY_CHARGE_TO_OVERDUE_LOANS"; + + @BeforeEach + public void setup() { + Utils.initializeRESTAssured(); + this.requestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build(); + this.requestSpec.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey()); + this.responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build(); + } + + @Test + public void shouldReturnApplyChargeToOverdueLoanStepConfig() { + JobBusinessStepConfigData response = BusinessStepConfigurationHelper.getConfiguredBusinessStepsByJobName(requestSpec, responseSpec, + LOAN_JOB_NAME); + + Assertions.assertNotNull(response); + assertEquals(LOAN_JOB_NAME, response.getJobName()); + assertTrue(response.getBusinessSteps().size() > 0); + assertTrue(response.getBusinessSteps().stream() + .anyMatch(businessStep -> APPLY_CHARGE_TO_OVERDUE_LOANS.equals(businessStep.getStepName()))); + } + + @Test + public void shouldReturnApplyChargeToOverdueLoanStepConfigByJobCategory() { + JobBusinessStepDetail response = BusinessStepConfigurationHelper.getAvailableBusinessStepsByJobName(requestSpec, responseSpec, + LOAN_CATEGORY_NAME); + + Assertions.assertNotNull(response); + assertEquals(LOAN_CATEGORY_NAME, response.getJobName()); + assertTrue(response.getAvailableBusinessSteps().size() > 0); + assertTrue(response.getAvailableBusinessSteps().stream() + .anyMatch(businessStep -> APPLY_CHARGE_TO_OVERDUE_LOANS.equals(businessStep.getStepName()))); + } + + @Test + public void shouldUpdateStepOrder() { + JobBusinessStepConfigData originalStepConfig = BusinessStepConfigurationHelper.getConfiguredBusinessStepsByJobName(requestSpec, + responseSpec, LOAN_JOB_NAME); + Long originalOrder = originalStepConfig.getBusinessSteps().stream() // + .filter(businessStep -> APPLY_CHARGE_TO_OVERDUE_LOANS.equals(businessStep.getStepName())) // + .findFirst().get().getOrder(); + + List requestBody = getBusinessSteps(originalOrder + 1); + BusinessStepConfigurationHelper.updateBusinessStepOrder(requestSpec, responseSpec, LOAN_JOB_NAME, + BusinessStepConfigurationHelper.toJsonString(requestBody)); + + JobBusinessStepConfigData newStepConfig = BusinessStepConfigurationHelper.getConfiguredBusinessStepsByJobName(requestSpec, + responseSpec, LOAN_JOB_NAME); + Long newOrder = newStepConfig.getBusinessSteps().stream() // + .filter(businessStep -> APPLY_CHARGE_TO_OVERDUE_LOANS.equals(businessStep.getStepName())) // + .findFirst().get().getOrder(); + assertEquals(originalOrder + 1, newOrder); + + List originalBusinessSteps = getBusinessSteps(originalOrder); + BusinessStepConfigurationHelper.updateBusinessStepOrder(requestSpec, responseSpec, LOAN_JOB_NAME, + BusinessStepConfigurationHelper.toJsonString(originalBusinessSteps)); + } + + private List getBusinessSteps(Long order) { + List businessSteps = new ArrayList<>(); + BusinessStep businessStep = new BusinessStep(); + businessStep.setStepName(APPLY_CHARGE_TO_OVERDUE_LOANS); + businessStep.setOrder(order); + businessSteps.add(businessStep); + return businessSteps; + } +} diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/BusinessStepConfigurationHelper.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/BusinessStepConfigurationHelper.java new file mode 100644 index 000000000..151f15791 --- /dev/null +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/BusinessStepConfigurationHelper.java @@ -0,0 +1,85 @@ +/** + * 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; + +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import io.restassured.specification.RequestSpecification; +import io.restassured.specification.ResponseSpecification; +import java.util.List; +import lombok.extern.slf4j.Slf4j; +import org.apache.fineract.cob.data.BusinessStep; +import org.apache.fineract.cob.data.JobBusinessStepConfigData; +import org.apache.fineract.cob.data.JobBusinessStepDetail; + +@Slf4j +public final class BusinessStepConfigurationHelper { + + private static final String BUSINESS_STEPS_API_URL_START = "/fineract-provider/api/v1/jobs/"; + private static final String BUSINESS_STEPS_API_URL_END = "/steps?" + Utils.TENANT_IDENTIFIER; + private static final String GET_AVAILABLE_BUSINESS_STEPS_API_URL_END = "/available-steps?" + Utils.TENANT_IDENTIFIER; + + private BusinessStepConfigurationHelper() { + + } + + public static String toJsonString(final List batchRequests) { + return new Gson().toJson(new BusinessStepWrapper(batchRequests)); + } + + private static JobBusinessStepConfigData configuredBusinessStepFromJsonString(final String json) { + return new Gson().fromJson(json, new TypeToken() {}.getType()); + } + + private static JobBusinessStepDetail availableBusinessStepFromJsonString(final String json) { + return new Gson().fromJson(json, new TypeToken() {}.getType()); + } + + public static JobBusinessStepConfigData getConfiguredBusinessStepsByJobName(final RequestSpecification requestSpec, + final ResponseSpecification responseSpec, String jobName) { + final String response = Utils.performServerGet(requestSpec, responseSpec, + BUSINESS_STEPS_API_URL_START + jobName + BUSINESS_STEPS_API_URL_END); + log.info("BusinessStepConfigurationHelper Response: {}", response); + return BusinessStepConfigurationHelper.configuredBusinessStepFromJsonString(response); + } + + public static JobBusinessStepDetail getAvailableBusinessStepsByJobName(final RequestSpecification requestSpec, + final ResponseSpecification responseSpec, String jobName) { + final String response = Utils.performServerGet(requestSpec, responseSpec, + BUSINESS_STEPS_API_URL_START + jobName + GET_AVAILABLE_BUSINESS_STEPS_API_URL_END); + log.info("BusinessStepConfigurationHelper Response: {}", response); + return BusinessStepConfigurationHelper.availableBusinessStepFromJsonString(response); + } + + public static void updateBusinessStepOrder(final RequestSpecification requestSpec, final ResponseSpecification responseSpec, + String jobName, String jsonBodyToSend) { + String response = Utils.performServerPut(requestSpec, responseSpec, + BUSINESS_STEPS_API_URL_START + jobName + BUSINESS_STEPS_API_URL_END, jsonBodyToSend); + log.info("BusinessStepConfigurationHelper Response: {}", response); + } + + private static final class BusinessStepWrapper { + + private List businessSteps; + + private BusinessStepWrapper(List businessSteps) { + this.businessSteps = businessSteps; + } + } +}