diff --git a/src/main/java/it/gov/pagopa/admissibility/mapper/Onboarding2EvaluationMapper.java b/src/main/java/it/gov/pagopa/admissibility/mapper/Onboarding2EvaluationMapper.java index be9c29ad..3dc5c2dc 100644 --- a/src/main/java/it/gov/pagopa/admissibility/mapper/Onboarding2EvaluationMapper.java +++ b/src/main/java/it/gov/pagopa/admissibility/mapper/Onboarding2EvaluationMapper.java @@ -45,7 +45,9 @@ private EvaluationCompletedDTO getEvaluationCompletedDTO(OnboardingDTO onboardin out.setBeneficiaryBudget(initiative.getBeneficiaryInitiativeBudget()); out.setInitiativeRewardType(initiative.getInitiativeRewardType()); out.setIsLogoPresent(initiative.getIsLogoPresent()); - setRankingValue(onboardingDTO, initiative, out); + if(onboardingDTO.getIsee()!=null) { + setRankingValue(onboardingDTO, initiative, out); + } } return out; diff --git a/src/main/java/it/gov/pagopa/admissibility/service/onboarding/AdmissibilityEvaluatorMediatorServiceImpl.java b/src/main/java/it/gov/pagopa/admissibility/service/onboarding/AdmissibilityEvaluatorMediatorServiceImpl.java index 805ce4ee..b880b258 100644 --- a/src/main/java/it/gov/pagopa/admissibility/service/onboarding/AdmissibilityEvaluatorMediatorServiceImpl.java +++ b/src/main/java/it/gov/pagopa/admissibility/service/onboarding/AdmissibilityEvaluatorMediatorServiceImpl.java @@ -8,8 +8,8 @@ import it.gov.pagopa.admissibility.dto.rule.InitiativeGeneralDTO; import it.gov.pagopa.admissibility.enums.OnboardingEvaluationStatus; import it.gov.pagopa.admissibility.exception.OnboardingException; -import it.gov.pagopa.admissibility.exception.WaitingFamilyOnBoardingException; import it.gov.pagopa.admissibility.exception.SkipAlreadyRankingFamilyOnBoardingException; +import it.gov.pagopa.admissibility.exception.WaitingFamilyOnBoardingException; import it.gov.pagopa.admissibility.mapper.Onboarding2EvaluationMapper; import it.gov.pagopa.admissibility.model.InitiativeConfig; import it.gov.pagopa.admissibility.service.AdmissibilityErrorNotifierService; @@ -25,6 +25,7 @@ import it.gov.pagopa.common.utils.CommonUtilities; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.tuple.Pair; +import org.jetbrains.annotations.NotNull; import org.springframework.beans.factory.annotation.Value; import org.springframework.messaging.Message; import org.springframework.stereotype.Service; @@ -40,6 +41,7 @@ @Service @Slf4j public class AdmissibilityEvaluatorMediatorServiceImpl implements AdmissibilityEvaluatorMediatorService { + private static final List REJECTION_REASON_CHECK_DATE_FAIL = List.of(OnboardingConstants.REJECTION_REASON_TC_CONSENSUS_DATETIME_FAIL, OnboardingConstants.REJECTION_REASON_CRITERIA_CONSENSUS_DATETIME_FAIL); private final int maxOnboardingRequestRetry; @@ -162,10 +164,10 @@ private Mono execute(Message message, OnboardingDTO onboa if (onboardingRequest != null) { EvaluationDTO rejectedRequest = evaluateOnboardingChecks(onboardingRequest, initiativeConfig, onboardingContext); if (rejectedRequest != null) { - return Mono.just(rejectedRequest); + return checkRejectionType(message, onboardingRequest, initiativeConfig, rejectedRequest); } else { log.debug("[ONBOARDING_REQUEST] [ONBOARDING_CHECK] onboarding of user {} into initiative {} resulted into successful preliminary checks", onboardingRequest.getUserId(), onboardingRequest.getInitiativeId()); - return checkOnboardingFamily(onboardingRequest, initiativeConfig, message) + return checkOnboardingFamily(onboardingRequest, initiativeConfig, message, true) .switchIfEmpty(retrieveAuthoritiesDataAndEvaluateRequest(onboardingRequest, initiativeConfig, message)) .onErrorResume(WaitingFamilyOnBoardingException.class, e -> Mono.empty()) @@ -197,6 +199,20 @@ private Mono execute(Message message, OnboardingDTO onboa } } + @NotNull + private Mono checkRejectionType(Message message, OnboardingDTO onboardingRequest, InitiativeConfig initiativeConfig, EvaluationDTO rejectedRequest) { + if(rejectedRequest instanceof EvaluationCompletedDTO completedDTO + && initiativeConfig !=null + && InitiativeGeneralDTO.BeneficiaryTypeEnum.NF.equals(initiativeConfig.getBeneficiaryType()) + && completedDTO.getOnboardingRejectionReasons().stream().anyMatch(o -> REJECTION_REASON_CHECK_DATE_FAIL.contains(o.getCode()))){ + return checkOnboardingFamily(onboardingRequest, initiativeConfig, message, false) + .switchIfEmpty(Mono.just(rejectedRequest)) + .onErrorResume(WaitingFamilyOnBoardingException.class, e -> Mono.empty()) + .onErrorResume(SkipAlreadyRankingFamilyOnBoardingException.class, e -> Mono.empty()); + } + return Mono.just(rejectedRequest); + } + private static String readRetryHeader(Message message) { Object retryHeader = message.getHeaders().get(KafkaConstants.ERROR_MSG_HEADER_RETRY); @@ -223,9 +239,9 @@ private EvaluationDTO evaluateOnboardingChecks(OnboardingDTO onboardingRequest, } else return null; } - private Mono checkOnboardingFamily(OnboardingDTO onboardingRequest, InitiativeConfig initiativeConfig, Message message) { + private Mono checkOnboardingFamily(OnboardingDTO onboardingRequest, InitiativeConfig initiativeConfig, Message message, boolean retrieveFamily) { if(isFamilyInitiative(initiativeConfig)){ - return onboardingFamilyEvaluationService.checkOnboardingFamily(onboardingRequest, initiativeConfig, message); + return onboardingFamilyEvaluationService.checkOnboardingFamily(onboardingRequest, initiativeConfig, message, retrieveFamily); } else { return Mono.empty(); } diff --git a/src/main/java/it/gov/pagopa/admissibility/service/onboarding/family/OnboardingFamilyEvaluationService.java b/src/main/java/it/gov/pagopa/admissibility/service/onboarding/family/OnboardingFamilyEvaluationService.java index 58b1a441..0b834991 100644 --- a/src/main/java/it/gov/pagopa/admissibility/service/onboarding/family/OnboardingFamilyEvaluationService.java +++ b/src/main/java/it/gov/pagopa/admissibility/service/onboarding/family/OnboardingFamilyEvaluationService.java @@ -12,6 +12,6 @@ * If already exists an onboarding it will demand to {@link ExistentFamilyHandlerService} to handle the request, otherwise to {@link FamilyDataRetrieverFacadeService} * */ public interface OnboardingFamilyEvaluationService { - Mono checkOnboardingFamily(OnboardingDTO onboardingRequest, InitiativeConfig initiativeConfig, Message message); + Mono checkOnboardingFamily(OnboardingDTO onboardingRequest, InitiativeConfig initiativeConfig, Message message, boolean retrieveFamily); Mono updateOnboardingFamilyOutcome(Family family, InitiativeConfig initiativeConfig, EvaluationDTO result); } diff --git a/src/main/java/it/gov/pagopa/admissibility/service/onboarding/family/OnboardingFamilyEvaluationServiceImpl.java b/src/main/java/it/gov/pagopa/admissibility/service/onboarding/family/OnboardingFamilyEvaluationServiceImpl.java index ad97e111..7d97bd30 100644 --- a/src/main/java/it/gov/pagopa/admissibility/service/onboarding/family/OnboardingFamilyEvaluationServiceImpl.java +++ b/src/main/java/it/gov/pagopa/admissibility/service/onboarding/family/OnboardingFamilyEvaluationServiceImpl.java @@ -1,5 +1,6 @@ package it.gov.pagopa.admissibility.service.onboarding.family; +import it.gov.pagopa.admissibility.connector.repository.OnboardingFamiliesRepository; import it.gov.pagopa.admissibility.dto.onboarding.EvaluationCompletedDTO; import it.gov.pagopa.admissibility.dto.onboarding.EvaluationDTO; import it.gov.pagopa.admissibility.dto.onboarding.OnboardingDTO; @@ -8,7 +9,6 @@ import it.gov.pagopa.admissibility.enums.OnboardingFamilyEvaluationStatus; import it.gov.pagopa.admissibility.model.InitiativeConfig; import it.gov.pagopa.admissibility.model.OnboardingFamilies; -import it.gov.pagopa.admissibility.connector.repository.OnboardingFamiliesRepository; import lombok.extern.slf4j.Slf4j; import org.springframework.messaging.Message; import org.springframework.stereotype.Service; @@ -35,14 +35,16 @@ public OnboardingFamilyEvaluationServiceImpl(OnboardingFamiliesRepository onboar } @Override - public Mono checkOnboardingFamily(OnboardingDTO onboardingRequest, InitiativeConfig initiativeConfig, Message message) { + public Mono checkOnboardingFamily(OnboardingDTO onboardingRequest, InitiativeConfig initiativeConfig, Message message, boolean retrieveFamily) { log.debug("[ONBOARDING_REQUEST] Checking if user family has been onboarded: userId {}; initiativeId {}", onboardingRequest.getUserId(), onboardingRequest.getInitiativeId()); return onboardingFamiliesRepository.findByMemberIdsInAndInitiativeId(onboardingRequest.getUserId(), onboardingRequest.getInitiativeId()) .collectSortedList(COMPARATOR_FAMILIES_CREATE_DATE_DESC) .flatMap(f -> { if (f.isEmpty()) { - return familyDataRetrieverFacadeService.retrieveFamily(onboardingRequest, initiativeConfig, message); + return retrieveFamily ? + familyDataRetrieverFacadeService.retrieveFamily(onboardingRequest, initiativeConfig, message) + : Mono.empty(); } else { return existentFamilyHandlerService.handleExistentFamily(onboardingRequest, f.get(0), initiativeConfig, message); } diff --git a/src/test/java/it/gov/pagopa/admissibility/service/onboarding/AdmissibilityEvaluatorMediatorServiceImplTest.java b/src/test/java/it/gov/pagopa/admissibility/service/onboarding/AdmissibilityEvaluatorMediatorServiceImplTest.java index f2cacb24..27ee18ae 100644 --- a/src/test/java/it/gov/pagopa/admissibility/service/onboarding/AdmissibilityEvaluatorMediatorServiceImplTest.java +++ b/src/test/java/it/gov/pagopa/admissibility/service/onboarding/AdmissibilityEvaluatorMediatorServiceImplTest.java @@ -12,6 +12,7 @@ import it.gov.pagopa.admissibility.exception.WaitingFamilyOnBoardingException; import it.gov.pagopa.admissibility.mapper.Onboarding2EvaluationMapper; import it.gov.pagopa.admissibility.model.InitiativeConfig; +import it.gov.pagopa.admissibility.model.Order; import it.gov.pagopa.admissibility.service.AdmissibilityErrorNotifierService; import it.gov.pagopa.admissibility.service.onboarding.evaluate.OnboardingRequestEvaluatorService; import it.gov.pagopa.admissibility.service.onboarding.family.OnboardingFamilyEvaluationService; @@ -24,9 +25,11 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.data.domain.Sort; import org.springframework.messaging.Message; import org.springframework.messaging.support.GenericMessage; import org.springframework.messaging.support.MessageBuilder; @@ -264,22 +267,22 @@ void mediatorTestWhenFamilyInitiative() { Mockito.when(onboardingCheckServiceMock.check(Mockito.any(), Mockito.same(initiativeConfig), Mockito.any())).thenReturn(null); - Mockito.when(onboardingFamilyEvaluationServiceMock.checkOnboardingFamily(onboarding_first, initiativeConfig, msgs.get(0))).thenAnswer(i -> { + Mockito.when(onboardingFamilyEvaluationServiceMock.checkOnboardingFamily(onboarding_first, initiativeConfig, msgs.get(0), true)).thenAnswer(i -> { i.getArgument(0, OnboardingDTO.class).setFamily(family1); onboarding_first.setFamily(family1); return Mono.empty(); }); - Mockito.when(onboardingFamilyEvaluationServiceMock.checkOnboardingFamily(onboarding_waitingFirst, initiativeConfig, msgs.get(1))).thenAnswer(i -> { + Mockito.when(onboardingFamilyEvaluationServiceMock.checkOnboardingFamily(onboarding_waitingFirst, initiativeConfig, msgs.get(1), true)).thenAnswer(i -> { i.getArgument(0, OnboardingDTO.class).setFamily(family2); onboarding_waitingFirst.setFamily(family2); return Mono.error(new WaitingFamilyOnBoardingException()); }); - Mockito.when(onboardingFamilyEvaluationServiceMock.checkOnboardingFamily(onboarding_familyOk, initiativeConfig, msgs.get(2))).thenAnswer(i -> { + Mockito.when(onboardingFamilyEvaluationServiceMock.checkOnboardingFamily(onboarding_familyOk, initiativeConfig, msgs.get(2), true)).thenAnswer(i -> { i.getArgument(0, OnboardingDTO.class).setFamily(family3); onboarding_familyOk.setFamily(family3); return Mono.just(expectedEvaluationOnboardingFamilyOk); }); - Mockito.when(onboardingFamilyEvaluationServiceMock.checkOnboardingFamily(onboarding_familyKo, initiativeConfig, msgs.get(3))).thenAnswer(i -> { + Mockito.when(onboardingFamilyEvaluationServiceMock.checkOnboardingFamily(onboarding_familyKo, initiativeConfig, msgs.get(3), true)).thenAnswer(i -> { i.getArgument(0, OnboardingDTO.class).setFamily(family4); onboarding_familyKo.setFamily(family4); return Mono.just(expectedEvaluationOnboardingFamilyKo); @@ -316,6 +319,66 @@ void mediatorTestWhenFamilyInitiative() { checkCommits(checkpointers); } + @Test + void mediatorTestWhenFamilyOuterInitiative() { + // Given + String initiativeId = "INITIATIVEID"; + String userId = "USERID"; + OnboardingDTO onboarding = OnboardingDTO.builder().userId(userId).initiativeId(initiativeId).build(); + + InitiativeConfig initiativeConfig = InitiativeConfig.builder() + .initiativeId(initiativeId) + .rankingInitiative(true) + .rankingFields(List.of(Order.builder().fieldCode(OnboardingConstants.CRITERIA_CODE_ISEE).direction(Sort.Direction.ASC).build())) + .beneficiaryType(InitiativeGeneralDTO.BeneficiaryTypeEnum.NF) + .build(); + + Mockito.when(onboardingContextHolderServiceMock.getInitiativeConfig(initiativeId)).thenReturn(Mono.just(initiativeConfig)); + + List checkpointers= new ArrayList<>(1); + List> msgs = Stream.of(onboarding) + .map(TestUtils::jsonSerializer) + .map(s -> { + Checkpointer checkpointer = Mockito.mock(Checkpointer.class); + Mockito.when(checkpointer.success()).thenReturn(Mono.empty()); + checkpointers.add(checkpointer); + return MessageBuilder.withPayload(s) + .setHeader(AzureHeaders.CHECKPOINTER, checkpointer); + } + ) + .map(MessageBuilder::build).toList(); + + Flux> onboardingFlux = Flux.fromIterable(msgs); + + Mockito.when(onboardingCheckServiceMock.check(Mockito.any(), Mockito.same(initiativeConfig), Mockito.any())) + .thenReturn(OnboardingRejectionReason.builder() + .type(OnboardingRejectionReason.OnboardingRejectionReasonType.INVALID_REQUEST) + .code(OnboardingConstants.REJECTION_REASON_TC_CONSENSUS_DATETIME_FAIL).build()); + + Mockito.when(onboardingFamilyEvaluationServiceMock.checkOnboardingFamily(onboarding, initiativeConfig, msgs.get(0), false)) + .thenReturn(Mono.empty()); + + Mockito.when(onboardingNotifierServiceMock.notify(Mockito.any())).thenReturn(true); + + // When + admissibilityEvaluatorMediatorService.execute(onboardingFlux); + + // Then + Mockito.verifyNoInteractions(admissibilityErrorNotifierServiceMock); + + Mockito.verify(onboardingCheckServiceMock).check(Mockito.eq(onboarding), Mockito.same(initiativeConfig), Mockito.any()); + + Mockito.verify(onboardingNotifierServiceMock).notify(Mockito.any()); + + ArgumentCaptor argument = ArgumentCaptor.forClass(EvaluationCompletedDTO.class); + Mockito.verify(onboardingNotifierServiceMock).notify(argument.capture()); + Assertions.assertEquals(argument.getValue().getOnboardingRejectionReasons(), List.of(OnboardingRejectionReason.builder() + .type(OnboardingRejectionReason.OnboardingRejectionReasonType.INVALID_REQUEST) + .code(OnboardingConstants.REJECTION_REASON_TC_CONSENSUS_DATETIME_FAIL).build())); + + checkCommits(checkpointers); + } + private static void checkCommits(List checkpointers) { TestUtils.wait(100, TimeUnit.MILLISECONDS); checkpointers.forEach(c -> Mockito.verify(c).success()); diff --git a/src/test/java/it/gov/pagopa/admissibility/service/onboarding/family/OnboardingFamilyEvaluationServiceTest.java b/src/test/java/it/gov/pagopa/admissibility/service/onboarding/family/OnboardingFamilyEvaluationServiceTest.java index 4686a939..9ebb375b 100644 --- a/src/test/java/it/gov/pagopa/admissibility/service/onboarding/family/OnboardingFamilyEvaluationServiceTest.java +++ b/src/test/java/it/gov/pagopa/admissibility/service/onboarding/family/OnboardingFamilyEvaluationServiceTest.java @@ -20,6 +20,7 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; +import org.junit.jupiter.params.provider.ValueSource; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; @@ -66,15 +67,16 @@ void testNewFamily(){ Mockito.when(familyDataRetrieverFacadeServiceMock.retrieveFamily(Mockito.same(request), Mockito.same(initiativeConfig), Mockito.same(expectedMessage))).thenReturn(Mono.just(expectedResult)); // When - EvaluationDTO result = service.checkOnboardingFamily(request, initiativeConfig, expectedMessage).block(); + EvaluationDTO result = service.checkOnboardingFamily(request, initiativeConfig, expectedMessage, true).block(); // Then Assertions.assertEquals(expectedResult, result); } - @Test - void testExistentFamily(){ + @ParameterizedTest + @ValueSource(booleans = {true, false}) + void testExistentFamily(boolean retrieveFamily){ // Given OnboardingDTO request = OnboardingDTOFaker.mockInstance(0, "INITIATIVEID"); InitiativeConfig initiativeConfig = new InitiativeConfig(); @@ -93,7 +95,7 @@ void testExistentFamily(){ Mockito.when(existentFamilyHandlerServiceMock.handleExistentFamily(Mockito.same(request), Mockito.same(f2), Mockito.same(initiativeConfig), Mockito.same(expectedMessage))).thenReturn(Mono.just(expectedResult)); // When - EvaluationDTO result = service.checkOnboardingFamily(request, initiativeConfig, expectedMessage).block(); + EvaluationDTO result = service.checkOnboardingFamily(request, initiativeConfig, expectedMessage, retrieveFamily).block(); // Then Assertions.assertEquals(expectedResult, result); @@ -143,4 +145,22 @@ void testUpdateOnboardingFamilyOutcome_Ranking(){ // Then Assertions.assertSame(result, evaluation); } + + @Test + void testNewFamilyNotRetrieve(){ + // Given + OnboardingDTO request = OnboardingDTOFaker.mockInstance(0, "INITIATIVEID"); + InitiativeConfig initiativeConfig = new InitiativeConfig(); + + @SuppressWarnings("unchecked") Message expectedMessage = Mockito.mock(Message.class); + + Mockito.when(onboardingFamiliesRepositoryMock.findByMemberIdsInAndInitiativeId(request.getUserId(), request.getInitiativeId())) + .thenReturn(Flux.empty()); + + // When + EvaluationDTO result = service.checkOnboardingFamily(request, initiativeConfig, expectedMessage, false).block(); + + // Then + Assertions.assertNull(result); + } }