Skip to content

Commit

Permalink
[SELC-3493] feat: Approve Endpoint for Enhanced Onboarding Process Ap…
Browse files Browse the repository at this point in the history
…proval (#95)

* endpoint for approve

* fix unit test onboarding get

* unify endpoint approve

* fix error message
  • Loading branch information
manuraf authored Jan 19, 2024
1 parent ee4e627 commit 14f0f4e
Show file tree
Hide file tree
Showing 6 changed files with 155 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,7 @@ private Uni<String> readUserIdFromToken(SecurityContext ctx) {
});
}


@Operation(summary = "Perform complete operation of an onboarding request receiving onboarding id and contract signed by hte institution." +
@Operation(summary = "Perform complete operation of an onboarding request receiving onboarding id and contract signed by the institution." +
"It checks the contract's signature and upload the contract on an azure storage" +
"At the end, function triggers async activities related to complete onboarding " +
"that consist of create the institution, activate the onboarding and sending data to notification queue.")
Expand All @@ -121,6 +120,19 @@ public Uni<Response> complete(@PathParam(value = "onboardingId") String onboardi
.build());
}

@Operation(summary = "Perform approve operation of an onboarding request receiving onboarding id." +
"Function triggers async activities related to onboarding based on institution type or completing onboarding. " )

@PUT
@Path("/{onboardingId}/approve")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Uni<Response> approve(@PathParam(value = "onboardingId") String onboardingId) {
return onboardingService.approve(onboardingId)
.map(ignore -> Response
.status(HttpStatus.SC_OK)
.build());
}

@Operation(summary = "The API retrieves paged onboarding using optional filter, order by descending creation date")
@GET
@Produces(MediaType.APPLICATION_JSON)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ public interface OnboardingService {

Uni<OnboardingResponse> onboardingPa(OnboardingPaRequest onboardingRequest);

Uni<OnboardingGet> approve(String onboardingId);

Uni<Onboarding> complete(String tokenId, File contract);

Uni<Onboarding> completeWithoutSignatureVerification(String tokenId, File contract);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
import org.jboss.resteasy.reactive.ClientWebApplicationException;
import org.openapi.quarkus.core_json.api.OnboardingApi;
import org.openapi.quarkus.onboarding_functions_json.api.OrchestrationApi;
import org.openapi.quarkus.onboarding_functions_json.model.OrchestrationResponse;
import org.openapi.quarkus.party_registry_proxy_json.api.AooApi;
import org.openapi.quarkus.party_registry_proxy_json.api.UoApi;
import org.openapi.quarkus.user_registry_json.api.UserApi;
Expand All @@ -58,12 +59,12 @@
import java.time.OffsetDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;

import static it.pagopa.selfcare.onboarding.common.ProductId.PROD_INTEROP;
import static it.pagopa.selfcare.onboarding.constants.CustomError.*;
import static it.pagopa.selfcare.onboarding.util.GenericError.GENERIC_ERROR;
import static it.pagopa.selfcare.onboarding.util.GenericError.ONBOARDING_EXPIRED;
import static it.pagopa.selfcare.onboarding.util.GenericError.*;

@ApplicationScoped
public class OnboardingServiceDefault implements OnboardingService {
Expand Down Expand Up @@ -418,6 +419,28 @@ private static boolean isFieldToUpdate(CertifiableFieldResourceOfstring certifie
return isToUpdate;
}

@Override
public Uni<OnboardingGet> approve(String onboardingId) {

// If approve if for PT it must complete onboarding, otherwise continue to onboarding process
Function<WorkflowType, Supplier<Uni<OrchestrationResponse>>> approveFunction =
workflowType -> WorkflowType.FOR_APPROVE_PT.equals(workflowType)
? () -> orchestrationApi.apiStartOnboardingCompletionOrchestrationGet(onboardingId)
: () -> orchestrationApi.apiStartOnboardingOrchestrationGet(onboardingId);

return retrieveOnboardingAndCheckIfExpired(onboardingId)
.onItem().transformToUni(this::checkIfToBeValidated)
//Fail if onboarding exists for a product
.onItem().transformToUni(onboarding -> product(onboarding.getProductId())
.onItem().transformToUni(product -> verifyAlreadyOnboardingForProductAndProductParent(onboarding, product))
)
.onItem().transformToUni(onboarding -> onboardingOrchestrationEnabled
? approveFunction.apply(onboarding.getWorkflowType())
.get().map(ignore -> onboarding)
: Uni.createFrom().item(onboarding))
.map(onboardingMapper::toGetResponse);
}

@Override
public Uni<Onboarding> complete(String onboardingId, File contract) {

Expand Down Expand Up @@ -498,6 +521,14 @@ private Uni<Onboarding> retrieveOnboardingAndCheckIfExpired(String onboardingId)
onboardingId, ONBOARDING_EXPIRED.getCode())))));
}


