Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: save product role when onboarding #137

Merged
merged 1 commit into from
Feb 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,5 @@ public class UserRequest {
private String surname;
private String email;
private PartyRole role;
private String productRole;
//private Env env = Env.ROOT;

}
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
package it.pagopa.selfcare.onboarding.controller.response;

import it.pagopa.selfcare.onboarding.controller.request.AdditionalInformationsDto;
import lombok.Data;

import java.util.List;

@Data
public class OnboardingResponse {

private InstitutionResponse institution;
private String id;
private String productId;
private String workflowType;
private InstitutionResponse institution;
private String pricingPlan;
private List<UserResponse> users;
private List<UserOnboardingResponse> users;
private BillingResponse billing;
private String status;
private AdditionalInformationsDto additionalInformations;
private String userRequestUid;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package it.pagopa.selfcare.onboarding.controller.response;

import it.pagopa.selfcare.onboarding.common.PartyRole;
import lombok.Data;

@Data
public class UserOnboardingResponse {

private String id;
private PartyRole role;
private String productRole;
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ public class UserResponse {
private String surname;
private String email;
private PartyRole role;
private String productRole;
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@ public class User {

private String id;
private PartyRole role;
private String ProductRole;
private String productRole;
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ public interface OnboardingMapper {
@Mapping(source = "institutionType", target = "institution.institutionType")
Onboarding toEntity(OnboardingPgRequest request);

OnboardingResponse toResponse(Onboarding onboarding);
@Mapping(target = "id", expression = "java(objectIdToString(model.getId()))")
OnboardingResponse toResponse(Onboarding model);

@Mapping(target = "id", expression = "java(objectIdToString(model.getId()))")
OnboardingGet toGetResponse(Onboarding model);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@ public class OnboardingServiceDefault implements OnboardingService {
protected static final String ATLEAST_ONE_PRODUCT_ROLE_REQUIRED = "At least one Product role related to %s Party role is required";
protected static final String MORE_THAN_ONE_PRODUCT_ROLE_AVAILABLE = "More than one Product role related to %s Party role is available. Cannot automatically set the Product role";
private static final String ONBOARDING_NOT_ALLOWED_ERROR_MESSAGE_TEMPLATE = "Institution with external id '%s' is not allowed to onboard '%s' product";
private static final String ONBOARDING_NOT_ALLOWED_ERROR_MESSAGE_NOT_DELEGABLE = "Institution with external id '%s' is not allowed to onboard '%s' product because it is not delegable";
private static final String INVALID_OBJECTID = "Given onboardingId [%s] has wrong format";
private static final String ONBOARDING_NOT_FOUND_OR_ALREADY_DELETED = "Onboarding with id %s not found or already deleted";
public static final String UNABLE_TO_COMPLETE_THE_ONBOARDING_FOR_INSTITUTION_FOR_PRODUCT_DISMISSED = "Unable to complete the onboarding for institution with taxCode '%s' to product '%s', the product is dismissed.";
Expand Down Expand Up @@ -157,17 +156,17 @@ public Uni<OnboardingResponse> onboardingCompletion(Onboarding onboarding, List<
private Uni<OnboardingResponse> fillUsersAndOnboarding(Onboarding onboarding, List<UserRequest> userRequests, String timeout) {
onboarding.setCreatedAt(LocalDateTime.now());

return validationProductDataAndOnboardingExists(onboarding, userRequests)
.onItem().transformToUni(OnboardingUtils::customValidationOnboardingData)
.onItem().transformToUni(this::addParentDescriptionForAooOrUo)
/* I have to retrieve onboarding id for saving reference to pdv */
.onItem().transformToUni(current -> Panache.withTransaction(() -> Onboarding.persist(onboarding).replaceWith(onboarding)
.onItem().transformToUni(onboardingPersisted -> validationRoleAndRetrieveUsers(userRequests, onboardingPersisted.id.toHexString())
.onItem().invoke(onboardingPersisted::setUsers).replaceWith(onboardingPersisted))))
/* Update onboarding data with users and start orchestration */
.onItem().transformToUni(currentOnboarding -> persistAndStartOrchestrationOnboarding(currentOnboarding,
orchestrationApi.apiStartOnboardingOrchestrationGet(currentOnboarding.getId().toHexString(), timeout)))
.onItem().transform(onboardingMapper::toResponse);
return validationProductDataAndOnboardingExists(onboarding)
.onItem().transformToUni(product -> OnboardingUtils.customValidationOnboardingData(onboarding, product)
.onItem().transformToUni(this::addParentDescriptionForAooOrUo)
/* I have to retrieve onboarding id for saving reference to pdv */
.onItem().transformToUni(current -> Panache.withTransaction(() -> Onboarding.persist(onboarding).replaceWith(onboarding)
.onItem().transformToUni(onboardingPersisted -> validationRoleAndRetrieveUsers(userRequests, onboardingPersisted.id.toHexString(), product)
.onItem().invoke(onboardingPersisted::setUsers).replaceWith(onboardingPersisted))))
/* Update onboarding data with users and start orchestration */
.onItem().transformToUni(currentOnboarding -> persistAndStartOrchestrationOnboarding(currentOnboarding,
orchestrationApi.apiStartOnboardingOrchestrationGet(currentOnboarding.getId().toHexString(), timeout)))
.onItem().transform(onboardingMapper::toResponse));
}


Expand Down Expand Up @@ -253,41 +252,28 @@ private Uni<Product> product(String productId) {
.runSubscriptionOn(Infrastructure.getDefaultWorkerPool());
}

public Uni<Onboarding> validationProductDataAndOnboardingExists(Onboarding onboarding, List<UserRequest> userRequests) {
public Uni<Product> validationProductDataAndOnboardingExists(Onboarding onboarding) {

/* retrieve product, if is not valid will throw OnboardingNotAllowedException */
return product(onboarding.getProductId())
.onFailure().transform(ex -> new OnboardingNotAllowedException(String.format(UNABLE_TO_COMPLETE_THE_ONBOARDING_FOR_INSTITUTION_FOR_PRODUCT_DISMISSED,
onboarding.getInstitution().getTaxCode(),
onboarding.getProductId()), DEFAULT_ERROR.getCode()))
.onItem().transformToUni(product -> {

/* if PT and product is not delegable, throw an exception */
if(InstitutionType.PT == onboarding.getInstitution().getInstitutionType() && !product.isDelegable()) {
return Uni.createFrom().failure(new OnboardingNotAllowedException(String.format(ONBOARDING_NOT_ALLOWED_ERROR_MESSAGE_NOT_DELEGABLE,
onboarding.getInstitution().getTaxCode(),
onboarding.getProductId()), DEFAULT_ERROR.getCode()));
}

validateProductRole(userRequests, Objects.nonNull(product.getParent())
? product.getParent().getRoleMappings()
: product.getRoleMappings());

return verifyAlreadyOnboardingForProductAndProductParent(onboarding, product);
});
.onItem().transformToUni(product -> verifyAlreadyOnboardingForProductAndProductParent(onboarding.getInstitution().getTaxCode(), onboarding.getInstitution().getSubunitCode(),
product.getId(), product.getParentId())
.replaceWith(product));
}

private Uni<Onboarding> verifyAlreadyOnboardingForProductAndProductParent(Onboarding onboarding, Product product) {
String institutionTaxCode = onboarding.getInstitution().getTaxCode();
String institutionSubunitCode = onboarding.getInstitution().getSubunitCode();

return (Objects.nonNull(product.getParent())
private Uni<Boolean> verifyAlreadyOnboardingForProductAndProductParent(String institutionTaxCode, String institutionSubunitCode,
String productId, String productParentId) {
return (Objects.nonNull(productParentId)
//If product has parent, I must verify if onboarding is present for parent and child
? checkIfAlreadyOnboardingAndValidateAllowedMap(product.getParentId(), institutionTaxCode, institutionSubunitCode)
.onFailure(InvalidRequestException.class).recoverWithUni(ignore -> checkIfAlreadyOnboardingAndValidateAllowedMap(product.getId(), institutionTaxCode, institutionSubunitCode))
? checkIfAlreadyOnboardingAndValidateAllowedMap(productParentId, institutionTaxCode, institutionSubunitCode)
.onFailure(InvalidRequestException.class)
.recoverWithUni(ignore -> checkIfAlreadyOnboardingAndValidateAllowedMap(productId, institutionTaxCode, institutionSubunitCode))
//If product is a root, I must only verify if onboarding for root
: checkIfAlreadyOnboardingAndValidateAllowedMap(product.getId(), institutionTaxCode, institutionSubunitCode)
).replaceWith(onboarding);
: checkIfAlreadyOnboardingAndValidateAllowedMap(productId, institutionTaxCode, institutionSubunitCode)
);
}

private Uni<Boolean> checkIfAlreadyOnboardingAndValidateAllowedMap(String productId, String institutionTaxCode, String institutionSubuniCode) {
Expand All @@ -309,25 +295,25 @@ private Uni<Boolean> checkIfAlreadyOnboardingAndValidateAllowedMap(String produc
.replaceWith(Boolean.TRUE);
}

private void validateProductRole(List<UserRequest> users, Map<PartyRole, ProductRoleInfo> roleMappings) {
private String retrieveProductRole(UserRequest userInfo, Map<PartyRole, ProductRoleInfo> roleMappings) {
try {
if(Objects.isNull(roleMappings) || roleMappings.isEmpty())
throw new IllegalArgumentException("Role mappings is required");
users.forEach(userInfo -> {
if(Objects.isNull(roleMappings.get(userInfo.getRole())))
throw new IllegalArgumentException(String.format(ATLEAST_ONE_PRODUCT_ROLE_REQUIRED, userInfo.getRole()));
if(Objects.isNull((roleMappings.get(userInfo.getRole()).getRoles())))
throw new IllegalArgumentException(String.format(ATLEAST_ONE_PRODUCT_ROLE_REQUIRED, userInfo.getRole()));
if(roleMappings.get(userInfo.getRole()).getRoles().size() != 1)
throw new IllegalArgumentException(String.format(MORE_THAN_ONE_PRODUCT_ROLE_AVAILABLE, userInfo.getRole()));
userInfo.setProductRole(roleMappings.get(userInfo.getRole()).getRoles().get(0).getCode());
});

if(Objects.isNull(roleMappings.get(userInfo.getRole())))
throw new IllegalArgumentException(String.format(ATLEAST_ONE_PRODUCT_ROLE_REQUIRED, userInfo.getRole()));
if(Objects.isNull((roleMappings.get(userInfo.getRole()).getRoles())))
throw new IllegalArgumentException(String.format(ATLEAST_ONE_PRODUCT_ROLE_REQUIRED, userInfo.getRole()));
if(roleMappings.get(userInfo.getRole()).getRoles().size() != 1)
throw new IllegalArgumentException(String.format(MORE_THAN_ONE_PRODUCT_ROLE_AVAILABLE, userInfo.getRole()));
return roleMappings.get(userInfo.getRole()).getRoles().get(0).getCode();

} catch (IllegalArgumentException e){
throw new OnboardingNotAllowedException(e.getMessage(), DEFAULT_ERROR.getCode());
}
}

public Uni<List<User>> validationRoleAndRetrieveUsers(List<UserRequest> users, String onboardingId) {
public Uni<List<User>> validationRoleAndRetrieveUsers(List<UserRequest> users, String onboardingId, Product product) {

List<PartyRole> validRoles = List.of(PartyRole.MANAGER, PartyRole.DELEGATE);

Expand All @@ -342,6 +328,10 @@ public Uni<List<User>> validationRoleAndRetrieveUsers(List<UserRequest> users, S
CustomError.ROLES_NOT_ADMITTED_ERROR.getCode()));
}

Map<PartyRole, ProductRoleInfo> roleMappings = Objects.nonNull(product.getParent())
? product.getParent().getRoleMappings()
: product.getRoleMappings();

return Multi.createFrom().iterable(users)
.onItem().transformToUni(user -> userRegistryApi
.searchUsingPOST(USERS_FIELD_LIST, new UserSearchDto().fiscalCode(user.getTaxCode()))
Expand All @@ -358,6 +348,7 @@ public Uni<List<User>> validationRoleAndRetrieveUsers(List<UserRequest> users, S
.onItem().transform(userResourceId -> User.builder()
.id(userResourceId.toString())
.role(user.getRole())
.productRole(retrieveProductRole(user, roleMappings))
.build())
)
.concatenate().collect().asList();
Expand Down Expand Up @@ -436,7 +427,11 @@ public Uni<OnboardingGet> approve(String 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(product -> verifyAlreadyOnboardingForProductAndProductParent(onboarding.getInstitution().getTaxCode(),
onboarding.getInstitution().getSubunitCode(),
product.getId(),
product.getParentId()))
.replaceWith(onboarding)
)
.onItem().transformToUni(onboarding -> onboardingOrchestrationEnabled
? orchestrationApi.apiStartOnboardingOrchestrationGet(onboardingId, null)
Expand Down Expand Up @@ -479,7 +474,11 @@ private Uni<Onboarding> complete(String onboardingId, File contract, Function<On
.onItem().transformToUni(verificationContractSignature::apply)
//Fail if onboarding exists for a product
.onItem().transformToUni(onboarding -> product(onboarding.getProductId())
.onItem().transformToUni(product -> verifyAlreadyOnboardingForProductAndProductParent(onboarding, product))
.onItem().transformToUni(product -> verifyAlreadyOnboardingForProductAndProductParent(onboarding.getInstitution().getTaxCode(),
onboarding.getInstitution().getSubunitCode(),
product.getId(),
product.getParentId()))
.replaceWith(onboarding)
)
//Upload contract on storage
.onItem().transformToUni(onboarding -> uploadSignedContractAndUpdateToken(onboardingId, contract)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,31 @@
import it.pagopa.selfcare.onboarding.common.ProductId;
import it.pagopa.selfcare.onboarding.entity.Onboarding;
import it.pagopa.selfcare.onboarding.exception.InvalidRequestException;
import it.pagopa.selfcare.onboarding.exception.OnboardingNotAllowedException;
import it.pagopa.selfcare.product.entity.Product;

import java.util.Objects;

import static it.pagopa.selfcare.onboarding.constants.CustomError.DEFAULT_ERROR;

public class OnboardingUtils {

private static final String ADDITIONAL_INFORMATIONS_REQUIRED = "Additional Informations is required when institutionType is GSP and productId is pagopa";
private static final String OTHER_NOTE_REQUIRED = "Other Note is required when other boolean are false";
private static final String BILLING_OR_RECIPIENT_CODE_REQUIRED = "Billing and/or recipient code are required";
private static final String ONBOARDING_NOT_ALLOWED_ERROR_MESSAGE_NOT_DELEGABLE = "Institution with external id '%s' is not allowed to onboard '%s' product because it is not delegable";

public static Uni<Onboarding> customValidationOnboardingData(Onboarding onboarding, Product product) {

/* if PT and product is not delegable, throw an exception */
if(InstitutionType.PT == onboarding.getInstitution().getInstitutionType() && !product.isDelegable()) {
throw new OnboardingNotAllowedException(String.format(ONBOARDING_NOT_ALLOWED_ERROR_MESSAGE_NOT_DELEGABLE,
onboarding.getInstitution().getTaxCode(),
onboarding.getProductId()), DEFAULT_ERROR.getCode());
}

public static Uni<Onboarding> customValidationOnboardingData(Onboarding onboarding) {
if(InstitutionType.PA.equals(onboarding.getInstitution().getInstitutionType()) &&
!ProductId.PROD_INTEROP.getValue().equals(onboarding.getProductId())){
!ProductId.PROD_INTEROP.getValue().equals(onboarding.getProductId())){
if(Objects.isNull(onboarding.getBilling()) || Objects.isNull(onboarding.getBilling().getRecipientCode()))
return Uni.createFrom().failure(new InvalidRequestException(BILLING_OR_RECIPIENT_CODE_REQUIRED));
}
Expand Down
Loading
Loading