Skip to content

Commit

Permalink
[SELC-5481] Added api for increment aggregates and fix userRole value…
Browse files Browse the repository at this point in the history
… in mapUsers of OnboardingMapper (#497)
  • Loading branch information
flaminiaScarciofolo authored Sep 20, 2024
1 parent 9886951 commit 65aac4e
Show file tree
Hide file tree
Showing 8 changed files with 239 additions and 10 deletions.
38 changes: 38 additions & 0 deletions apps/onboarding-ms/src/main/docs/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,44 @@
} ]
}
},
"/v1/onboarding/aggregation/increment" : {
"post" : {
"tags" : [ "Onboarding Controller" ],
"summary" : "Perform Increment for aggregates",
"description" : "Perform the increment of the aggregates for an aggregator entity that has already completed the initial onboarding.The API initiates the onboarding process for the aggregated entities received as input.",
"operationId" : "onboardingAggregationIncrement",
"requestBody" : {
"content" : {
"application/json" : {
"schema" : {
"$ref" : "#/components/schemas/OnboardingPaRequest"
}
}
}
},
"responses" : {
"200" : {
"description" : "OK",
"content" : {
"application/json" : {
"schema" : {
"$ref" : "#/components/schemas/OnboardingResponse"
}
}
}
},
"401" : {
"description" : "Not Authorized"
},
"403" : {
"description" : "Not Allowed"
}
},
"security" : [ {
"SecurityScheme" : [ ]
} ]
}
},
"/v1/onboarding/check-manager" : {
"post" : {
"tags" : [ "Onboarding Controller" ],
Expand Down
27 changes: 27 additions & 0 deletions apps/onboarding-ms/src/main/docs/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,33 @@ paths:
description: Not Allowed
security:
- SecurityScheme: []
/v1/onboarding/aggregation/increment:
post:
tags:
- Onboarding Controller
summary: Perform Increment for aggregates
description: Perform the increment of the aggregates for an aggregator entity
that has already completed the initial onboarding.The API initiates the onboarding
process for the aggregated entities received as input.
operationId: onboardingAggregationIncrement
requestBody:
content:
application/json:
schema:
$ref: "#/components/schemas/OnboardingPaRequest"
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: "#/components/schemas/OnboardingResponse"
"401":
description: Not Authorized
"403":
description: Not Allowed
security:
- SecurityScheme: []
/v1/onboarding/check-manager:
post:
tags:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,19 @@ public Uni<OnboardingResponse> onboardingPaAggregation(@Valid OnboardingPaReques
.onboarding(fillUserId(onboardingMapper.toEntity(onboardingRequest), userId), onboardingRequest.getUsers(), onboardingRequest.getAggregates()));
}

@Operation(summary = "Perform Increment for aggregates",
description = "Perform the increment of the aggregates for an aggregator entity that has already completed the initial onboarding."
+ "The API initiates the onboarding process for the aggregated entities received as input.")
@POST
@Path("/aggregation/increment")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Uni<OnboardingResponse> onboardingAggregationIncrement(@Valid OnboardingPaRequest onboardingRequest, @Context SecurityContext ctx) {
return readUserIdFromToken(ctx)
.onItem().transformToUni(userId -> onboardingService
.onboardingIncrement(fillUserId(onboardingMapper.toEntity(onboardingRequest), userId), onboardingRequest.getUsers(), onboardingRequest.getAggregates()));
}

@Operation(
summary = "Onboarding for PSP institutions, saves user data, and requests admin approval via email.",
description = "Perform onboarding request for PSP institution type." +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ default List<AggregateUser> mapUsers(CsvAggregateSend csvAggregateSend) {
user.setSurname(csvAggregateSend.getAdminAggregateSurname());
user.setTaxCode(csvAggregateSend.getAdminAggregateTaxCode());
user.setEmail(csvAggregateSend.getAdminAggregateEmail());
user.setRole("Delegate");
user.setRole(PartyRole.DELEGATE.value());

return Collections.singletonList(user);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,6 @@ public interface OnboardingService {

Uni<CustomError> checkRecipientCode(String recipientCode, String originId);

Uni<OnboardingResponse> onboardingIncrement(Onboarding onboarding, List<UserRequest> userRequests, List<AggregateInstitutionRequest> aggregates);

}
Original file line number Diff line number Diff line change
Expand Up @@ -150,9 +150,20 @@ public Uni<OnboardingResponse> onboarding(Onboarding onboarding, List<UserReques
onboarding.setWorkflowType(getWorkflowType(onboarding));
onboarding.setStatus(OnboardingStatus.REQUEST);

return fillUsersAndOnboarding(onboarding, userRequests, aggregates, null);
return fillUsersAndOnboarding(onboarding, userRequests, aggregates, null, false);
}


@Override
public Uni<OnboardingResponse> onboardingIncrement(Onboarding onboarding, List<UserRequest> userRequests, List<AggregateInstitutionRequest> aggregates) {
onboarding.setExpiringDate(OffsetDateTime.now().plusDays(onboardingExpireDate).toLocalDateTime());
onboarding.setWorkflowType(WorkflowType.INCREMENT_REGISTRATION_AGGREGATOR);
onboarding.setStatus(OnboardingStatus.PENDING);

return fillUsersAndOnboarding(onboarding, userRequests, aggregates, null, true);
}


/**
* As onboarding but it is specific for USERS workflow
*/
Expand All @@ -178,15 +189,15 @@ public Uni<OnboardingResponse> onboardingCompletion(Onboarding onboarding, List<
onboarding.setWorkflowType(WorkflowType.CONFIRMATION);
onboarding.setStatus(OnboardingStatus.PENDING);

return fillUsersAndOnboarding(onboarding, userRequests, null, TIMEOUT_ORCHESTRATION_RESPONSE);
return fillUsersAndOnboarding(onboarding, userRequests, null, TIMEOUT_ORCHESTRATION_RESPONSE,false);
}

@Override
public Uni<OnboardingResponse> onboardingAggregationCompletion(Onboarding onboarding, List<UserRequest> userRequests, List<AggregateInstitutionRequest> aggregates) {
onboarding.setWorkflowType(WorkflowType.CONTRACT_REGISTRATION_AGGREGATOR);
onboarding.setStatus(OnboardingStatus.PENDING);

return fillUsersAndOnboarding(onboarding, userRequests, aggregates, null);
return fillUsersAndOnboarding(onboarding, userRequests, aggregates, null,false);
}

/**
Expand All @@ -203,11 +214,11 @@ public Uni<OnboardingResponse> onboardingImport(Onboarding onboarding, List<User
* @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<OnboardingResponse> fillUsersAndOnboarding(Onboarding onboarding, List<UserRequest> userRequests,List<AggregateInstitutionRequest> aggregates,String timeout) {
private Uni<OnboardingResponse> fillUsersAndOnboarding(Onboarding onboarding, List<UserRequest> userRequests,List<AggregateInstitutionRequest> aggregates,String timeout, boolean isAggregatesIncrement) {
onboarding.setCreatedAt(LocalDateTime.now());

return getProductByOnboarding(onboarding)
.onItem().transformToUni(product -> verifyAlreadyOnboardingForProductAndProductParent(onboarding.getInstitution(), product.getId(), product.getParentId())
.onItem().transformToUni(product -> verifyAlreadyOnboarding(onboarding.getInstitution(), product.getId(), product.getParentId(), isAggregatesIncrement)
.replaceWith(product))
.onItem().transformToUni(product -> getRegistryResource(onboarding)
.onItem().transformToUni(proxyResource -> onboardingUtils.customValidationOnboardingData(onboarding, product, proxyResource)
Expand All @@ -224,6 +235,20 @@ private Uni<OnboardingResponse> fillUsersAndOnboarding(Onboarding onboarding, Li
.onItem().transform(onboardingMapper::toResponse));
}

/**
* This method checks whether the product and any parent have already been onboarded for the provided institution.
* In the case where we are in the aggregate increment flow, the product on the aggregator entity must already be onboarded,
* so in the case of a ResourceConflictException, the exception should not be propagated.
* In the case of standard onboarding, the exception should be propagated, and the flow should be blocked.
*/
private Uni<Void> verifyAlreadyOnboarding(Institution institution, String productId, String parentId, boolean isAggregatesIncrement) {
if(isAggregatesIncrement) {
return verifyAlreadyOnboardingForProductAndProductParent(institution, productId, parentId)
.onFailure(ResourceConflictException.class).recoverWithNull().replaceWithVoid();
}
return verifyAlreadyOnboardingForProductAndProductParent(institution, productId, parentId).replaceWithVoid();
}

/**
* @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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,35 @@ void onboardingPaAggregator() {
assertFalse(captor.getValue().getAggregates().isEmpty());
}

@Test
@TestSecurity(user = "userJwt")
void onboardingAggregationIncrement() {
OnboardingPaRequest onboardingPaValid = dummyOnboardingPa();
onboardingPaValid.setIsAggregator(Boolean.TRUE);
List<AggregateInstitutionRequest> aggregateInstitutions = new ArrayList<>();
AggregateInstitutionRequest aggregateInstitutionRequest = new AggregateInstitutionRequest();
aggregateInstitutions.add(aggregateInstitutionRequest);
onboardingPaValid.setAggregates(aggregateInstitutions);

Mockito.when(onboardingService.onboardingIncrement(any(), any(), any()))
.thenReturn(Uni.createFrom().item(new OnboardingResponse()));

given()
.when()
.body(onboardingPaValid)
.contentType(ContentType.JSON)
.post("/aggregation/increment")
.then()
.statusCode(200);

ArgumentCaptor<Onboarding> captor = ArgumentCaptor.forClass(Onboarding.class);
Mockito.verify(onboardingService, times(1))
.onboardingIncrement(captor.capture(), any(), any());
assertEquals(captor.getValue().getBilling().getRecipientCode(), onboardingPaValid.getBilling().getRecipientCode().toUpperCase());
assertTrue(captor.getValue().getIsAggregator());
assertFalse(captor.getValue().getAggregates().isEmpty());
}

@Test
@TestSecurity(user = "userJwt")
void onboardingUsers() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,7 @@
import it.pagopa.selfcare.onboarding.controller.request.OnboardingImportContract;
import it.pagopa.selfcare.onboarding.controller.request.OnboardingUserRequest;
import it.pagopa.selfcare.onboarding.controller.request.UserRequest;
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.controller.response.UserResponse;
import it.pagopa.selfcare.onboarding.controller.response.*;
import it.pagopa.selfcare.onboarding.entity.*;
import it.pagopa.selfcare.onboarding.exception.InvalidRequestException;
import it.pagopa.selfcare.onboarding.exception.OnboardingNotAllowedException;
Expand Down Expand Up @@ -77,11 +74,14 @@
import java.util.*;

import static it.pagopa.selfcare.onboarding.common.ProductId.*;
import static it.pagopa.selfcare.onboarding.common.WorkflowType.INCREMENT_REGISTRATION_AGGREGATOR;
import static it.pagopa.selfcare.onboarding.service.OnboardingServiceDefault.USERS_FIELD_LIST;
import static it.pagopa.selfcare.onboarding.service.OnboardingServiceDefault.USERS_FIELD_TAXCODE;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.*;
import static org.openapi.quarkus.core_json.model.InstitutionProduct.StateEnum.PENDING;


@QuarkusTest
Expand Down Expand Up @@ -241,6 +241,101 @@ void onboardingPa_throwExceptionIfProductAlreadyOnboarded(UniAsserter asserter)
asserter.assertFailedWith(() -> onboardingService.onboarding(onboardingRequest, users, null), ResourceConflictException.class);
}

@Test
@RunOnVertxContext
void onboardingIncrement_Ok(UniAsserter asserter) {
Onboarding onboardingRequest = new Onboarding();
onboardingRequest.setIsAggregator(true);
List<UserRequest> users = List.of(manager);
onboardingRequest.setProductId("productId");
Institution institutionBaseRequest = new Institution();
institutionBaseRequest.setInstitutionType(InstitutionType.PA);
institutionBaseRequest.setTaxCode("taxCode");
institutionBaseRequest.setOriginId("originId");
onboardingRequest.setInstitution(institutionBaseRequest);
Billing billing = new Billing();
billing.setRecipientCode("recCode");
onboardingRequest.setBilling(billing);

AggregateInstitution aggregateInstitution = new AggregateInstitution();
aggregateInstitution.setDescription("test");
onboardingRequest.setAggregates(List.of(aggregateInstitution));

AggregateInstitutionRequest aggregateInstitutionRequest = new AggregateInstitutionRequest();
aggregateInstitutionRequest.setDescription("test");
aggregateInstitutionRequest.setTaxCode("taxCode");

mockSimpleProductValidAssert(onboardingRequest.getProductId(), false, asserter);
mockVerifyAllowedMap(onboardingRequest.getInstitution().getTaxCode(), onboardingRequest.getProductId(), asserter);
mockVerifyOnboardingNotEmpty(asserter);

UOResource uoResource = new UOResource();
uoResource.setCodiceFiscaleSfe("codSfe");
uoResource.setCodiceIpa("originId");
when(uoApi.findByUnicodeUsingGET1("recCode", null)).thenReturn(Uni.createFrom().item(uoResource));

managerResource.setId(UUID.fromString("9456d91f-ef53-4f89-8330-7f9a195d5d1e"));
when(userRegistryApi.searchUsingPOST(eq(USERS_FIELD_LIST), any())).thenReturn(Uni.createFrom().item(managerResource));

OnboardingResponse onboardingResponse = getOnboardingResponse();

Uni<OnboardingResponse> response = onboardingService.onboardingIncrement(onboardingRequest, users, List.of(aggregateInstitutionRequest));

asserter.assertEquals(() -> response,onboardingResponse);
}

private static OnboardingResponse getOnboardingResponse() {
OnboardingResponse onboardingResponse = new OnboardingResponse();
onboardingResponse.setWorkflowType(INCREMENT_REGISTRATION_AGGREGATOR.toString());
onboardingResponse.setProductId("productId");
InstitutionResponse institution = new InstitutionResponse();
institution.setInstitutionType("PA");
institution.setOriginId("originId");
institution.setTaxCode("taxCode");
onboardingResponse.setInstitution(institution);

UserOnboardingResponse userOnboardingResponse = new UserOnboardingResponse();
userOnboardingResponse.setId("9456d91f-ef53-4f89-8330-7f9a195d5d1e");
userOnboardingResponse.setRole(PartyRole.MANAGER);
userOnboardingResponse.setProductRole("admin");
onboardingResponse.setUsers(List.of(userOnboardingResponse));

BillingResponse billingResponse = new BillingResponse();
billingResponse.setRecipientCode("recCode");
onboardingResponse.setBilling(billingResponse);

onboardingResponse.setStatus(PENDING.toString());
onboardingResponse.setIsAggregator(true);
return onboardingResponse;
}


@Test
@RunOnVertxContext
void onboardingIncrement_throwExceptionIfProductNotOnboarded(UniAsserter asserter) {
Onboarding onboardingRequest = new Onboarding();
List<UserRequest> users = List.of(manager);
onboardingRequest.setProductId("productId");
Institution institutionBaseRequest = new Institution();
institutionBaseRequest.setInstitutionType(InstitutionType.PA);
institutionBaseRequest.setTaxCode("taxCode");
onboardingRequest.setInstitution(institutionBaseRequest);

AggregateInstitution aggregateInstitution = new AggregateInstitution();
aggregateInstitution.setDescription("test");
onboardingRequest.setAggregates(List.of(aggregateInstitution));

AggregateInstitutionRequest aggregateInstitutionRequest = new AggregateInstitutionRequest();
aggregateInstitutionRequest.setDescription("test");
aggregateInstitutionRequest.setTaxCode("taxCode");

mockSimpleProductValidAssert(onboardingRequest.getProductId(), false, asserter);
mockVerifyAllowedMap(onboardingRequest.getInstitution().getTaxCode(), onboardingRequest.getProductId(), asserter);
mockVerifyOnboardingNotFound();

asserter.assertFailedWith(() -> onboardingService.onboardingIncrement(onboardingRequest, users, List.of(aggregateInstitutionRequest)), InvalidRequestException.class);
}

@Test
@RunOnVertxContext
void onboarding_throwExceptionIfProductIsNotDelegable(UniAsserter asserter) {
Expand Down

0 comments on commit 65aac4e

Please sign in to comment.