private Uni<Onboarding> checkIfToBeValidated(Onboarding onboarding) {
return OnboardingStatus.TO_BE_VALIDATED.equals(onboarding.getStatus())
? Uni.createFrom().item(onboarding)
: Uni.createFrom().failure(new InvalidRequestException(String.format(ONBOARDING_NOT_TO_BE_VALIDATED.getMessage(),
onboarding.getId(), ONBOARDING_NOT_TO_BE_VALIDATED.getCode())));
}

public static boolean isOnboardingExpired(LocalDateTime dateTime) {
LocalDateTime now = LocalDateTime.now();
return Objects.nonNull(dateTime) && (now.isEqual(dateTime) || now.isAfter(dateTime));
Expand Down Expand Up @@ -574,6 +605,7 @@ public Uni<Long> deleteOnboarding(String onboardingId) {
public Uni<OnboardingGet> onboardingPending(String onboardingId) {
return onboardingGet(onboardingId)
.flatMap(onboardingGet -> OnboardingStatus.PENDING.name().equals(onboardingGet.getStatus())
|| OnboardingStatus.TO_BE_VALIDATED.name().equals(onboardingGet.getStatus())
? Uni.createFrom().item(onboardingGet)
: Uni.createFrom().failure(new ResourceNotFoundException(String.format("Onboarding with id %s not found or not in PENDING status!",onboardingId))));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ public enum GenericError {
GET_INSTITUTION_ATTRIBUTES_ERROR("0022", "Error while getting party attributes"),

ONBOARDING_EXPIRED("0040", "Onboarding with id %s not found or it is expired!"),
ONBOARDING_NOT_TO_BE_VALIDATED("0043", "Onboarding with id %s has not TO_BE_VALIDATED status!"),
GET_INSTITUTION_BY_GEOTAXONOMY_ERROR("0053", "Error while searching institutions related to given geoTaxonomies"),
GET_INSTITUTION_BY_PRODUCTID_ERROR("0053", "Error while searching institutions related to given productId"),
GET_INSTITUTIONS_REQUEST_ERROR("0054", "Invalid request parameters sent. Allowed filters combinations taxCode and subunit or origin and originId"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,6 @@ void getOnboardingByIdWithUserInfo(){
.onboardingGetWithUserInfo(onboardingGet.getId());
}


@Test
@TestSecurity(user = "userJwt")
void getOnboardingPending(){
Expand All @@ -340,6 +339,23 @@ void getOnboardingPending(){
verify(onboardingService, times(1))
.onboardingPending(onboardingGet.getId());
}
@Test
@TestSecurity(user = "userJwt")
void approve(){
OnboardingGet onboardingGet = dummyOnboardingGet();
when(onboardingService.approve(onboardingGet.getId()))
.thenReturn(Uni.createFrom().item(onboardingGet));

given()
.when()
.put("/{onboardingId}/approve", onboardingGet.getId())
.then()
.statusCode(200);

verify(onboardingService, times(1))
.approve(onboardingGet.getId());
}

private static Map<String, String> getStringStringMap() {
Map<String, String> queryParameterMap = new HashMap<>();
queryParameterMap.put("productId","prod-io");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
import it.pagopa.selfcare.onboarding.common.OnboardingStatus;
import it.pagopa.selfcare.onboarding.common.PartyRole;
import it.pagopa.selfcare.onboarding.controller.request.*;
import it.pagopa.selfcare.onboarding.controller.response.InstitutionResponse;
import it.pagopa.selfcare.onboarding.controller.response.OnboardingGet;
import it.pagopa.selfcare.onboarding.controller.response.OnboardingGetResponse;
import it.pagopa.selfcare.onboarding.controller.response.UserResponse;
Expand All @@ -27,6 +26,8 @@
import it.pagopa.selfcare.onboarding.exception.InvalidRequestException;
import it.pagopa.selfcare.onboarding.exception.OnboardingNotAllowedException;
import it.pagopa.selfcare.onboarding.exception.ResourceNotFoundException;
import it.pagopa.selfcare.onboarding.mapper.OnboardingMapper;
import it.pagopa.selfcare.onboarding.mapper.OnboardingMapperImpl;
import it.pagopa.selfcare.onboarding.util.InstitutionPaSubunitType;
import it.pagopa.selfcare.product.entity.Product;
import it.pagopa.selfcare.product.entity.ProductRole;
Expand All @@ -42,6 +43,7 @@
import org.jboss.resteasy.reactive.ClientWebApplicationException;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.mockito.Spy;
import org.openapi.quarkus.core_json.api.OnboardingApi;
import org.openapi.quarkus.onboarding_functions_json.api.OrchestrationApi;
import org.openapi.quarkus.onboarding_functions_json.model.OrchestrationResponse;
Expand Down Expand Up @@ -102,6 +104,9 @@ class OnboardingServiceDefaultTest {
@RestClient
OrchestrationApi orchestrationApi;

@Spy
OnboardingMapper onboardingMapper = new OnboardingMapperImpl();

final static UserRequest manager = UserRequest.builder()
.name("name")
.surname("surname")
Expand Down Expand Up @@ -931,7 +936,7 @@ void testOnboardingGet() {
int page = 0, size = 3;
Onboarding onboarding = createDummyOnboarding();
mockFindOnboarding(onboarding);
OnboardingGetResponse getResponse = getOnboardingGetResponse(onboarding.getId());
OnboardingGetResponse getResponse = getOnboardingGetResponse(onboarding);
UniAssertSubscriber<OnboardingGetResponse> subscriber = onboardingService
.onboardingGet("prod-io", null, null, "2023-11-10", "2021-12-10", page,size)
.subscribe()
Expand All @@ -940,19 +945,11 @@ void testOnboardingGet() {
subscriber.assertCompleted().assertItem(getResponse);
}

private static OnboardingGetResponse getOnboardingGetResponse(ObjectId id) {
OnboardingGet onboarding = new OnboardingGet();
onboarding.setId(id.toString());
onboarding.setProductId("prod-id");
UserResponse user = new UserResponse();
user.setId("actual-user-id");
user.setRole(PartyRole.MANAGER);
onboarding.setUsers(List.of(user));
InstitutionResponse institutionResponse = new InstitutionResponse();
onboarding.setInstitution(institutionResponse);
private OnboardingGetResponse getOnboardingGetResponse(Onboarding onboarding) {
OnboardingGet onboardingGet = onboardingMapper.toGetResponse(onboarding);
OnboardingGetResponse response = new OnboardingGetResponse();
response.setCount(1L);
response.setItems(List.of(onboarding));
response.setItems(List.of(onboardingGet));
return response;
}

Expand Down Expand Up @@ -992,6 +989,8 @@ private Onboarding createDummyOnboarding() {
onboarding.setProductId("prod-id");

Institution institution = new Institution();
institution.setTaxCode("taxCode");
institution.setSubunitCode("subunitCode");
onboarding.setInstitution(institution);

User user = new User();
Expand Down Expand Up @@ -1100,7 +1099,7 @@ void onboardingPending_shouldResourceNotFound() {
when(Onboarding.findByIdOptional(any()))
.thenReturn(Uni.createFrom().item(Optional.of(onboarding)));

UniAssertSubscriber<OnboardingGet> subscriber = onboardingService
onboardingService
.onboardingPending(ObjectId.get().toHexString())
.subscribe()
.withSubscriber(UniAssertSubscriber.create())
Expand Down Expand Up @@ -1132,4 +1131,78 @@ void onboardingGetWithUserInfo() {
Assertions.assertEquals(actualUser.getSurname(), managerResource.getFamilyName().getValue());
}



@Test
void approve() {
Onboarding onboarding = createDummyOnboarding();
onboarding.setStatus(OnboardingStatus.TO_BE_VALIDATED);
PanacheMock.mock(Onboarding.class);
when(Onboarding.findByIdOptional(any()))
.thenReturn(Uni.createFrom().item(Optional.of(onboarding)));

when(productService.getProductIsValid(onboarding.getProductId()))
.thenReturn(createDummyProduct(onboarding.getProductId(), false));

when(onboardingApi.verifyOnboardingInfoUsingHEAD(onboarding.getInstitution().getTaxCode(), onboarding.getProductId(),
onboarding.getInstitution().getSubunitCode()))
.thenReturn(Uni.createFrom().failure(new ClientWebApplicationException(404)));

when(orchestrationApi.apiStartOnboardingOrchestrationGet(onboarding.getId().toHexString()))
.thenReturn(Uni.createFrom().item(new OrchestrationResponse()));

UniAssertSubscriber<OnboardingGet> subscriber = onboardingService
.approve(onboarding.getId().toHexString())
.subscribe()
.withSubscriber(UniAssertSubscriber.create());

OnboardingGet actual = subscriber.awaitItem().getItem();
Assertions.assertNotNull(actual);
Assertions.assertEquals(onboarding.getId().toHexString(), actual.getId());
}

@Test
void approve_throwExceptionIfOnboardingIsNotToBeValidated() {
Onboarding onboarding = createDummyOnboarding();
PanacheMock.mock(Onboarding.class);
when(Onboarding.findByIdOptional(any()))
.thenReturn(Uni.createFrom().item(Optional.of(onboarding)));

when(productService.getProductIsValid(onboarding.getProductId()))
.thenReturn(createDummyProduct(onboarding.getProductId(), false));

onboardingService
.approve(onboarding.getId().toHexString())
.subscribe()
.withSubscriber(UniAssertSubscriber.create())
.assertFailedWith(InvalidRequestException.class);
}

@Test
void approveCompletion() {
Onboarding onboarding = createDummyOnboarding();
onboarding.setStatus(OnboardingStatus.TO_BE_VALIDATED);
PanacheMock.mock(Onboarding.class);
when(Onboarding.findByIdOptional(any()))
.thenReturn(Uni.createFrom().item(Optional.of(onboarding)));

when(productService.getProductIsValid(onboarding.getProductId()))
.thenReturn(createDummyProduct(onboarding.getProductId(), false));

when(onboardingApi.verifyOnboardingInfoUsingHEAD(onboarding.getInstitution().getTaxCode(), onboarding.getProductId(),
onboarding.getInstitution().getSubunitCode()))
.thenReturn(Uni.createFrom().failure(new ClientWebApplicationException(404)));

when(orchestrationApi.apiStartOnboardingCompletionOrchestrationGet(onboarding.getId().toHexString()))
.thenReturn(Uni.createFrom().item(new OrchestrationResponse()));

UniAssertSubscriber<OnboardingGet> subscriber = onboardingService
.approve(onboarding.getId().toHexString())
.subscribe()
.withSubscriber(UniAssertSubscriber.create());

OnboardingGet actual = subscriber.awaitItem().getItem();
Assertions.assertNotNull(actual);
Assertions.assertEquals(onboarding.getId().toHexString(), actual.getId());
}
}

0 comments on commit 14f0f4e

Please sign in to comment.