From 658ad5171b6cb2c81432ec8dd7a291bc5526f25e Mon Sep 17 00:00:00 2001 From: aacitelli Date: Tue, 17 Jan 2023 15:58:54 +0100 Subject: [PATCH 1/5] [PAGOPA-627] get call: refactoring from httpTrigger to spring rest call --- .../pagopa/afm/utils/ImportCDIFunction.java | 165 +---------------- .../utils/controller/ImportCDIController.java | 38 ++++ .../repository/CDICollectionRepository.java | 6 +- .../pagopa/afm/utils/service/CDIService.java | 175 ++++++++++++++++++ .../afm/utils/ImportCDIFunctionTest.java | 37 ++-- .../afm/utils/ImportCDIHandlerTest.java | 11 +- .../controller/ImportCDIControllerTest.java | 48 +++++ .../afm/utils/service/CDIServiceTest.java | 13 +- 8 files changed, 314 insertions(+), 179 deletions(-) create mode 100644 src/main/java/it/gov/pagopa/afm/utils/controller/ImportCDIController.java create mode 100644 src/test/java/it/gov/pagopa/afm/utils/controller/ImportCDIControllerTest.java diff --git a/src/main/java/it/gov/pagopa/afm/utils/ImportCDIFunction.java b/src/main/java/it/gov/pagopa/afm/utils/ImportCDIFunction.java index 11056657..ef6985a0 100644 --- a/src/main/java/it/gov/pagopa/afm/utils/ImportCDIFunction.java +++ b/src/main/java/it/gov/pagopa/afm/utils/ImportCDIFunction.java @@ -1,189 +1,34 @@ package it.gov.pagopa.afm.utils; -import java.time.LocalDate; -import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.function.Function; -import org.apache.commons.lang3.SerializationUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import org.springframework.util.CollectionUtils; -import com.azure.cosmos.implementation.apachecommons.lang.StringUtils; - -import feign.FeignException; -import it.gov.pagopa.afm.utils.entity.CDI; -import it.gov.pagopa.afm.utils.entity.Detail; -import it.gov.pagopa.afm.utils.entity.ServiceAmount; -import it.gov.pagopa.afm.utils.entity.StatusType; -import it.gov.pagopa.afm.utils.exception.AppError; -import it.gov.pagopa.afm.utils.exception.AppException; -import it.gov.pagopa.afm.utils.model.bundle.BundleRequest; import it.gov.pagopa.afm.utils.model.bundle.BundleResponse; -import it.gov.pagopa.afm.utils.model.bundle.BundleType; import it.gov.pagopa.afm.utils.model.bundle.CDIWrapper; -import it.gov.pagopa.afm.utils.model.bundle.PaymentMethodType; -import it.gov.pagopa.afm.utils.model.bundle.TouchpointType; import it.gov.pagopa.afm.utils.service.CDIService; -import it.gov.pagopa.afm.utils.service.MarketPlaceClient; import lombok.AllArgsConstructor; import lombok.NoArgsConstructor; -import lombok.extern.slf4j.Slf4j; import reactor.core.publisher.Mono; @Component -@Slf4j @NoArgsConstructor @AllArgsConstructor -public class ImportCDIFunction implements Function, Mono>>{ - - @Autowired(required=false) - private MarketPlaceClient marketPlaceClient; +public class ImportCDIFunction implements Function, Mono>> { - @Autowired(required=false) + @Autowired(required = false) private CDIService cdiService; - @Override - public Mono> apply(Mono input) { - - List bundleResponses = new ArrayList<>(); - - return input.map(wrapper -> { - - // the status of the items is put on PROCESSING to identify that these records are not in a final state - // *** @CosmosDBTrigger doesn't need of this step -> remove when change to this kind of function *** - this.setCDIToProcessingStatus(wrapper.getCdiItems()); - - for (CDI cdi: wrapper.getCdiItems()) { - // processed only cdis not in FAILED status - if (null != cdi.getCdiStatus() && !cdi.getCdiStatus().equals(StatusType.FAILED)) { - String idPsp = cdi.getIdPsp(); - List bundleRequestList = this.createBundlesByCDI(cdi); - try { - // create marketplace bundle - Optional.ofNullable(this.createBundleByList(idPsp, bundleRequestList)).ifPresent(bundleResponses::addAll); - // success -> delete the CDI - Optional.ofNullable(cdiService).ifPresent(result -> - { - cdiService.deleteCDI(cdi); - log.info(String.format("SUCCESS Bundles creation -> CDI deleted [idCdi=%s]", cdi.getIdCdi())); - }); - } - catch (AppException e) { - log.error("Error during the creation of the MarketPlace Bundles [idPsp= "+idPsp+", idCdi="+cdi.getIdCdi()+"]", e); - // error -> set CDI status to failed - cdi.setCdiStatus(StatusType.FAILED); - cdi.setCdiErrorDesc(e.getMessage()); - CDI updated = Optional.ofNullable(cdiService).map(result -> cdiService.updateCDI(cdi)).orElseGet(() -> CDI.builder().build()); - log.info(String.format("CDI status updated [idCdi=%s, status=%s, errorDesc=%s]", updated.getIdCdi(), updated.getCdiStatus(), updated.getCdiErrorDesc())); - } - - } - } - return bundleResponses; - }); - - } - - public List createBundlesByCDI(CDI cdi) { - List bundleRequestList = new ArrayList<>(); - if (!CollectionUtils.isEmpty(cdi.getDetails())) { - DateTimeFormatter dfDate = DateTimeFormatter.ofPattern("yyyy-MM-dd"); - BundleRequest bundleRequest = new BundleRequest(); - bundleRequest.setIdCdi(cdi.getIdCdi()); - bundleRequest.setDigitalStamp(cdi.getDigitalStamp()); - bundleRequest.setDigitalStampRestriction(Boolean.FALSE); - bundleRequest.setType(BundleType.GLOBAL); - bundleRequest.setTransferCategoryList(null); - bundleRequest.setValidityDateFrom(!StringUtils.isEmpty(cdi.getValidityDateFrom()) ? LocalDate.parse(cdi.getValidityDateFrom(), dfDate) : null); - bundleRequest.setValidityDateTo(null); - for (Detail d: cdi.getDetails()) { - bundleRequest.setIdChannel(d.getIdChannel()); - bundleRequest.setIdBrokerPsp(d.getIdBrokerPsp()); - bundleRequest.setName(d.getName()); - bundleRequest.setDescription(d.getDescription()); - bundleRequest.setPaymentType(d.getPaymentMethod()); - for (ServiceAmount sa: d.getServiceAmount()) { - bundleRequest.setPaymentAmount(sa.getPaymentAmount()); - bundleRequest.setMinPaymentAmount(sa.getMinPaymentAmount()); - bundleRequest.setMaxPaymentAmount(sa.getMaxPaymentAmount()); - this.addBundleByTouchpoint(d, bundleRequestList, bundleRequest); - } - } - } - return bundleRequestList; - } + public Mono> apply(Mono input) { - private void addBundleByTouchpoint(Detail d, List bundleRequestList, BundleRequest bundleRequest) { + return input.map(wrapper -> Optional.ofNullable(cdiService).map(result -> cdiService.syncCDI()) + .orElse(new ArrayList<>())); - boolean isNullTouchPoint = true; - - if (d.getPaymentMethod().equalsIgnoreCase(PaymentMethodType.PO.name())) { - isNullTouchPoint = false; - BundleRequest bundleRequestClone = SerializationUtils.clone(bundleRequest); - bundleRequestClone.setTouchpoint(TouchpointType.PSP.name()); - bundleRequestList.add(bundleRequestClone); - } - if ((d.getPaymentMethod().equalsIgnoreCase(PaymentMethodType.CP.name()) && d.getChannelCardsCart() && d.getChannelApp().equals(Boolean.FALSE)) || - (d.getPaymentMethod().matches("(?i)"+PaymentMethodType.BBT+"|"+PaymentMethodType.BP+"|"+PaymentMethodType.MYBK+"|"+PaymentMethodType.AD) && d.getChannelApp().equals(Boolean.FALSE)) || - (!d.getPaymentMethod().equalsIgnoreCase(PaymentMethodType.PPAL.name()) && d.getChannelApp())) { - isNullTouchPoint = false; - BundleRequest bundleRequestClone = SerializationUtils.clone(bundleRequest); - bundleRequestClone.setTouchpoint(TouchpointType.WISP.name()); - bundleRequestList.add(bundleRequestClone); - } - if ((d.getPaymentMethod().equalsIgnoreCase(PaymentMethodType.CP.name()) && d.getChannelCardsCart() && d.getChannelApp().equals(Boolean.FALSE)) || - (d.getPaymentMethod().equalsIgnoreCase(PaymentMethodType.PPAL.name()) && d.getChannelApp())) { - isNullTouchPoint = false; - BundleRequest bundleRequestClone = SerializationUtils.clone(bundleRequest); - bundleRequestClone.setTouchpoint(TouchpointType.IO.name()); - bundleRequestList.add(bundleRequestClone); - } - if ((d.getPaymentMethod().equalsIgnoreCase(PaymentMethodType.CP.name()) && d.getChannelCardsCart() && d.getChannelApp().equals(Boolean.FALSE))) { - isNullTouchPoint = false; - BundleRequest bundleRequestClone = SerializationUtils.clone(bundleRequest); - bundleRequestClone.setTouchpoint(TouchpointType.CHECKOUT.name()); - bundleRequestList.add(bundleRequestClone); - } - if (isNullTouchPoint) { - // default bundle with null touchpoint value - bundleRequestList.add(bundleRequest); - } - - } - - - private List createBundleByList(String idPsp, List bundleRequestList) throws AppException{ - List response = null; - try { - response = Optional.ofNullable(marketPlaceClient).map(result -> marketPlaceClient.createBundleByList(idPsp, bundleRequestList)).orElseGet(() -> null); - } catch (FeignException.BadRequest e) { - throw new AppException(AppError.BUNDLE_REQUEST_DATA_ERROR, e.getMessage()); - } catch (FeignException.NotFound e) { - throw new AppException(AppError.BUNDLE_NOT_FOUND_ERROR, e.getMessage()); - } catch (FeignException.Conflict e) { - throw new AppException(AppError.BUNDLE_CONFLICT_ERROR, e.getMessage()); - } catch (FeignException.InternalServerError e) { - throw new AppException(AppError.INTERNAL_SERVER_ERROR, e.getMessage()); - } catch (Exception e) { - throw new AppException(AppError.UNKNOWN, e.getMessage()); - } - return response; - } - - // remove when @CosmosDBTrigger function will be used - public void setCDIToProcessingStatus(List items) { - for (CDI cdi: items) { - cdi.setCdiStatus(StatusType.PROCESSING); - CDI updated = Optional.ofNullable(cdiService).map(result -> cdiService.updateCDI(cdi)).orElseGet(() -> CDI.builder().build()); - log.info(String.format("CDI status updated [idCdi=%s, status=%s]", updated.getIdCdi(), updated.getCdiStatus())); - } } - - } diff --git a/src/main/java/it/gov/pagopa/afm/utils/controller/ImportCDIController.java b/src/main/java/it/gov/pagopa/afm/utils/controller/ImportCDIController.java new file mode 100644 index 00000000..75ef54c6 --- /dev/null +++ b/src/main/java/it/gov/pagopa/afm/utils/controller/ImportCDIController.java @@ -0,0 +1,38 @@ +package it.gov.pagopa.afm.utils.controller; + +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import it.gov.pagopa.afm.utils.model.ProblemJson; +import it.gov.pagopa.afm.utils.model.bundle.BundleResponse; +import it.gov.pagopa.afm.utils.service.CDIService; + +@RestController +public class ImportCDIController { + + @Autowired + private CDIService cdiService; + + @Operation(summary = "Call to trigger the import of the CDIs and convert to bundles.", security = {@SecurityRequirement(name = "ApiKey")}, operationId = "syncCDI") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "Obtained bundle list.", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, array = @ArraySchema(schema = @Schema(name = "BundleResponse", implementation = BundleResponse.class)))), + @ApiResponse(responseCode = "500", description = "Service unavailable.", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, schema = @Schema(implementation = ProblemJson.class)))}) + @GetMapping(value = "/cdis/sync", + produces = MediaType.APPLICATION_JSON_VALUE) + ResponseEntity> syncCDI(){ + return new ResponseEntity<>(cdiService.syncCDI(), HttpStatus.OK); + } +} diff --git a/src/main/java/it/gov/pagopa/afm/utils/repository/CDICollectionRepository.java b/src/main/java/it/gov/pagopa/afm/utils/repository/CDICollectionRepository.java index 79b9f80d..43c62f28 100644 --- a/src/main/java/it/gov/pagopa/afm/utils/repository/CDICollectionRepository.java +++ b/src/main/java/it/gov/pagopa/afm/utils/repository/CDICollectionRepository.java @@ -1,12 +1,16 @@ package it.gov.pagopa.afm.utils.repository; +import java.util.List; + import org.springframework.stereotype.Repository; import com.azure.spring.data.cosmos.repository.CosmosRepository; +import com.azure.spring.data.cosmos.repository.Query; import it.gov.pagopa.afm.utils.entity.CDI; @Repository public interface CDICollectionRepository extends CosmosRepository { - + @Query("select * from Items r where r.cdiStatus = 'NEW'") + List getWorkableCDIs(); } diff --git a/src/main/java/it/gov/pagopa/afm/utils/service/CDIService.java b/src/main/java/it/gov/pagopa/afm/utils/service/CDIService.java index 51e56f9c..7e5bd73f 100644 --- a/src/main/java/it/gov/pagopa/afm/utils/service/CDIService.java +++ b/src/main/java/it/gov/pagopa/afm/utils/service/CDIService.java @@ -1,20 +1,49 @@ package it.gov.pagopa.afm.utils.service; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +import org.apache.commons.lang3.SerializationUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; + +import com.azure.cosmos.implementation.apachecommons.lang.StringUtils; +import feign.FeignException; import it.gov.pagopa.afm.utils.entity.CDI; +import it.gov.pagopa.afm.utils.entity.Detail; +import it.gov.pagopa.afm.utils.entity.ServiceAmount; +import it.gov.pagopa.afm.utils.entity.StatusType; +import it.gov.pagopa.afm.utils.exception.AppError; +import it.gov.pagopa.afm.utils.exception.AppException; +import it.gov.pagopa.afm.utils.model.bundle.BundleRequest; +import it.gov.pagopa.afm.utils.model.bundle.BundleResponse; +import it.gov.pagopa.afm.utils.model.bundle.BundleType; +import it.gov.pagopa.afm.utils.model.bundle.PaymentMethodType; +import it.gov.pagopa.afm.utils.model.bundle.TouchpointType; import it.gov.pagopa.afm.utils.repository.CDICollectionRepository; import lombok.AllArgsConstructor; import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; @Service @AllArgsConstructor @NoArgsConstructor +@Setter +@Slf4j public class CDIService { @Autowired private CDICollectionRepository cdisRepository; + @Autowired + private MarketPlaceClient marketPlaceClient; + public CDI updateCDI(CDI cdiEntity) { return cdisRepository.save(cdiEntity); } @@ -22,4 +51,150 @@ public CDI updateCDI(CDI cdiEntity) { public void deleteCDI(CDI cdiEntity) { cdisRepository.delete(cdiEntity); } + + public List getWorkableCDIs() { + return cdisRepository.getWorkableCDIs(); + } + + public List syncCDI() { + return this.turnCDIToBundles(this.getWorkableCDIs()); + } + + + public List turnCDIToBundles(List cdis){ + log.info("CDIService - turnCDIToBundles executed at: " + LocalDateTime.now() + " for CDI list with size: " + cdis.size()); + List bundleResponses = new ArrayList<>(); + // the status of the items is put on PROCESSING to identify that these records are not in a final state + this.setCDIToProcessingStatus(cdis); + for (CDI cdi: cdis) { + // processed only cdis not in FAILED status + if (null != cdi.getCdiStatus() && !cdi.getCdiStatus().equals(StatusType.FAILED)) { + String idPsp = cdi.getIdPsp(); + List bundleRequestList = this.createBundlesByCDI(cdi); + try { + // create marketplace bundle + Optional.ofNullable(this.createBundleByList(idPsp, bundleRequestList)).ifPresent(bundleResponses::addAll); + // success -> delete the CDI + this.deleteCDI(cdi); + log.info(String.format("SUCCESS Bundles creation -> CDI deleted [idCdi=%s]", cdi.getIdCdi())); + + } + catch (AppException e) { + log.error("Error during the creation of the MarketPlace Bundles [idPsp= "+idPsp+", idCdi="+cdi.getIdCdi()+"]", e); + // error -> set CDI status to failed + cdi.setCdiStatus(StatusType.FAILED); + cdi.setCdiErrorDesc(e.getMessage()); + CDI updated = this.updateCDI(cdi); + log.info(String.format("CDI status updated [idCdi=%s, status=%s, errorDesc=%s]", + Optional.ofNullable(updated).map(result -> updated.getIdCdi()), + Optional.ofNullable(updated).map(result -> updated.getCdiStatus()), + Optional.ofNullable(updated).map(result -> updated.getCdiErrorDesc()))); + } + + } + } + return bundleResponses; + + } + + public List createBundlesByCDI(CDI cdi) { + List bundleRequestList = new ArrayList<>(); + if (!CollectionUtils.isEmpty(cdi.getDetails())) { + DateTimeFormatter dfDate = DateTimeFormatter.ofPattern("yyyy-MM-dd"); + BundleRequest bundleRequest = new BundleRequest(); + bundleRequest.setIdCdi(cdi.getIdCdi()); + bundleRequest.setDigitalStamp(cdi.getDigitalStamp()); + bundleRequest.setDigitalStampRestriction(Boolean.FALSE); + bundleRequest.setType(BundleType.GLOBAL); + bundleRequest.setTransferCategoryList(null); + bundleRequest.setValidityDateFrom(!StringUtils.isEmpty(cdi.getValidityDateFrom()) ? LocalDate.parse(cdi.getValidityDateFrom(), dfDate) : null); + bundleRequest.setValidityDateTo(null); + for (Detail d: cdi.getDetails()) { + bundleRequest.setIdChannel(d.getIdChannel()); + bundleRequest.setIdBrokerPsp(d.getIdBrokerPsp()); + bundleRequest.setName(d.getName()); + bundleRequest.setDescription(d.getDescription()); + bundleRequest.setPaymentType(d.getPaymentMethod()); + for (ServiceAmount sa: d.getServiceAmount()) { + bundleRequest.setPaymentAmount(sa.getPaymentAmount()); + bundleRequest.setMinPaymentAmount(sa.getMinPaymentAmount()); + bundleRequest.setMaxPaymentAmount(sa.getMaxPaymentAmount()); + this.addBundleByTouchpoint(d, bundleRequestList, bundleRequest); + } + } + } + return bundleRequestList; + } + + private void addBundleByTouchpoint(Detail d, List bundleRequestList, BundleRequest bundleRequest) { + + boolean isNullTouchPoint = true; + + if (d.getPaymentMethod().equalsIgnoreCase(PaymentMethodType.PO.name())) { + isNullTouchPoint = false; + BundleRequest bundleRequestClone = SerializationUtils.clone(bundleRequest); + bundleRequestClone.setTouchpoint(TouchpointType.PSP.name()); + bundleRequestList.add(bundleRequestClone); + } + if ((d.getPaymentMethod().equalsIgnoreCase(PaymentMethodType.CP.name()) && d.getChannelCardsCart() && d.getChannelApp().equals(Boolean.FALSE)) || + (d.getPaymentMethod().matches("(?i)"+PaymentMethodType.BBT+"|"+PaymentMethodType.BP+"|"+PaymentMethodType.MYBK+"|"+PaymentMethodType.AD) && d.getChannelApp().equals(Boolean.FALSE)) || + (!d.getPaymentMethod().equalsIgnoreCase(PaymentMethodType.PPAL.name()) && d.getChannelApp())) { + isNullTouchPoint = false; + BundleRequest bundleRequestClone = SerializationUtils.clone(bundleRequest); + bundleRequestClone.setTouchpoint(TouchpointType.WISP.name()); + bundleRequestList.add(bundleRequestClone); + } + if ((d.getPaymentMethod().equalsIgnoreCase(PaymentMethodType.CP.name()) && d.getChannelCardsCart() && d.getChannelApp().equals(Boolean.FALSE)) || + (d.getPaymentMethod().equalsIgnoreCase(PaymentMethodType.PPAL.name()) && d.getChannelApp())) { + isNullTouchPoint = false; + BundleRequest bundleRequestClone = SerializationUtils.clone(bundleRequest); + bundleRequestClone.setTouchpoint(TouchpointType.IO.name()); + bundleRequestList.add(bundleRequestClone); + } + if ((d.getPaymentMethod().equalsIgnoreCase(PaymentMethodType.CP.name()) && d.getChannelCardsCart() && d.getChannelApp().equals(Boolean.FALSE))) { + isNullTouchPoint = false; + BundleRequest bundleRequestClone = SerializationUtils.clone(bundleRequest); + bundleRequestClone.setTouchpoint(TouchpointType.CHECKOUT.name()); + bundleRequestList.add(bundleRequestClone); + } + if (isNullTouchPoint) { + // default bundle with null touchpoint value + bundleRequestList.add(bundleRequest); + } + + } + + + private List createBundleByList(String idPsp, List bundleRequestList) throws AppException{ + List response = null; + try { + response = Optional.ofNullable(marketPlaceClient).map(result -> marketPlaceClient.createBundleByList(idPsp, bundleRequestList)).orElseGet(() -> null); + } catch (FeignException.BadRequest e) { + throw new AppException(AppError.BUNDLE_REQUEST_DATA_ERROR, e.getMessage()); + } catch (FeignException.NotFound e) { + throw new AppException(AppError.BUNDLE_NOT_FOUND_ERROR, e.getMessage()); + } catch (FeignException.Conflict e) { + throw new AppException(AppError.BUNDLE_CONFLICT_ERROR, e.getMessage()); + } catch (FeignException.InternalServerError e) { + throw new AppException(AppError.INTERNAL_SERVER_ERROR, e.getMessage()); + } catch (Exception e) { + throw new AppException(AppError.UNKNOWN, e.getMessage()); + } + return response; + } + + // remove when @CosmosDBTrigger function will be used + public void setCDIToProcessingStatus(List items) { + for (CDI cdi: items) { + cdi.setCdiStatus(StatusType.PROCESSING); + CDI updated = this.updateCDI(cdi); + log.info(String.format("CDI status updated [idCdi=%s, status=%s]", + Optional.ofNullable(updated).map(result -> updated.getIdCdi()), + Optional.ofNullable(updated).map(result -> updated.getCdiStatus()))); + } + } + + + + } diff --git a/src/test/java/it/gov/pagopa/afm/utils/ImportCDIFunctionTest.java b/src/test/java/it/gov/pagopa/afm/utils/ImportCDIFunctionTest.java index 22f64764..31cbe5cb 100644 --- a/src/test/java/it/gov/pagopa/afm/utils/ImportCDIFunctionTest.java +++ b/src/test/java/it/gov/pagopa/afm/utils/ImportCDIFunctionTest.java @@ -5,6 +5,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.lenient; import java.util.Arrays; import java.util.List; @@ -14,6 +15,7 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.Mockito; +import org.mockito.Spy; import org.mockito.junit.jupiter.MockitoExtension; import feign.FeignException; @@ -21,6 +23,7 @@ import it.gov.pagopa.afm.utils.entity.StatusType; import it.gov.pagopa.afm.utils.model.bundle.BundleResponse; import it.gov.pagopa.afm.utils.model.bundle.CDIWrapper; +import it.gov.pagopa.afm.utils.repository.CDICollectionRepository; import it.gov.pagopa.afm.utils.service.CDIService; import it.gov.pagopa.afm.utils.service.MarketPlaceClient; import reactor.core.publisher.Mono; @@ -32,22 +35,28 @@ class ImportCDIFunctionTest { private MarketPlaceClient marketPlaceClient; @Mock + private CDICollectionRepository cdisRepository; + + @Spy private CDIService cdiService; @Test void applyTest(){ // precondition + cdiService.setCdisRepository(cdisRepository); + cdiService.setMarketPlaceClient(marketPlaceClient); BundleResponse response = BundleResponse.builder().idBundle("12345").build(); Mockito.when(marketPlaceClient.createBundleByList(eq("201"), any())).thenReturn(Arrays.asList(response)); - EasyRandom generator = new EasyRandom(); CDI cdi = generator.nextObject(CDI.class); cdi.setIdPsp("201"); cdi.setValidityDateFrom("2022-12-15"); cdi.setCdiStatus(StatusType.NEW); + Mockito.when(cdisRepository.getWorkableCDIs()).thenReturn(Arrays.asList(new CDI[] {cdi})); + CDIWrapper input = CDIWrapper.builder().cdiItems(Arrays.asList(new CDI[] {cdi})).build(); - Mono> responses = new ImportCDIFunction(marketPlaceClient, cdiService).apply(Mono.just(input)); + Mono> responses = new ImportCDIFunction(cdiService).apply(Mono.just(input)); assertTrue(responses.block().size() > 0); assertThat(responses.block().get(0).getIdBundle()).isEqualTo("12345"); @@ -56,16 +65,18 @@ void applyTest(){ @Test void applyTest_400(){ // precondition + cdiService.setCdisRepository(cdisRepository); + cdiService.setMarketPlaceClient(marketPlaceClient); EasyRandom generator = new EasyRandom(); CDI cdi = generator.nextObject(CDI.class); cdi.setIdPsp("400"); cdi.setValidityDateFrom("2022-12-15"); cdi.setCdiStatus(StatusType.NEW); - Mockito.when(marketPlaceClient.createBundleByList(eq("400"), any())).thenThrow(FeignException.BadRequest.class); - Mockito.when(cdiService.updateCDI(any(CDI.class))).thenReturn(cdi); + Mockito.when(cdisRepository.getWorkableCDIs()).thenReturn(Arrays.asList(new CDI[] {cdi})); + lenient().when(marketPlaceClient.createBundleByList(eq("400"), any())).thenThrow(FeignException.BadRequest.class); CDIWrapper input = CDIWrapper.builder().cdiItems(Arrays.asList(new CDI[] {cdi})).build(); - Mono> responses = new ImportCDIFunction(marketPlaceClient, cdiService).apply(Mono.just(input)); + Mono> responses = new ImportCDIFunction(cdiService).apply(Mono.just(input)); assertEquals(0,responses.block().size()); } @@ -73,17 +84,19 @@ void applyTest_400(){ @Test void applyTest_409(){ // precondition + cdiService.setCdisRepository(cdisRepository); + cdiService.setMarketPlaceClient(marketPlaceClient); EasyRandom generator = new EasyRandom(); CDI cdi = generator.nextObject(CDI.class); cdi.setIdPsp("409"); cdi.setValidityDateFrom("2022-12-15"); cdi.setCdiStatus(StatusType.NEW); - Mockito.when(marketPlaceClient.createBundleByList(eq("409"), any())).thenThrow(FeignException.Conflict.class); - Mockito.when(cdiService.updateCDI(any(CDI.class))).thenReturn(cdi); + Mockito.when(cdisRepository.getWorkableCDIs()).thenReturn(Arrays.asList(new CDI[] {cdi})); + lenient().when(marketPlaceClient.createBundleByList(eq("409"), any())).thenThrow(FeignException.Conflict.class); CDIWrapper input = CDIWrapper.builder().cdiItems(Arrays.asList(new CDI[] {cdi})).build(); - Mono> responses = new ImportCDIFunction(marketPlaceClient, cdiService).apply(Mono.just(input)); + Mono> responses = new ImportCDIFunction(cdiService).apply(Mono.just(input)); assertEquals(0,responses.block().size()); } @@ -91,17 +104,19 @@ void applyTest_409(){ @Test void applyTest_404(){ // precondition + cdiService.setCdisRepository(cdisRepository); + cdiService.setMarketPlaceClient(marketPlaceClient); EasyRandom generator = new EasyRandom(); CDI cdi = generator.nextObject(CDI.class); cdi.setIdPsp("404"); cdi.setValidityDateFrom("2022-12-15"); cdi.setCdiStatus(StatusType.NEW); - Mockito.when(marketPlaceClient.createBundleByList(eq("404"), any())).thenThrow(FeignException.NotFound.class); - Mockito.when(cdiService.updateCDI(any(CDI.class))).thenReturn(cdi); + Mockito.when(cdisRepository.getWorkableCDIs()).thenReturn(Arrays.asList(new CDI[] {cdi})); + lenient().when(marketPlaceClient.createBundleByList(eq("404"), any())).thenThrow(FeignException.NotFound.class); CDIWrapper input = CDIWrapper.builder().cdiItems(Arrays.asList(new CDI[] {cdi})).build(); - Mono> responses = new ImportCDIFunction(marketPlaceClient, cdiService).apply(Mono.just(input)); + Mono> responses = new ImportCDIFunction(cdiService).apply(Mono.just(input)); assertEquals(0,responses.block().size()); } diff --git a/src/test/java/it/gov/pagopa/afm/utils/ImportCDIHandlerTest.java b/src/test/java/it/gov/pagopa/afm/utils/ImportCDIHandlerTest.java index 14a1a836..3f1bf7e5 100644 --- a/src/test/java/it/gov/pagopa/afm/utils/ImportCDIHandlerTest.java +++ b/src/test/java/it/gov/pagopa/afm/utils/ImportCDIHandlerTest.java @@ -20,12 +20,13 @@ import it.gov.pagopa.afm.utils.model.bundle.BundleRequest; import it.gov.pagopa.afm.utils.model.bundle.BundleResponse; import it.gov.pagopa.afm.utils.model.bundle.CDIWrapper; +import it.gov.pagopa.afm.utils.service.CDIService; @ExtendWith(MockitoExtension.class) class ImportCDIHandlerTest { @Spy - ImportCDIFunction importCDIFunction; + CDIService cdiService; @Test void execute() throws IOException, NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException { @@ -34,7 +35,7 @@ void execute() throws IOException, NoSuchFieldException, SecurityException, Ille List items = new ArrayList<>(); items.add(cdi); - List requests = importCDIFunction.createBundlesByCDI(cdi); + List requests = cdiService.createBundlesByCDI(cdi); //test execution FunctionInvoker> handler = new FunctionInvoker<>(ImportCDIFunction.class); @@ -69,7 +70,7 @@ void executeMultipleTouchPoint() throws IOException { List items = new ArrayList<>(); items.add(cdi); - List requests = importCDIFunction.createBundlesByCDI(cdi); + List requests = cdiService.createBundlesByCDI(cdi); //test execution FunctionInvoker> handler = new FunctionInvoker<>(ImportCDIFunction.class); @@ -104,7 +105,7 @@ void executeMultipleServiceAmount() throws IOException { List items = new ArrayList<>(); items.add(cdi); - List requests = importCDIFunction.createBundlesByCDI(cdi); + List requests = cdiService.createBundlesByCDI(cdi); //test execution FunctionInvoker> handler = new FunctionInvoker<>(ImportCDIFunction.class); @@ -139,7 +140,7 @@ void executePaymentMethodPO() throws IOException, NoSuchFieldException, Security List items = new ArrayList<>(); items.add(cdi); - List requests = importCDIFunction.createBundlesByCDI(cdi); + List requests = cdiService.createBundlesByCDI(cdi); assertEquals(1, requests.size()); assertEquals("PSP", requests.get(0).getTouchpoint()); diff --git a/src/test/java/it/gov/pagopa/afm/utils/controller/ImportCDIControllerTest.java b/src/test/java/it/gov/pagopa/afm/utils/controller/ImportCDIControllerTest.java new file mode 100644 index 00000000..bbb3f2c2 --- /dev/null +++ b/src/test/java/it/gov/pagopa/afm/utils/controller/ImportCDIControllerTest.java @@ -0,0 +1,48 @@ +package it.gov.pagopa.afm.utils.controller; + +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.mockito.Mockito.when; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import java.util.ArrayList; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.MvcResult; + +import it.gov.pagopa.afm.utils.service.CDIService; + +@SpringBootTest +@AutoConfigureMockMvc +class ImportCDIControllerTest { + + @Autowired + private MockMvc mvc; + + @Mock + private CDIService cdiService; + + @BeforeEach + void setUp() { + // precondition + when(cdiService.syncCDI()).thenReturn(new ArrayList<>()); + } + + @Test + void syncCDI() throws Exception { + String url = "/cdis/sync"; + MvcResult result = mvc.perform(get(url).contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON)) + .andReturn(); + assertNotNull(result.getResponse().getContentAsString()); + } +} diff --git a/src/test/java/it/gov/pagopa/afm/utils/service/CDIServiceTest.java b/src/test/java/it/gov/pagopa/afm/utils/service/CDIServiceTest.java index 82ab387e..80f63cb3 100644 --- a/src/test/java/it/gov/pagopa/afm/utils/service/CDIServiceTest.java +++ b/src/test/java/it/gov/pagopa/afm/utils/service/CDIServiceTest.java @@ -14,18 +14,27 @@ class CDIServiceTest { @Mock private CDICollectionRepository cdisRepository; + @Mock + private MarketPlaceClient marketPlaceClient; @Test void deleteTest() { - CDIService cdiService = new CDIService(cdisRepository); + CDIService cdiService = new CDIService(cdisRepository, marketPlaceClient); cdiService.deleteCDI(CDI.builder().build()); assertTrue(true); } @Test void updateTest() { - CDIService cdiService = new CDIService(cdisRepository); + CDIService cdiService = new CDIService(cdisRepository, marketPlaceClient); cdiService.updateCDI(CDI.builder().build()); assertTrue(true); } + + @Test + void getWorkableCDIs() { + CDIService cdiService = new CDIService(cdisRepository, marketPlaceClient); + cdiService.getWorkableCDIs(); + assertTrue(true); + } } From 1522e906d1bf72ccb33bad2008b00d691c3118fb Mon Sep 17 00:00:00 2001 From: aacitelli Date: Tue, 17 Jan 2023 15:58:54 +0100 Subject: [PATCH 2/5] [PAGOPA-627] get call: updated dockerfile and swagger --- Dockerfile | 33 ++-- openapi/openapi.json | 73 +++++++- .../pagopa/afm/utils/ImportCDIFunction.java | 165 +---------------- .../pagopa/afm/utils/config/FeignConfig.java | 5 +- .../utils/controller/ImportCDIController.java | 38 ++++ .../afm/utils/exception/AppException.java | 5 + .../repository/CDICollectionRepository.java | 6 +- .../pagopa/afm/utils/service/CDIService.java | 175 ++++++++++++++++++ .../afm/utils/task/MarketPlaceTrigger.java | 2 - .../afm/utils/ImportCDIFunctionTest.java | 37 ++-- .../afm/utils/ImportCDIHandlerTest.java | 11 +- .../controller/ImportCDIControllerTest.java | 48 +++++ .../afm/utils/service/CDIServiceTest.java | 13 +- 13 files changed, 408 insertions(+), 203 deletions(-) create mode 100644 src/main/java/it/gov/pagopa/afm/utils/controller/ImportCDIController.java create mode 100644 src/test/java/it/gov/pagopa/afm/utils/controller/ImportCDIControllerTest.java diff --git a/Dockerfile b/Dockerfile index a0a1c9e2..f0ef9532 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,20 +1,23 @@ -ARG JAVA_VERSION=11 +# +# Build +# +FROM maven:3.8.4-jdk-11-slim as buildtime +WORKDIR /build +COPY . . +RUN mvn clean package -Dmaven.test.skip=true -FROM mcr.microsoft.com/azure-functions/java:4-java$JAVA_VERSION-build AS installer-env -COPY . /build/java-function-app -RUN cd /build/java-function-app && \ - mkdir -p /home/site/wwwroot && \ - mvn clean package -Dmaven.test.skip=true && \ - cd ./target/azure-functions/ && \ - cd $(ls -d */|head -n 1) && \ - cp -a . /home/site/wwwroot +FROM adoptopenjdk/openjdk11:alpine-jre as builder +COPY --from=buildtime /build/target/*.jar application.jar +RUN java -Djarmode=layertools -jar application.jar extract -FROM mcr.microsoft.com/azure-functions/java:4-java$JAVA_VERSION -ENV AzureWebJobsScriptRoot=/home/site/wwwroot \ - AzureFunctionsJobHost__Logging__Console__IsEnabled=true +FROM ghcr.io/pagopa/docker-base-springboot-openjdk11:v1.0.1@sha256:bbbe948e91efa0a3e66d8f308047ec255f64898e7f9250bdb63985efd3a95dbf +COPY --chown=spring:spring --from=builder dependencies/ ./ +COPY --chown=spring:spring --from=builder snapshot-dependencies/ ./ +# https://github.com/moby/moby/issues/37965#issuecomment-426853382 +RUN true +COPY --chown=spring:spring --from=builder spring-boot-loader/ ./ +COPY --chown=spring:spring --from=builder application/ ./ -COPY --from=installer-env ["/home/site/wwwroot", "/home/site/wwwroot"] - -EXPOSE 8080 +EXPOSE 8080 \ No newline at end of file diff --git a/openapi/openapi.json b/openapi/openapi.json index e5c037a7..d8e508d6 100644 --- a/openapi/openapi.json +++ b/openapi/openapi.json @@ -13,14 +13,14 @@ } ], "paths": { - "/cdis/sync": { + "/api/cdis/sync": { "get": { "tags": [ - "Import CDI API" + "Import CDI function API" ], "description": "Returns the list of ids of the created bundles", "operationId": "importCDIFunction", - "summary": "import cdi", + "summary": "Azure function API to trigger the import of the CDIs and convert to bundles", "responses": { "200": { "description": "OK", @@ -56,6 +56,71 @@ } ] }, + "/cdis/sync": { + "get": { + "tags": [ + "Import CDI rest API" + ], + "summary": "Rest API to trigger the import of the CDIs and convert to bundles.", + "operationId": "syncCDI", + "responses": { + "200": { + "description": "Obtained bundle list.", + "headers": { + "X-Request-Id": { + "description": "This header identifies the call", + "schema": { + "type": "string" + } + } + }, + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/BundleResponse" + } + } + } + } + }, + "500": { + "description": "Service unavailable.", + "headers": { + "X-Request-Id": { + "description": "This header identifies the call", + "schema": { + "type": "string" + } + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemJson" + } + } + } + } + }, + "security": [ + { + "ApiKey": [] + } + ] + }, + "parameters": [ + { + "name": "X-Request-Id", + "in": "header", + "description": "This header identifies the call, if not passed it is self-generated. This ID is returned in the response.", + "schema": { + "type": "string" + } + } + ] + }, "/info": { "get": { "tags": [ @@ -233,4 +298,4 @@ } } } -} +} \ No newline at end of file diff --git a/src/main/java/it/gov/pagopa/afm/utils/ImportCDIFunction.java b/src/main/java/it/gov/pagopa/afm/utils/ImportCDIFunction.java index 11056657..ef6985a0 100644 --- a/src/main/java/it/gov/pagopa/afm/utils/ImportCDIFunction.java +++ b/src/main/java/it/gov/pagopa/afm/utils/ImportCDIFunction.java @@ -1,189 +1,34 @@ package it.gov.pagopa.afm.utils; -import java.time.LocalDate; -import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.function.Function; -import org.apache.commons.lang3.SerializationUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import org.springframework.util.CollectionUtils; -import com.azure.cosmos.implementation.apachecommons.lang.StringUtils; - -import feign.FeignException; -import it.gov.pagopa.afm.utils.entity.CDI; -import it.gov.pagopa.afm.utils.entity.Detail; -import it.gov.pagopa.afm.utils.entity.ServiceAmount; -import it.gov.pagopa.afm.utils.entity.StatusType; -import it.gov.pagopa.afm.utils.exception.AppError; -import it.gov.pagopa.afm.utils.exception.AppException; -import it.gov.pagopa.afm.utils.model.bundle.BundleRequest; import it.gov.pagopa.afm.utils.model.bundle.BundleResponse; -import it.gov.pagopa.afm.utils.model.bundle.BundleType; import it.gov.pagopa.afm.utils.model.bundle.CDIWrapper; -import it.gov.pagopa.afm.utils.model.bundle.PaymentMethodType; -import it.gov.pagopa.afm.utils.model.bundle.TouchpointType; import it.gov.pagopa.afm.utils.service.CDIService; -import it.gov.pagopa.afm.utils.service.MarketPlaceClient; import lombok.AllArgsConstructor; import lombok.NoArgsConstructor; -import lombok.extern.slf4j.Slf4j; import reactor.core.publisher.Mono; @Component -@Slf4j @NoArgsConstructor @AllArgsConstructor -public class ImportCDIFunction implements Function, Mono>>{ - - @Autowired(required=false) - private MarketPlaceClient marketPlaceClient; +public class ImportCDIFunction implements Function, Mono>> { - @Autowired(required=false) + @Autowired(required = false) private CDIService cdiService; - @Override - public Mono> apply(Mono input) { - - List bundleResponses = new ArrayList<>(); - - return input.map(wrapper -> { - - // the status of the items is put on PROCESSING to identify that these records are not in a final state - // *** @CosmosDBTrigger doesn't need of this step -> remove when change to this kind of function *** - this.setCDIToProcessingStatus(wrapper.getCdiItems()); - - for (CDI cdi: wrapper.getCdiItems()) { - // processed only cdis not in FAILED status - if (null != cdi.getCdiStatus() && !cdi.getCdiStatus().equals(StatusType.FAILED)) { - String idPsp = cdi.getIdPsp(); - List bundleRequestList = this.createBundlesByCDI(cdi); - try { - // create marketplace bundle - Optional.ofNullable(this.createBundleByList(idPsp, bundleRequestList)).ifPresent(bundleResponses::addAll); - // success -> delete the CDI - Optional.ofNullable(cdiService).ifPresent(result -> - { - cdiService.deleteCDI(cdi); - log.info(String.format("SUCCESS Bundles creation -> CDI deleted [idCdi=%s]", cdi.getIdCdi())); - }); - } - catch (AppException e) { - log.error("Error during the creation of the MarketPlace Bundles [idPsp= "+idPsp+", idCdi="+cdi.getIdCdi()+"]", e); - // error -> set CDI status to failed - cdi.setCdiStatus(StatusType.FAILED); - cdi.setCdiErrorDesc(e.getMessage()); - CDI updated = Optional.ofNullable(cdiService).map(result -> cdiService.updateCDI(cdi)).orElseGet(() -> CDI.builder().build()); - log.info(String.format("CDI status updated [idCdi=%s, status=%s, errorDesc=%s]", updated.getIdCdi(), updated.getCdiStatus(), updated.getCdiErrorDesc())); - } - - } - } - return bundleResponses; - }); - - } - - public List createBundlesByCDI(CDI cdi) { - List bundleRequestList = new ArrayList<>(); - if (!CollectionUtils.isEmpty(cdi.getDetails())) { - DateTimeFormatter dfDate = DateTimeFormatter.ofPattern("yyyy-MM-dd"); - BundleRequest bundleRequest = new BundleRequest(); - bundleRequest.setIdCdi(cdi.getIdCdi()); - bundleRequest.setDigitalStamp(cdi.getDigitalStamp()); - bundleRequest.setDigitalStampRestriction(Boolean.FALSE); - bundleRequest.setType(BundleType.GLOBAL); - bundleRequest.setTransferCategoryList(null); - bundleRequest.setValidityDateFrom(!StringUtils.isEmpty(cdi.getValidityDateFrom()) ? LocalDate.parse(cdi.getValidityDateFrom(), dfDate) : null); - bundleRequest.setValidityDateTo(null); - for (Detail d: cdi.getDetails()) { - bundleRequest.setIdChannel(d.getIdChannel()); - bundleRequest.setIdBrokerPsp(d.getIdBrokerPsp()); - bundleRequest.setName(d.getName()); - bundleRequest.setDescription(d.getDescription()); - bundleRequest.setPaymentType(d.getPaymentMethod()); - for (ServiceAmount sa: d.getServiceAmount()) { - bundleRequest.setPaymentAmount(sa.getPaymentAmount()); - bundleRequest.setMinPaymentAmount(sa.getMinPaymentAmount()); - bundleRequest.setMaxPaymentAmount(sa.getMaxPaymentAmount()); - this.addBundleByTouchpoint(d, bundleRequestList, bundleRequest); - } - } - } - return bundleRequestList; - } + public Mono> apply(Mono input) { - private void addBundleByTouchpoint(Detail d, List bundleRequestList, BundleRequest bundleRequest) { + return input.map(wrapper -> Optional.ofNullable(cdiService).map(result -> cdiService.syncCDI()) + .orElse(new ArrayList<>())); - boolean isNullTouchPoint = true; - - if (d.getPaymentMethod().equalsIgnoreCase(PaymentMethodType.PO.name())) { - isNullTouchPoint = false; - BundleRequest bundleRequestClone = SerializationUtils.clone(bundleRequest); - bundleRequestClone.setTouchpoint(TouchpointType.PSP.name()); - bundleRequestList.add(bundleRequestClone); - } - if ((d.getPaymentMethod().equalsIgnoreCase(PaymentMethodType.CP.name()) && d.getChannelCardsCart() && d.getChannelApp().equals(Boolean.FALSE)) || - (d.getPaymentMethod().matches("(?i)"+PaymentMethodType.BBT+"|"+PaymentMethodType.BP+"|"+PaymentMethodType.MYBK+"|"+PaymentMethodType.AD) && d.getChannelApp().equals(Boolean.FALSE)) || - (!d.getPaymentMethod().equalsIgnoreCase(PaymentMethodType.PPAL.name()) && d.getChannelApp())) { - isNullTouchPoint = false; - BundleRequest bundleRequestClone = SerializationUtils.clone(bundleRequest); - bundleRequestClone.setTouchpoint(TouchpointType.WISP.name()); - bundleRequestList.add(bundleRequestClone); - } - if ((d.getPaymentMethod().equalsIgnoreCase(PaymentMethodType.CP.name()) && d.getChannelCardsCart() && d.getChannelApp().equals(Boolean.FALSE)) || - (d.getPaymentMethod().equalsIgnoreCase(PaymentMethodType.PPAL.name()) && d.getChannelApp())) { - isNullTouchPoint = false; - BundleRequest bundleRequestClone = SerializationUtils.clone(bundleRequest); - bundleRequestClone.setTouchpoint(TouchpointType.IO.name()); - bundleRequestList.add(bundleRequestClone); - } - if ((d.getPaymentMethod().equalsIgnoreCase(PaymentMethodType.CP.name()) && d.getChannelCardsCart() && d.getChannelApp().equals(Boolean.FALSE))) { - isNullTouchPoint = false; - BundleRequest bundleRequestClone = SerializationUtils.clone(bundleRequest); - bundleRequestClone.setTouchpoint(TouchpointType.CHECKOUT.name()); - bundleRequestList.add(bundleRequestClone); - } - if (isNullTouchPoint) { - // default bundle with null touchpoint value - bundleRequestList.add(bundleRequest); - } - - } - - - private List createBundleByList(String idPsp, List bundleRequestList) throws AppException{ - List response = null; - try { - response = Optional.ofNullable(marketPlaceClient).map(result -> marketPlaceClient.createBundleByList(idPsp, bundleRequestList)).orElseGet(() -> null); - } catch (FeignException.BadRequest e) { - throw new AppException(AppError.BUNDLE_REQUEST_DATA_ERROR, e.getMessage()); - } catch (FeignException.NotFound e) { - throw new AppException(AppError.BUNDLE_NOT_FOUND_ERROR, e.getMessage()); - } catch (FeignException.Conflict e) { - throw new AppException(AppError.BUNDLE_CONFLICT_ERROR, e.getMessage()); - } catch (FeignException.InternalServerError e) { - throw new AppException(AppError.INTERNAL_SERVER_ERROR, e.getMessage()); - } catch (Exception e) { - throw new AppException(AppError.UNKNOWN, e.getMessage()); - } - return response; - } - - // remove when @CosmosDBTrigger function will be used - public void setCDIToProcessingStatus(List items) { - for (CDI cdi: items) { - cdi.setCdiStatus(StatusType.PROCESSING); - CDI updated = Optional.ofNullable(cdiService).map(result -> cdiService.updateCDI(cdi)).orElseGet(() -> CDI.builder().build()); - log.info(String.format("CDI status updated [idCdi=%s, status=%s]", updated.getIdCdi(), updated.getCdiStatus())); - } } - - } diff --git a/src/main/java/it/gov/pagopa/afm/utils/config/FeignConfig.java b/src/main/java/it/gov/pagopa/afm/utils/config/FeignConfig.java index 467c83b3..32549d7e 100644 --- a/src/main/java/it/gov/pagopa/afm/utils/config/FeignConfig.java +++ b/src/main/java/it/gov/pagopa/afm/utils/config/FeignConfig.java @@ -1,12 +1,11 @@ package it.gov.pagopa.afm.utils.config; -import feign.RequestInterceptor; -import lombok.extern.slf4j.Slf4j; import org.slf4j.MDC; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; -@Slf4j +import feign.RequestInterceptor; + public class FeignConfig { static final String HEADER_REQUEST_ID = "X-Request-Id"; diff --git a/src/main/java/it/gov/pagopa/afm/utils/controller/ImportCDIController.java b/src/main/java/it/gov/pagopa/afm/utils/controller/ImportCDIController.java new file mode 100644 index 00000000..97ee8519 --- /dev/null +++ b/src/main/java/it/gov/pagopa/afm/utils/controller/ImportCDIController.java @@ -0,0 +1,38 @@ +package it.gov.pagopa.afm.utils.controller; + +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import it.gov.pagopa.afm.utils.model.ProblemJson; +import it.gov.pagopa.afm.utils.model.bundle.BundleResponse; +import it.gov.pagopa.afm.utils.service.CDIService; + +@RestController +public class ImportCDIController { + + @Autowired + private CDIService cdiService; + + @Operation(summary = "API to trigger the import of the CDIs and convert to bundles.", security = {@SecurityRequirement(name = "ApiKey")}, operationId = "syncCDI", tags = {"Import CDI rest API"}) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "Obtained bundle list.", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, array = @ArraySchema(schema = @Schema(name = "BundleResponse", implementation = BundleResponse.class)))), + @ApiResponse(responseCode = "500", description = "Service unavailable.", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, schema = @Schema(implementation = ProblemJson.class)))}) + @GetMapping(value = "/cdis/sync", + produces = MediaType.APPLICATION_JSON_VALUE) + ResponseEntity> syncCDI(){ + return new ResponseEntity<>(cdiService.syncCDI(), HttpStatus.OK); + } +} diff --git a/src/main/java/it/gov/pagopa/afm/utils/exception/AppException.java b/src/main/java/it/gov/pagopa/afm/utils/exception/AppException.java index acf13748..e43d63af 100644 --- a/src/main/java/it/gov/pagopa/afm/utils/exception/AppException.java +++ b/src/main/java/it/gov/pagopa/afm/utils/exception/AppException.java @@ -18,6 +18,11 @@ public class AppException extends RuntimeException { /** + * + */ + private static final long serialVersionUID = 7691154761840463091L; + + /** * title returned to the response when this exception occurred */ String title; diff --git a/src/main/java/it/gov/pagopa/afm/utils/repository/CDICollectionRepository.java b/src/main/java/it/gov/pagopa/afm/utils/repository/CDICollectionRepository.java index 79b9f80d..43c62f28 100644 --- a/src/main/java/it/gov/pagopa/afm/utils/repository/CDICollectionRepository.java +++ b/src/main/java/it/gov/pagopa/afm/utils/repository/CDICollectionRepository.java @@ -1,12 +1,16 @@ package it.gov.pagopa.afm.utils.repository; +import java.util.List; + import org.springframework.stereotype.Repository; import com.azure.spring.data.cosmos.repository.CosmosRepository; +import com.azure.spring.data.cosmos.repository.Query; import it.gov.pagopa.afm.utils.entity.CDI; @Repository public interface CDICollectionRepository extends CosmosRepository { - + @Query("select * from Items r where r.cdiStatus = 'NEW'") + List getWorkableCDIs(); } diff --git a/src/main/java/it/gov/pagopa/afm/utils/service/CDIService.java b/src/main/java/it/gov/pagopa/afm/utils/service/CDIService.java index 51e56f9c..7e5bd73f 100644 --- a/src/main/java/it/gov/pagopa/afm/utils/service/CDIService.java +++ b/src/main/java/it/gov/pagopa/afm/utils/service/CDIService.java @@ -1,20 +1,49 @@ package it.gov.pagopa.afm.utils.service; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +import org.apache.commons.lang3.SerializationUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; + +import com.azure.cosmos.implementation.apachecommons.lang.StringUtils; +import feign.FeignException; import it.gov.pagopa.afm.utils.entity.CDI; +import it.gov.pagopa.afm.utils.entity.Detail; +import it.gov.pagopa.afm.utils.entity.ServiceAmount; +import it.gov.pagopa.afm.utils.entity.StatusType; +import it.gov.pagopa.afm.utils.exception.AppError; +import it.gov.pagopa.afm.utils.exception.AppException; +import it.gov.pagopa.afm.utils.model.bundle.BundleRequest; +import it.gov.pagopa.afm.utils.model.bundle.BundleResponse; +import it.gov.pagopa.afm.utils.model.bundle.BundleType; +import it.gov.pagopa.afm.utils.model.bundle.PaymentMethodType; +import it.gov.pagopa.afm.utils.model.bundle.TouchpointType; import it.gov.pagopa.afm.utils.repository.CDICollectionRepository; import lombok.AllArgsConstructor; import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; @Service @AllArgsConstructor @NoArgsConstructor +@Setter +@Slf4j public class CDIService { @Autowired private CDICollectionRepository cdisRepository; + @Autowired + private MarketPlaceClient marketPlaceClient; + public CDI updateCDI(CDI cdiEntity) { return cdisRepository.save(cdiEntity); } @@ -22,4 +51,150 @@ public CDI updateCDI(CDI cdiEntity) { public void deleteCDI(CDI cdiEntity) { cdisRepository.delete(cdiEntity); } + + public List getWorkableCDIs() { + return cdisRepository.getWorkableCDIs(); + } + + public List syncCDI() { + return this.turnCDIToBundles(this.getWorkableCDIs()); + } + + + public List turnCDIToBundles(List cdis){ + log.info("CDIService - turnCDIToBundles executed at: " + LocalDateTime.now() + " for CDI list with size: " + cdis.size()); + List bundleResponses = new ArrayList<>(); + // the status of the items is put on PROCESSING to identify that these records are not in a final state + this.setCDIToProcessingStatus(cdis); + for (CDI cdi: cdis) { + // processed only cdis not in FAILED status + if (null != cdi.getCdiStatus() && !cdi.getCdiStatus().equals(StatusType.FAILED)) { + String idPsp = cdi.getIdPsp(); + List bundleRequestList = this.createBundlesByCDI(cdi); + try { + // create marketplace bundle + Optional.ofNullable(this.createBundleByList(idPsp, bundleRequestList)).ifPresent(bundleResponses::addAll); + // success -> delete the CDI + this.deleteCDI(cdi); + log.info(String.format("SUCCESS Bundles creation -> CDI deleted [idCdi=%s]", cdi.getIdCdi())); + + } + catch (AppException e) { + log.error("Error during the creation of the MarketPlace Bundles [idPsp= "+idPsp+", idCdi="+cdi.getIdCdi()+"]", e); + // error -> set CDI status to failed + cdi.setCdiStatus(StatusType.FAILED); + cdi.setCdiErrorDesc(e.getMessage()); + CDI updated = this.updateCDI(cdi); + log.info(String.format("CDI status updated [idCdi=%s, status=%s, errorDesc=%s]", + Optional.ofNullable(updated).map(result -> updated.getIdCdi()), + Optional.ofNullable(updated).map(result -> updated.getCdiStatus()), + Optional.ofNullable(updated).map(result -> updated.getCdiErrorDesc()))); + } + + } + } + return bundleResponses; + + } + + public List createBundlesByCDI(CDI cdi) { + List bundleRequestList = new ArrayList<>(); + if (!CollectionUtils.isEmpty(cdi.getDetails())) { + DateTimeFormatter dfDate = DateTimeFormatter.ofPattern("yyyy-MM-dd"); + BundleRequest bundleRequest = new BundleRequest(); + bundleRequest.setIdCdi(cdi.getIdCdi()); + bundleRequest.setDigitalStamp(cdi.getDigitalStamp()); + bundleRequest.setDigitalStampRestriction(Boolean.FALSE); + bundleRequest.setType(BundleType.GLOBAL); + bundleRequest.setTransferCategoryList(null); + bundleRequest.setValidityDateFrom(!StringUtils.isEmpty(cdi.getValidityDateFrom()) ? LocalDate.parse(cdi.getValidityDateFrom(), dfDate) : null); + bundleRequest.setValidityDateTo(null); + for (Detail d: cdi.getDetails()) { + bundleRequest.setIdChannel(d.getIdChannel()); + bundleRequest.setIdBrokerPsp(d.getIdBrokerPsp()); + bundleRequest.setName(d.getName()); + bundleRequest.setDescription(d.getDescription()); + bundleRequest.setPaymentType(d.getPaymentMethod()); + for (ServiceAmount sa: d.getServiceAmount()) { + bundleRequest.setPaymentAmount(sa.getPaymentAmount()); + bundleRequest.setMinPaymentAmount(sa.getMinPaymentAmount()); + bundleRequest.setMaxPaymentAmount(sa.getMaxPaymentAmount()); + this.addBundleByTouchpoint(d, bundleRequestList, bundleRequest); + } + } + } + return bundleRequestList; + } + + private void addBundleByTouchpoint(Detail d, List bundleRequestList, BundleRequest bundleRequest) { + + boolean isNullTouchPoint = true; + + if (d.getPaymentMethod().equalsIgnoreCase(PaymentMethodType.PO.name())) { + isNullTouchPoint = false; + BundleRequest bundleRequestClone = SerializationUtils.clone(bundleRequest); + bundleRequestClone.setTouchpoint(TouchpointType.PSP.name()); + bundleRequestList.add(bundleRequestClone); + } + if ((d.getPaymentMethod().equalsIgnoreCase(PaymentMethodType.CP.name()) && d.getChannelCardsCart() && d.getChannelApp().equals(Boolean.FALSE)) || + (d.getPaymentMethod().matches("(?i)"+PaymentMethodType.BBT+"|"+PaymentMethodType.BP+"|"+PaymentMethodType.MYBK+"|"+PaymentMethodType.AD) && d.getChannelApp().equals(Boolean.FALSE)) || + (!d.getPaymentMethod().equalsIgnoreCase(PaymentMethodType.PPAL.name()) && d.getChannelApp())) { + isNullTouchPoint = false; + BundleRequest bundleRequestClone = SerializationUtils.clone(bundleRequest); + bundleRequestClone.setTouchpoint(TouchpointType.WISP.name()); + bundleRequestList.add(bundleRequestClone); + } + if ((d.getPaymentMethod().equalsIgnoreCase(PaymentMethodType.CP.name()) && d.getChannelCardsCart() && d.getChannelApp().equals(Boolean.FALSE)) || + (d.getPaymentMethod().equalsIgnoreCase(PaymentMethodType.PPAL.name()) && d.getChannelApp())) { + isNullTouchPoint = false; + BundleRequest bundleRequestClone = SerializationUtils.clone(bundleRequest); + bundleRequestClone.setTouchpoint(TouchpointType.IO.name()); + bundleRequestList.add(bundleRequestClone); + } + if ((d.getPaymentMethod().equalsIgnoreCase(PaymentMethodType.CP.name()) && d.getChannelCardsCart() && d.getChannelApp().equals(Boolean.FALSE))) { + isNullTouchPoint = false; + BundleRequest bundleRequestClone = SerializationUtils.clone(bundleRequest); + bundleRequestClone.setTouchpoint(TouchpointType.CHECKOUT.name()); + bundleRequestList.add(bundleRequestClone); + } + if (isNullTouchPoint) { + // default bundle with null touchpoint value + bundleRequestList.add(bundleRequest); + } + + } + + + private List createBundleByList(String idPsp, List bundleRequestList) throws AppException{ + List response = null; + try { + response = Optional.ofNullable(marketPlaceClient).map(result -> marketPlaceClient.createBundleByList(idPsp, bundleRequestList)).orElseGet(() -> null); + } catch (FeignException.BadRequest e) { + throw new AppException(AppError.BUNDLE_REQUEST_DATA_ERROR, e.getMessage()); + } catch (FeignException.NotFound e) { + throw new AppException(AppError.BUNDLE_NOT_FOUND_ERROR, e.getMessage()); + } catch (FeignException.Conflict e) { + throw new AppException(AppError.BUNDLE_CONFLICT_ERROR, e.getMessage()); + } catch (FeignException.InternalServerError e) { + throw new AppException(AppError.INTERNAL_SERVER_ERROR, e.getMessage()); + } catch (Exception e) { + throw new AppException(AppError.UNKNOWN, e.getMessage()); + } + return response; + } + + // remove when @CosmosDBTrigger function will be used + public void setCDIToProcessingStatus(List items) { + for (CDI cdi: items) { + cdi.setCdiStatus(StatusType.PROCESSING); + CDI updated = this.updateCDI(cdi); + log.info(String.format("CDI status updated [idCdi=%s, status=%s]", + Optional.ofNullable(updated).map(result -> updated.getIdCdi()), + Optional.ofNullable(updated).map(result -> updated.getCdiStatus()))); + } + } + + + + } diff --git a/src/main/java/it/gov/pagopa/afm/utils/task/MarketPlaceTrigger.java b/src/main/java/it/gov/pagopa/afm/utils/task/MarketPlaceTrigger.java index 714ac27c..987e6177 100644 --- a/src/main/java/it/gov/pagopa/afm/utils/task/MarketPlaceTrigger.java +++ b/src/main/java/it/gov/pagopa/afm/utils/task/MarketPlaceTrigger.java @@ -1,9 +1,7 @@ package it.gov.pagopa.afm.utils.task; import it.gov.pagopa.afm.utils.service.MarketPlaceClient; -import lombok.extern.slf4j.Slf4j; -@Slf4j public class MarketPlaceTrigger implements Runnable { private final MarketPlaceClient marketPlaceClient; diff --git a/src/test/java/it/gov/pagopa/afm/utils/ImportCDIFunctionTest.java b/src/test/java/it/gov/pagopa/afm/utils/ImportCDIFunctionTest.java index 22f64764..31cbe5cb 100644 --- a/src/test/java/it/gov/pagopa/afm/utils/ImportCDIFunctionTest.java +++ b/src/test/java/it/gov/pagopa/afm/utils/ImportCDIFunctionTest.java @@ -5,6 +5,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.lenient; import java.util.Arrays; import java.util.List; @@ -14,6 +15,7 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.Mockito; +import org.mockito.Spy; import org.mockito.junit.jupiter.MockitoExtension; import feign.FeignException; @@ -21,6 +23,7 @@ import it.gov.pagopa.afm.utils.entity.StatusType; import it.gov.pagopa.afm.utils.model.bundle.BundleResponse; import it.gov.pagopa.afm.utils.model.bundle.CDIWrapper; +import it.gov.pagopa.afm.utils.repository.CDICollectionRepository; import it.gov.pagopa.afm.utils.service.CDIService; import it.gov.pagopa.afm.utils.service.MarketPlaceClient; import reactor.core.publisher.Mono; @@ -32,22 +35,28 @@ class ImportCDIFunctionTest { private MarketPlaceClient marketPlaceClient; @Mock + private CDICollectionRepository cdisRepository; + + @Spy private CDIService cdiService; @Test void applyTest(){ // precondition + cdiService.setCdisRepository(cdisRepository); + cdiService.setMarketPlaceClient(marketPlaceClient); BundleResponse response = BundleResponse.builder().idBundle("12345").build(); Mockito.when(marketPlaceClient.createBundleByList(eq("201"), any())).thenReturn(Arrays.asList(response)); - EasyRandom generator = new EasyRandom(); CDI cdi = generator.nextObject(CDI.class); cdi.setIdPsp("201"); cdi.setValidityDateFrom("2022-12-15"); cdi.setCdiStatus(StatusType.NEW); + Mockito.when(cdisRepository.getWorkableCDIs()).thenReturn(Arrays.asList(new CDI[] {cdi})); + CDIWrapper input = CDIWrapper.builder().cdiItems(Arrays.asList(new CDI[] {cdi})).build(); - Mono> responses = new ImportCDIFunction(marketPlaceClient, cdiService).apply(Mono.just(input)); + Mono> responses = new ImportCDIFunction(cdiService).apply(Mono.just(input)); assertTrue(responses.block().size() > 0); assertThat(responses.block().get(0).getIdBundle()).isEqualTo("12345"); @@ -56,16 +65,18 @@ void applyTest(){ @Test void applyTest_400(){ // precondition + cdiService.setCdisRepository(cdisRepository); + cdiService.setMarketPlaceClient(marketPlaceClient); EasyRandom generator = new EasyRandom(); CDI cdi = generator.nextObject(CDI.class); cdi.setIdPsp("400"); cdi.setValidityDateFrom("2022-12-15"); cdi.setCdiStatus(StatusType.NEW); - Mockito.when(marketPlaceClient.createBundleByList(eq("400"), any())).thenThrow(FeignException.BadRequest.class); - Mockito.when(cdiService.updateCDI(any(CDI.class))).thenReturn(cdi); + Mockito.when(cdisRepository.getWorkableCDIs()).thenReturn(Arrays.asList(new CDI[] {cdi})); + lenient().when(marketPlaceClient.createBundleByList(eq("400"), any())).thenThrow(FeignException.BadRequest.class); CDIWrapper input = CDIWrapper.builder().cdiItems(Arrays.asList(new CDI[] {cdi})).build(); - Mono> responses = new ImportCDIFunction(marketPlaceClient, cdiService).apply(Mono.just(input)); + Mono> responses = new ImportCDIFunction(cdiService).apply(Mono.just(input)); assertEquals(0,responses.block().size()); } @@ -73,17 +84,19 @@ void applyTest_400(){ @Test void applyTest_409(){ // precondition + cdiService.setCdisRepository(cdisRepository); + cdiService.setMarketPlaceClient(marketPlaceClient); EasyRandom generator = new EasyRandom(); CDI cdi = generator.nextObject(CDI.class); cdi.setIdPsp("409"); cdi.setValidityDateFrom("2022-12-15"); cdi.setCdiStatus(StatusType.NEW); - Mockito.when(marketPlaceClient.createBundleByList(eq("409"), any())).thenThrow(FeignException.Conflict.class); - Mockito.when(cdiService.updateCDI(any(CDI.class))).thenReturn(cdi); + Mockito.when(cdisRepository.getWorkableCDIs()).thenReturn(Arrays.asList(new CDI[] {cdi})); + lenient().when(marketPlaceClient.createBundleByList(eq("409"), any())).thenThrow(FeignException.Conflict.class); CDIWrapper input = CDIWrapper.builder().cdiItems(Arrays.asList(new CDI[] {cdi})).build(); - Mono> responses = new ImportCDIFunction(marketPlaceClient, cdiService).apply(Mono.just(input)); + Mono> responses = new ImportCDIFunction(cdiService).apply(Mono.just(input)); assertEquals(0,responses.block().size()); } @@ -91,17 +104,19 @@ void applyTest_409(){ @Test void applyTest_404(){ // precondition + cdiService.setCdisRepository(cdisRepository); + cdiService.setMarketPlaceClient(marketPlaceClient); EasyRandom generator = new EasyRandom(); CDI cdi = generator.nextObject(CDI.class); cdi.setIdPsp("404"); cdi.setValidityDateFrom("2022-12-15"); cdi.setCdiStatus(StatusType.NEW); - Mockito.when(marketPlaceClient.createBundleByList(eq("404"), any())).thenThrow(FeignException.NotFound.class); - Mockito.when(cdiService.updateCDI(any(CDI.class))).thenReturn(cdi); + Mockito.when(cdisRepository.getWorkableCDIs()).thenReturn(Arrays.asList(new CDI[] {cdi})); + lenient().when(marketPlaceClient.createBundleByList(eq("404"), any())).thenThrow(FeignException.NotFound.class); CDIWrapper input = CDIWrapper.builder().cdiItems(Arrays.asList(new CDI[] {cdi})).build(); - Mono> responses = new ImportCDIFunction(marketPlaceClient, cdiService).apply(Mono.just(input)); + Mono> responses = new ImportCDIFunction(cdiService).apply(Mono.just(input)); assertEquals(0,responses.block().size()); } diff --git a/src/test/java/it/gov/pagopa/afm/utils/ImportCDIHandlerTest.java b/src/test/java/it/gov/pagopa/afm/utils/ImportCDIHandlerTest.java index 14a1a836..3f1bf7e5 100644 --- a/src/test/java/it/gov/pagopa/afm/utils/ImportCDIHandlerTest.java +++ b/src/test/java/it/gov/pagopa/afm/utils/ImportCDIHandlerTest.java @@ -20,12 +20,13 @@ import it.gov.pagopa.afm.utils.model.bundle.BundleRequest; import it.gov.pagopa.afm.utils.model.bundle.BundleResponse; import it.gov.pagopa.afm.utils.model.bundle.CDIWrapper; +import it.gov.pagopa.afm.utils.service.CDIService; @ExtendWith(MockitoExtension.class) class ImportCDIHandlerTest { @Spy - ImportCDIFunction importCDIFunction; + CDIService cdiService; @Test void execute() throws IOException, NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException { @@ -34,7 +35,7 @@ void execute() throws IOException, NoSuchFieldException, SecurityException, Ille List items = new ArrayList<>(); items.add(cdi); - List requests = importCDIFunction.createBundlesByCDI(cdi); + List requests = cdiService.createBundlesByCDI(cdi); //test execution FunctionInvoker> handler = new FunctionInvoker<>(ImportCDIFunction.class); @@ -69,7 +70,7 @@ void executeMultipleTouchPoint() throws IOException { List items = new ArrayList<>(); items.add(cdi); - List requests = importCDIFunction.createBundlesByCDI(cdi); + List requests = cdiService.createBundlesByCDI(cdi); //test execution FunctionInvoker> handler = new FunctionInvoker<>(ImportCDIFunction.class); @@ -104,7 +105,7 @@ void executeMultipleServiceAmount() throws IOException { List items = new ArrayList<>(); items.add(cdi); - List requests = importCDIFunction.createBundlesByCDI(cdi); + List requests = cdiService.createBundlesByCDI(cdi); //test execution FunctionInvoker> handler = new FunctionInvoker<>(ImportCDIFunction.class); @@ -139,7 +140,7 @@ void executePaymentMethodPO() throws IOException, NoSuchFieldException, Security List items = new ArrayList<>(); items.add(cdi); - List requests = importCDIFunction.createBundlesByCDI(cdi); + List requests = cdiService.createBundlesByCDI(cdi); assertEquals(1, requests.size()); assertEquals("PSP", requests.get(0).getTouchpoint()); diff --git a/src/test/java/it/gov/pagopa/afm/utils/controller/ImportCDIControllerTest.java b/src/test/java/it/gov/pagopa/afm/utils/controller/ImportCDIControllerTest.java new file mode 100644 index 00000000..bbb3f2c2 --- /dev/null +++ b/src/test/java/it/gov/pagopa/afm/utils/controller/ImportCDIControllerTest.java @@ -0,0 +1,48 @@ +package it.gov.pagopa.afm.utils.controller; + +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.mockito.Mockito.when; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import java.util.ArrayList; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.MvcResult; + +import it.gov.pagopa.afm.utils.service.CDIService; + +@SpringBootTest +@AutoConfigureMockMvc +class ImportCDIControllerTest { + + @Autowired + private MockMvc mvc; + + @Mock + private CDIService cdiService; + + @BeforeEach + void setUp() { + // precondition + when(cdiService.syncCDI()).thenReturn(new ArrayList<>()); + } + + @Test + void syncCDI() throws Exception { + String url = "/cdis/sync"; + MvcResult result = mvc.perform(get(url).contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON)) + .andReturn(); + assertNotNull(result.getResponse().getContentAsString()); + } +} diff --git a/src/test/java/it/gov/pagopa/afm/utils/service/CDIServiceTest.java b/src/test/java/it/gov/pagopa/afm/utils/service/CDIServiceTest.java index 82ab387e..80f63cb3 100644 --- a/src/test/java/it/gov/pagopa/afm/utils/service/CDIServiceTest.java +++ b/src/test/java/it/gov/pagopa/afm/utils/service/CDIServiceTest.java @@ -14,18 +14,27 @@ class CDIServiceTest { @Mock private CDICollectionRepository cdisRepository; + @Mock + private MarketPlaceClient marketPlaceClient; @Test void deleteTest() { - CDIService cdiService = new CDIService(cdisRepository); + CDIService cdiService = new CDIService(cdisRepository, marketPlaceClient); cdiService.deleteCDI(CDI.builder().build()); assertTrue(true); } @Test void updateTest() { - CDIService cdiService = new CDIService(cdisRepository); + CDIService cdiService = new CDIService(cdisRepository, marketPlaceClient); cdiService.updateCDI(CDI.builder().build()); assertTrue(true); } + + @Test + void getWorkableCDIs() { + CDIService cdiService = new CDIService(cdisRepository, marketPlaceClient); + cdiService.getWorkableCDIs(); + assertTrue(true); + } } From 3bf913e84d74fa24a8c795eb1111a93e8b78711b Mon Sep 17 00:00:00 2001 From: Jacopo Carlini Date: Wed, 18 Jan 2023 12:09:10 +0100 Subject: [PATCH 3/5] Update src/main/java/it/gov/pagopa/afm/utils/service/CDIService.java --- src/main/java/it/gov/pagopa/afm/utils/service/CDIService.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/main/java/it/gov/pagopa/afm/utils/service/CDIService.java b/src/main/java/it/gov/pagopa/afm/utils/service/CDIService.java index f8ed97f4..b02fb6ff 100644 --- a/src/main/java/it/gov/pagopa/afm/utils/service/CDIService.java +++ b/src/main/java/it/gov/pagopa/afm/utils/service/CDIService.java @@ -52,9 +52,6 @@ public void deleteCDI(CDI cdiEntity) { cdisRepository.delete(cdiEntity); } - public List getWorkableCDIs() { - return cdisRepository.getWorkableCDIs(); - } public List syncCDI() { return this.turnCDIToBundles(cdisRepository.getWorkableCDIs()); From 290ed90144adc803b9720dbae67dc9e89ced4560 Mon Sep 17 00:00:00 2001 From: aacitelli Date: Wed, 18 Jan 2023 12:25:12 +0100 Subject: [PATCH 4/5] [PAGOPA-627] from httptrigger to GET: minor fix --- .../java/it/gov/pagopa/afm/utils/service/CDIService.java | 1 - .../it/gov/pagopa/afm/utils/service/CDIServiceTest.java | 6 ------ 2 files changed, 7 deletions(-) diff --git a/src/main/java/it/gov/pagopa/afm/utils/service/CDIService.java b/src/main/java/it/gov/pagopa/afm/utils/service/CDIService.java index b02fb6ff..4d86b70f 100644 --- a/src/main/java/it/gov/pagopa/afm/utils/service/CDIService.java +++ b/src/main/java/it/gov/pagopa/afm/utils/service/CDIService.java @@ -52,7 +52,6 @@ public void deleteCDI(CDI cdiEntity) { cdisRepository.delete(cdiEntity); } - public List syncCDI() { return this.turnCDIToBundles(cdisRepository.getWorkableCDIs()); } diff --git a/src/test/java/it/gov/pagopa/afm/utils/service/CDIServiceTest.java b/src/test/java/it/gov/pagopa/afm/utils/service/CDIServiceTest.java index 68ccc07c..1b2bfee8 100644 --- a/src/test/java/it/gov/pagopa/afm/utils/service/CDIServiceTest.java +++ b/src/test/java/it/gov/pagopa/afm/utils/service/CDIServiceTest.java @@ -34,10 +34,4 @@ void updateTest() { Mockito.verify(cdisRepository, times(1)).save(cdi); } - @Test - void getWorkableCDIs() { - CDIService cdiService = new CDIService(cdisRepository, marketPlaceClient); - cdiService.getWorkableCDIs(); - Mockito.verify(cdisRepository, times(1)).getWorkableCDIs(); - } } From ca39753ae54715a0b0c0e17bb462df19f7318c83 Mon Sep 17 00:00:00 2001 From: aacitelli Date: Wed, 18 Jan 2023 12:25:12 +0100 Subject: [PATCH 5/5] [PAGOPA-627] from httptrigger to GET: minor fix --- pom.xml | 8 -------- .../java/it/gov/pagopa/afm/utils/service/CDIService.java | 1 - .../it/gov/pagopa/afm/utils/service/CDIServiceTest.java | 6 ------ 3 files changed, 15 deletions(-) diff --git a/pom.xml b/pom.xml index ac6c7686..b990d59c 100644 --- a/pom.xml +++ b/pom.xml @@ -50,14 +50,6 @@ org.springframework.boot spring-boot-starter-validation - diff --git a/src/main/java/it/gov/pagopa/afm/utils/service/CDIService.java b/src/main/java/it/gov/pagopa/afm/utils/service/CDIService.java index b02fb6ff..4d86b70f 100644 --- a/src/main/java/it/gov/pagopa/afm/utils/service/CDIService.java +++ b/src/main/java/it/gov/pagopa/afm/utils/service/CDIService.java @@ -52,7 +52,6 @@ public void deleteCDI(CDI cdiEntity) { cdisRepository.delete(cdiEntity); } - public List syncCDI() { return this.turnCDIToBundles(cdisRepository.getWorkableCDIs()); } diff --git a/src/test/java/it/gov/pagopa/afm/utils/service/CDIServiceTest.java b/src/test/java/it/gov/pagopa/afm/utils/service/CDIServiceTest.java index 68ccc07c..1b2bfee8 100644 --- a/src/test/java/it/gov/pagopa/afm/utils/service/CDIServiceTest.java +++ b/src/test/java/it/gov/pagopa/afm/utils/service/CDIServiceTest.java @@ -34,10 +34,4 @@ void updateTest() { Mockito.verify(cdisRepository, times(1)).save(cdi); } - @Test - void getWorkableCDIs() { - CDIService cdiService = new CDIService(cdisRepository, marketPlaceClient); - cdiService.getWorkableCDIs(); - Mockito.verify(cdisRepository, times(1)).getWorkableCDIs(); - } }