From 95c2b2675de43a11be670042ecb657a6a2f8ba98 Mon Sep 17 00:00:00 2001 From: Giampiero Ferrara Date: Wed, 15 Jan 2025 15:50:43 +0100 Subject: [PATCH] Added new endpoint into OnboardingController --- apps/onboarding-ms/src/main/docs/openapi.json | 85 ++++++++++++ apps/onboarding-ms/src/main/docs/openapi.yaml | 62 +++++++++ .../controller/OnboardingController.java | 50 +++++-- .../OnboardingAggregationImportRequest.java | 16 +++ .../onboarding/service/OnboardingService.java | 7 +- .../service/OnboardingServiceDefault.java | 131 ++++++++++-------- 6 files changed, 284 insertions(+), 67 deletions(-) create mode 100644 apps/onboarding-ms/src/main/java/it/pagopa/selfcare/onboarding/entity/OnboardingAggregationImportRequest.java diff --git a/apps/onboarding-ms/src/main/docs/openapi.json b/apps/onboarding-ms/src/main/docs/openapi.json index 894114b50..e0378c721 100644 --- a/apps/onboarding-ms/src/main/docs/openapi.json +++ b/apps/onboarding-ms/src/main/docs/openapi.json @@ -449,6 +449,44 @@ } ] } }, + "/v1/onboarding/aggregation/import" : { + "post" : { + "tags" : [ "Onboarding Controller" ], + "summary" : "Asynchronously import aggregated onboarding to COMPLETED status and create token", + "description" : "Perform a manual onboarding with aggregator, create token and set onboarding status to COMPLETED phase.", + "operationId" : "onboardingAggregationImport", + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/OnboardingAggregationImportRequest" + } + } + } + }, + "responses" : { + "200" : { + "description" : "OK", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/OnboardingResponse" + } + } + } + }, + "401" : { + "description" : "Not Authorized" + }, + "403" : { + "description" : "Not Allowed" + } + }, + "security" : [ { + "SecurityScheme" : [ ] + } ] + } + }, "/v1/onboarding/aggregation/increment" : { "post" : { "tags" : [ "Onboarding Controller" ], @@ -2356,6 +2394,53 @@ "type" : "string", "example" : "2022-03-10T12:15:50" }, + "OnboardingAggregationImportRequest" : { + "required" : [ "productId", "users", "institution" ], + "type" : "object", + "properties" : { + "productId" : { + "minLength" : 1, + "type" : "string" + }, + "users" : { + "minItems" : 1, + "type" : "array", + "items" : { + "$ref" : "#/components/schemas/UserRequest" + } + }, + "aggregates" : { + "type" : "array", + "items" : { + "$ref" : "#/components/schemas/AggregateInstitutionRequest" + } + }, + "isAggregator" : { + "type" : "boolean" + }, + "pricingPlan" : { + "type" : "string" + }, + "signContract" : { + "type" : "boolean" + }, + "institution" : { + "$ref" : "#/components/schemas/InstitutionBaseRequest" + }, + "billing" : { + "$ref" : "#/components/schemas/BillingRequest" + }, + "additionalInformations" : { + "$ref" : "#/components/schemas/AdditionalInformationsDto" + }, + "gpuData" : { + "$ref" : "#/components/schemas/GPUData" + }, + "onboardingImportContract" : { + "$ref" : "#/components/schemas/OnboardingImportContract" + } + } + }, "OnboardingDefaultRequest" : { "required" : [ "productId", "users", "institution" ], "type" : "object", diff --git a/apps/onboarding-ms/src/main/docs/openapi.yaml b/apps/onboarding-ms/src/main/docs/openapi.yaml index 46679ea32..73e6994ed 100644 --- a/apps/onboarding-ms/src/main/docs/openapi.yaml +++ b/apps/onboarding-ms/src/main/docs/openapi.yaml @@ -326,6 +326,33 @@ paths: description: Not Allowed security: - SecurityScheme: [] + /v1/onboarding/aggregation/import: + post: + tags: + - Onboarding Controller + summary: Asynchronously import aggregated onboarding to COMPLETED status and + create token + description: "Perform a manual onboarding with aggregator, create token and\ + \ set onboarding status to COMPLETED phase." + operationId: onboardingAggregationImport + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/OnboardingAggregationImportRequest" + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: "#/components/schemas/OnboardingResponse" + "401": + description: Not Authorized + "403": + description: Not Allowed + security: + - SecurityScheme: [] /v1/onboarding/aggregation/increment: post: tags: @@ -1712,6 +1739,41 @@ components: format: date-time type: string example: 2022-03-10T12:15:50 + OnboardingAggregationImportRequest: + required: + - productId + - users + - institution + type: object + properties: + productId: + minLength: 1 + type: string + users: + minItems: 1 + type: array + items: + $ref: "#/components/schemas/UserRequest" + aggregates: + type: array + items: + $ref: "#/components/schemas/AggregateInstitutionRequest" + isAggregator: + type: boolean + pricingPlan: + type: string + signContract: + type: boolean + institution: + $ref: "#/components/schemas/InstitutionBaseRequest" + billing: + $ref: "#/components/schemas/BillingRequest" + additionalInformations: + $ref: "#/components/schemas/AdditionalInformationsDto" + gpuData: + $ref: "#/components/schemas/GPUData" + onboardingImportContract: + $ref: "#/components/schemas/OnboardingImportContract" OnboardingDefaultRequest: required: - productId diff --git a/apps/onboarding-ms/src/main/java/it/pagopa/selfcare/onboarding/controller/OnboardingController.java b/apps/onboarding-ms/src/main/java/it/pagopa/selfcare/onboarding/controller/OnboardingController.java index 83fa4ef66..b8055f549 100644 --- a/apps/onboarding-ms/src/main/java/it/pagopa/selfcare/onboarding/controller/OnboardingController.java +++ b/apps/onboarding-ms/src/main/java/it/pagopa/selfcare/onboarding/controller/OnboardingController.java @@ -1,5 +1,7 @@ package it.pagopa.selfcare.onboarding.controller; +import static it.pagopa.selfcare.onboarding.util.Utils.retrieveContractFromFormData; + import io.quarkus.security.Authenticated; import io.quarkus.security.identity.CurrentIdentityAssociation; import io.smallrye.jwt.auth.principal.DefaultJWTCallerPrincipal; @@ -7,13 +9,22 @@ import it.pagopa.selfcare.onboarding.common.OnboardingStatus; import it.pagopa.selfcare.onboarding.common.WorkflowType; import it.pagopa.selfcare.onboarding.constants.CustomError; -import it.pagopa.selfcare.onboarding.controller.request.*; +import it.pagopa.selfcare.onboarding.controller.request.OnboardingDefaultRequest; +import it.pagopa.selfcare.onboarding.controller.request.OnboardingImportPspRequest; +import it.pagopa.selfcare.onboarding.controller.request.OnboardingImportRequest; +import it.pagopa.selfcare.onboarding.controller.request.OnboardingPaRequest; +import it.pagopa.selfcare.onboarding.controller.request.OnboardingPgRequest; +import it.pagopa.selfcare.onboarding.controller.request.OnboardingPspRequest; +import it.pagopa.selfcare.onboarding.controller.request.OnboardingUserPgRequest; +import it.pagopa.selfcare.onboarding.controller.request.OnboardingUserRequest; +import it.pagopa.selfcare.onboarding.controller.request.ReasonRequest; import it.pagopa.selfcare.onboarding.controller.response.OnboardingGet; import it.pagopa.selfcare.onboarding.controller.response.OnboardingGetResponse; import it.pagopa.selfcare.onboarding.controller.response.OnboardingResponse; import it.pagopa.selfcare.onboarding.entity.Billing; import it.pagopa.selfcare.onboarding.entity.CheckManagerResponse; import it.pagopa.selfcare.onboarding.entity.Onboarding; +import it.pagopa.selfcare.onboarding.entity.OnboardingAggregationImportRequest; import it.pagopa.selfcare.onboarding.exception.ResourceNotFoundException; import it.pagopa.selfcare.onboarding.mapper.OnboardingMapper; import it.pagopa.selfcare.onboarding.model.OnboardingGetFilters; @@ -22,11 +33,24 @@ import jakarta.inject.Inject; import jakarta.validation.Valid; import jakarta.validation.constraints.NotNull; -import jakarta.ws.rs.*; +import jakarta.ws.rs.Consumes; +import jakarta.ws.rs.DefaultValue; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.HEAD; +import jakarta.ws.rs.InternalServerErrorException; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.PUT; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.PathParam; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.QueryParam; import jakarta.ws.rs.core.Context; import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; import jakarta.ws.rs.core.SecurityContext; +import java.io.File; +import java.util.List; +import java.util.Objects; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.http.HttpStatus; @@ -36,12 +60,6 @@ import org.jboss.resteasy.reactive.RestForm; import org.jboss.resteasy.reactive.server.core.ResteasyReactiveRequestContext; -import java.io.File; -import java.util.List; -import java.util.Objects; - -import static it.pagopa.selfcare.onboarding.util.Utils.retrieveContractFromFormData; - @Authenticated @Path("/v1/onboarding") @Tag(name = "Onboarding Controller") @@ -567,4 +585,20 @@ public Uni checkRecipientCode(@QueryParam("recipientCode") return RecipientCodeStatus.ACCEPTED; }); } + + @Operation( + summary = "Asynchronously import aggregated onboarding to COMPLETED status and create token", + description = "Perform a manual onboarding with aggregator, create token and set onboarding status to COMPLETED phase." + ) + @Path("/aggregation/import") + @POST + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Uni onboardingAggregationImport(@Valid OnboardingAggregationImportRequest onboardingRequest, + @Context SecurityContext ctx) { + return readUserIdFromToken(ctx) + .onItem().transformToUni(userId -> onboardingService + .onboardingAggregationImport(fillUserId(onboardingMapper.toEntity(onboardingRequest), userId), + onboardingRequest.getOnboardingImportContract(), onboardingRequest.getUsers(), onboardingRequest.getAggregates())); + } } diff --git a/apps/onboarding-ms/src/main/java/it/pagopa/selfcare/onboarding/entity/OnboardingAggregationImportRequest.java b/apps/onboarding-ms/src/main/java/it/pagopa/selfcare/onboarding/entity/OnboardingAggregationImportRequest.java new file mode 100644 index 000000000..eb7181f65 --- /dev/null +++ b/apps/onboarding-ms/src/main/java/it/pagopa/selfcare/onboarding/entity/OnboardingAggregationImportRequest.java @@ -0,0 +1,16 @@ +package it.pagopa.selfcare.onboarding.entity; + +import it.pagopa.selfcare.onboarding.controller.request.OnboardingDefaultRequest; +import it.pagopa.selfcare.onboarding.controller.request.OnboardingImportContract; +import jakarta.validation.Valid; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Data +@EqualsAndHashCode(callSuper = true) +public class OnboardingAggregationImportRequest extends OnboardingDefaultRequest { + + @Valid + private OnboardingImportContract onboardingImportContract; +} + diff --git a/apps/onboarding-ms/src/main/java/it/pagopa/selfcare/onboarding/service/OnboardingService.java b/apps/onboarding-ms/src/main/java/it/pagopa/selfcare/onboarding/service/OnboardingService.java index 488be2e3a..0b41dcca5 100644 --- a/apps/onboarding-ms/src/main/java/it/pagopa/selfcare/onboarding/service/OnboardingService.java +++ b/apps/onboarding-ms/src/main/java/it/pagopa/selfcare/onboarding/service/OnboardingService.java @@ -15,7 +15,6 @@ import it.pagopa.selfcare.onboarding.entity.Onboarding; import it.pagopa.selfcare.onboarding.model.FormItem; import it.pagopa.selfcare.onboarding.model.OnboardingGetFilters; - import java.util.List; public interface OnboardingService { @@ -45,6 +44,12 @@ Uni onboardingAggregationCompletion( List userRequests, List aggregates); + Uni onboardingAggregationImport( + Onboarding onboarding, + OnboardingImportContract contractImported, + List userRequests, + List aggregates); + Uni onboardingUserPg(Onboarding onboarding, List userRequests); Uni approve(String onboardingId); diff --git a/apps/onboarding-ms/src/main/java/it/pagopa/selfcare/onboarding/service/OnboardingServiceDefault.java b/apps/onboarding-ms/src/main/java/it/pagopa/selfcare/onboarding/service/OnboardingServiceDefault.java index 989b52f40..1e3e28e37 100644 --- a/apps/onboarding-ms/src/main/java/it/pagopa/selfcare/onboarding/service/OnboardingServiceDefault.java +++ b/apps/onboarding-ms/src/main/java/it/pagopa/selfcare/onboarding/service/OnboardingServiceDefault.java @@ -290,18 +290,32 @@ public Uni onboardingAggregationCompletion( return fillUsersAndOnboarding(onboarding, userRequests, aggregates, null, false); } + @Override + public Uni onboardingAggregationImport( + Onboarding onboarding, + OnboardingImportContract contractImported, + List userRequests, + List aggregates) { + onboarding.setWorkflowType(WorkflowType.CONTRACT_REGISTRATION_AGGREGATOR); + onboarding.setStatus(OnboardingStatus.PENDING); + + return fillUsersAndOnboardingForImport( + onboarding, userRequests, aggregates, contractImported, TIMEOUT_ORCHESTRATION_RESPONSE, false); + } + + /** * As onboarding but it is specific for IMPORT workflow */ @Override public Uni onboardingImport( - Onboarding onboarding, - List userRequests, - OnboardingImportContract contractImported, boolean forceImport) { + Onboarding onboarding, + List userRequests, + OnboardingImportContract contractImported, boolean forceImport) { onboarding.setWorkflowType(WorkflowType.IMPORT); onboarding.setStatus(OnboardingStatus.PENDING); return fillUsersAndOnboardingForImport( - onboarding, userRequests, contractImported, TIMEOUT_ORCHESTRATION_RESPONSE, forceImport); + onboarding, userRequests, null, contractImported, TIMEOUT_ORCHESTRATION_RESPONSE, forceImport); } /** @@ -438,65 +452,66 @@ private Uni verifyExistingOnboarding( } /** - * @param timeout The orchestration instances will try complete within the defined timeout and the - * response is delivered synchronously. If is null the timeout is default 1 sec and the - * response is delivered asynchronously + * @param timeout The orchestration instances will try complete within the defined timeout and the response is delivered synchronously. If is null + * the timeout is default 1 sec and the response is delivered asynchronously */ private Uni fillUsersAndOnboardingForImport( - Onboarding onboarding, - List userRequests, - OnboardingImportContract contractImported, - String timeout, boolean forceImport) { + Onboarding onboarding, + List userRequests, + List aggregateRequests, + OnboardingImportContract contractImported, + String timeout, boolean forceImport) { + onboarding.setCreatedAt(LocalDateTime.now()); return getProductByOnboarding(onboarding) - .onItem() - .transformToUni( - product -> - verifyAlreadyOnboardingForProductAndProductParent( - onboarding.getInstitution(), product.getId(), product.getParentId()) - .replaceWith(product)) - .onItem() - .transformToUni( - product -> - Uni.createFrom() - .item(registryResourceFactory.create(onboarding, getManagerTaxCode(userRequests))) - .onItem() - .invoke( - registryManager -> - registryManager.setResource(registryManager.retrieveInstitution())) - .runSubscriptionOn(Infrastructure.getDefaultWorkerPool()) - .onItem() - .transformToUni( - registryManager -> - registryManager - .isValid() - .onItem() - .transformToUni( - ignored -> registryManager.customValidation(product))) - /* if product has some test environments, request must also onboard them (for ex. prod-interop-coll) */ - .onItem() - .invoke(() -> onboarding.setTestEnvProductIds(product.getTestEnvProductIds())) - .onItem() - .transformToUni( - current -> persistOnboarding(onboarding, userRequests, product, null)) - .onItem() - .call( - onboardingPersisted -> - Panache.withTransaction( - () -> - Token.persist( - getToken(onboardingPersisted, product, contractImported)))) - /* Update onboarding data with users and start orchestration */ - .onItem() - .transformToUni( - currentOnboarding -> - persistAndStartOrchestrationOnboarding( - currentOnboarding, - orchestrationApi.apiStartOnboardingOrchestrationGet( - currentOnboarding.getId(), timeout))) - .onItem() - .transform(onboardingMapper::toResponse)); + .onItem() + .transformToUni( + product -> + verifyAlreadyOnboardingForProductAndProductParent( + onboarding.getInstitution(), product.getId(), product.getParentId()) + .replaceWith(product)) + .onItem() + .transformToUni( + product -> + Uni.createFrom() + .item(registryResourceFactory.create(onboarding, getManagerTaxCode(userRequests))) + .onItem() + .invoke( + registryManager -> + registryManager.setResource(registryManager.retrieveInstitution())) + .runSubscriptionOn(Infrastructure.getDefaultWorkerPool()) + .onItem() + .transformToUni( + registryManager -> + registryManager + .isValid() + .onItem() + .transformToUni( + ignored -> registryManager.customValidation(product))) + /* if product has some test environments, request must also onboard them (for ex. prod-interop-coll) */ + .onItem() + .invoke(() -> onboarding.setTestEnvProductIds(product.getTestEnvProductIds())) + .onItem() + .transformToUni( + current -> persistOnboarding(onboarding, userRequests, product, aggregateRequests)) + .onItem() + .call( + onboardingPersisted -> + Panache.withTransaction( + () -> + Token.persist( + getToken(onboardingPersisted, product, contractImported)))) + /* Update onboarding data with users and start orchestration */ + .onItem() + .transformToUni( + currentOnboarding -> + persistAndStartOrchestrationOnboarding( + currentOnboarding, + orchestrationApi.apiStartOnboardingOrchestrationGet( + currentOnboarding.getId(), timeout))) + .onItem() + .transform(onboardingMapper::toResponse)); } private Uni persistOnboarding(