diff --git a/.gitignore b/.gitignore index 9b1ae502..0c187eaa 100644 --- a/.gitignore +++ b/.gitignore @@ -51,3 +51,8 @@ glowroot.jar /secrets/postgres_password.txt /secrets/secrets_protools_properties.properties /secrets/** +/src/main/resources/application-conteneur.properties +/src/main/resources/application-dev.properties +/src/main/resources/application-kubedev.properties + +/src/test/httpRequests/fak/ diff --git a/changelog.md b/changelog.md index 0f9d8499..4f94a7cf 100644 --- a/changelog.md +++ b/changelog.md @@ -1,19 +1,26 @@ # Change Log All notable changes to this project will be documented in this file. - + The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [Unreleased 1.1.1-SNAPSHOT] - xx-xx-xxxx +### Changed +#### BPMN TASKS +- [sugoiCreateUserTask](TODO) + La longueur du mot de passe crée dépend du contexte (8 pour household ; 12 sinon) +- [cleanUserPasswordTask](TODO) + Suppression de toutes les variables de mots de passe (sur le contexte et dans l'historique) -## [Unreleased 1.1.0] - yyyy-mm-dd +## [1.1.0] - 14-05-2024 ### Added #### BPMN TASKS - [SabianePilotageCreateSUTask](http://preparation_collecte.gitlab-pages.insee.fr/prepadoc/Protools/taches/#cr%c3%a9er-une-ue-dans-la-plateforme-de-collecte-enqu%c3%aateur-partie-pilotage) Tâche de création d'une UE dans sabiane pilotage - [SabianeQuestionnaireCreateSUTask](http://preparation_collecte.gitlab-pages.insee.fr/prepadoc/Protools/taches/#cr%c3%a9er-une-ue-dans-la-plateforme-de-collecte-enqu%c3%aateur-partie-questionnaire) Tâche de création d'une UE dans sabiane questionnaire -- [sugoiCreateUserTask](TODO) - Tâche de création d'un utilisateur dans l'annuaire Sugoi et initialization d'un mot de passe par défaut. +- [sugoiCreateUserTask](http://preparation_collecte.gitlab-pages.insee.fr/prepadoc/Protools/taches/#cr%c3%a9ation-de-comptes-dans-lannuaire-sugoi) + Tâche de création d'un utilisateur dans l'annuaire Sugoi et initialization d'un mot de passe par défaut - [platinePilotageGetSUIsToFollowUpTask]( TODO) Tâche de lecture dans Platine Pilotage de l'état a-relancer/eligible/isToFollowUp d'une UE (d'une partition). - [platinePilotageAddSUFollowUpTask]( TODO) @@ -38,7 +45,7 @@ Travail sur les tâches BPMN pour ERA et REM. - [remGetSUTask](http://preparation_collecte.gitlab-pages.insee.fr/prepadoc/Protools/taches/#r%c3%a9cup%c3%a9ration-dune-ue-dans-rem) Tâche de récupération d'une UE dans REM à partir de son ID. - [extractContactIdentifierFromREMSUTask](http://preparation_collecte.gitlab-pages.insee.fr/prepadoc/Protools/taches/#extraire-lidentifiant-de-compte-des-additionals-info-dans-une-ue-rem) - Tâche d'extraction de l'identifiant internet depuis les additionalInformations d'un json d'UE REM + Tâche d'extraction de l'identifiant internet depuis les additionalInformations d'un json d'UE REM - [remWriteEraSUListTask](http://preparation_collecte.gitlab-pages.insee.fr/prepadoc/Protools/taches/#ecriture-dune-liste-due-dans-une-partition-rem) Tâche d'écriture dans REM d'une liste d'UE récupérée dans ERA - [eraGetSUForPeriodAndGenderTask](http://preparation_collecte.gitlab-pages.insee.fr/prepadoc/Protools/taches/#extractions-de-donn%c3%a9ees-du-rp-avec-era) @@ -54,24 +61,24 @@ Travail sur les tâches BPMN pour ERA et REM. #### Endpoints - /api_configuration qui renverra la configuration de chaque API orchestrée par protools. Cela permet donc de savoir -quelle plateforme est appelée. + quelle plateforme est appelée. #### Autres - Vérification que le fichier de contexte satisfait bien toutes les tâches du BPMN associé au processus. - Possibilité d'utiliser la date de début et de fin de collecte d'une partition dans les expressions BPMN via PartitionCtxResolver -- Ajout des périodes X01 à X99 à l'énumération pour pilotage +- Ajout des périodes X01 à X99 à l'énumération pour pilotage -- +- ### Changed #### Variables du processus - "sugoi-id-contact" devient "directory_access-id-contact" (peut casser les BPMN la référençant en dur). - + ### Fixed - + ## [0.0.3] - 2023-05-16 ### Added - Création de contexte de campagne dans sabiane et platine +Création de contexte de campagne dans sabiane et platine ### Changed ### Fixed diff --git a/pom.xml b/pom.xml index 3aa4d5fa..ce6b834d 100644 --- a/pom.xml +++ b/pom.xml @@ -5,17 +5,18 @@ org.springframework.boot spring-boot-starter-parent - 3.3.1 + 3.3.4 fr.insee.sndil.protools protools-protlsbo - 1.1.0 + 1.1.1-SNAPSHOT Protools Back Office Protools Back Office: Survey Orchestrator and Management Tool - Built with Flowable Engine 17 2.5.0 + 1.0.0 7.0.1-insee 1.16.1 1.2.1 @@ -42,6 +43,13 @@ ${flowable.version} + + + fr.insee + boot-properties-logger-starter + ${properties-logger.version} + + org.passay @@ -125,6 +133,29 @@ test + + io.micrometer + micrometer-core + 1.12.3 + + + + org.springframework.boot + spring-boot-starter-data-mongodb + + + + com.networknt + json-schema-validator + 1.5.1 + + + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + + @@ -140,6 +171,11 @@ + @@ -148,12 +184,24 @@ ${pitest.version} - fr.insee.protools.backend.service.* - fr.insee.protools.backend.controller.StarterController + fr.insee.protools.backend.* STRONGER + + java.util.logging + org.apache.log4j + org.slf4j + org.apache.commons.logging + fr.insee.protools.backend.logging + fr.insee.protools.backend.logging.LoggingHelper + + + fr.insee.protools.backend.logging.* + fr.insee.protools.backend.dto.* + *xxBPMNError + @@ -185,28 +233,58 @@ - maven-resources-plugin + org.apache.maven.plugins + maven-compiler-plugin + + 21 + 21 + + fr/insee/protools/backend/deprecated/**/*.java + + + **/deprecated/**/*.java + + + + + + org.jsonschema2pojo + jsonschema2pojo-maven-plugin + 1.2.1 + + java.time.Instant + ${basedir}/src/main/resources/schema + fr.insee.protools.backend.dto + ALWAYS + - copy-resources - validate - copy-resources + generate + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + generate-sources + + add-source - ${project.build.outputDirectory} - - - ${basedir} - - changelog.md - - - + + ${project.build.directory}/generated-sources/jsonschema2pojo + + + diff --git a/src/main/java/fr/insee/protools/backend/StarterApplication.java b/src/main/java/fr/insee/protools/backend/StarterApplication.java index f18c8d6f..522df08e 100644 --- a/src/main/java/fr/insee/protools/backend/StarterApplication.java +++ b/src/main/java/fr/insee/protools/backend/StarterApplication.java @@ -1,6 +1,5 @@ package fr.insee.protools.backend; -import fr.insee.protools.backend.configuration.PropertiesLogger; import jakarta.servlet.ServletRequest; import jakarta.servlet.http.HttpServletRequest; import org.springdoc.core.utils.SpringDocUtils; @@ -15,8 +14,7 @@ public static void main(String[] args) { configureApplicationBuilder(new SpringApplicationBuilder()).build().run(args); } public static SpringApplicationBuilder configureApplicationBuilder(SpringApplicationBuilder springApplicationBuilder){ - return springApplicationBuilder.sources(StarterApplication.class) - .listeners(new PropertiesLogger()); + return springApplicationBuilder.sources(StarterApplication.class); } @EventListener(ApplicationReadyEvent.class) diff --git a/src/main/java/fr/insee/protools/backend/configuration/PropertiesLogger.java b/src/main/java/fr/insee/protools/backend/configuration/PropertiesLogger.java deleted file mode 100644 index e0469771..00000000 --- a/src/main/java/fr/insee/protools/backend/configuration/PropertiesLogger.java +++ /dev/null @@ -1,193 +0,0 @@ -package fr.insee.protools.backend.configuration; - -import lombok.AccessLevel; -import lombok.AllArgsConstructor; -import lombok.NonNull; -import lombok.extern.slf4j.Slf4j; -import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent; -import org.springframework.context.ApplicationListener; -import org.springframework.core.env.AbstractEnvironment; -import org.springframework.core.env.EnumerablePropertySource; -import org.springframework.core.env.Environment; -import org.springframework.core.env.PropertySource; - -import java.util.*; -import java.util.function.Supplier; - -/** - * Listener Spring permettant d'afficher les props dans les logs au démarrage de l'application : se déclenche - * sur l'évènement ApplicationEnvironmentPreparedEvent. - * - * Par défaut affiche les propriétés qui vérifient les conditions suivantes : - * 1. passées soit par la ligne de commande (--maProp=valeur), soit présentes dans les fichiers properties - * détectés par Spring boot au démarrage (une propriété présente uniquement dans le code sous la forme - * @Value("${ma.propriete}") dont la valeur serait passée uniquement par variable d'environnement ne sera - * donc pas détectée. Pour qu'elle le soit, il faut la faire figurer dans le fichier application.properties par exemple) - * 2. qui sont préfixées par l'un des éléments de PropertiesLogger.prefixesAffichesParDefaut - * - * Pour chaque propriété affichée : - * - si la clé contient l'un des mots parmi PropertiesLogger.motsCachesParDefaut, affiche alors "****" - * - sinon c'est la valeur de la propriété telle qu'elle sera résolue par Spring boot dans l'application qui est affichée - * - * Enfin, sont loguées également les noms des PropertySource de Spring dont proviennent les clés des propriétés qui sont affichées - * - * Le comportement de cette classe peut être amendé par les propriétés suivantes : - * - fr.insee.properties.log.key.select : stratégie de sélection des sources de propriétés qui seront affichées : - * - trois valeurs possibles : - * - ALL(toutes les propriétés des propertysource traitées seront affichées, peu importe les prefixes) - * - NONE (rien ne sera affiché) - * - PREFIX (valeur par défaut) : affiche les propriétés dont le prefixe est dans fr.insee.properties.log.key.prefixes - * et qui ne font pas partie des propertySource ignorés (le nom des propertysource ignorés figurent - * dans fr.insee.properties.log.sources.ignored)) - * - cf enum PropertySelectorEnum - * - fr.insee.properties.log.sources.ignored : nom des propertysource (ex: application-dev.properties) qui seront ignorées. - * - la valeur attendue est une liste de noms séparés par des virgules. Si vide alors aucune propertysource ne sera ignorée - * - Valeur par défaut : PropertiesLogger.propertySourcesIgnoreesParDefaut - * - fr.insee.properties.log.key.prefixes : permet de définir les préfixes des propriétés qui seront affichées. - * - Valeur par défaut : PropertiesLogger.prefixesAffichesParDefaut - * - la valeur attendue est une liste de noms séparés par des virgules. Si vide aucune propriété ne sera affichée - * - fr.insee.properties.log.key.hidden : liste des mots pour lesquels la valeur de la propriété sera masquée (si la clé de - * la propriété contient l'un des mots de la liste alors la valeur sera masquée). - * - Valeur par défaut : PropertiesLogger.motsCachesParDefaut - * - la valeur attendue est une liste de noms séparés par des virgules. /!\ ☠️ si vide tous les secrets seront affichés dans la log - * - */ -@Slf4j -public class PropertiesLogger implements ApplicationListener { - - public static final String PROPERTY_KEY_FOR_PREFIXES = "fr.insee.properties.log.key.prefixes"; - public static final String PROPERTY_KEY_FOR_MORE_HIDDEN = "fr.insee.properties.log.key.hidden.more"; - public static final String PROPERTY_KEY_FOR_SOURCES_IGNORED = "fr.insee.properties.log.sources.ignored"; - public static final String PROPERTY_KEY_FOR_SOURCES_SELECT = "fr.insee.properties.log.key.select"; - private static final Set baseMotsCaches = Set.of("password", "pwd", "jeton", "token", "secret", "credential", "pw"); - private static final Set prefixesAffichesParDefaut= Set.of("fr.insee","logging","keycloak","spring","application","server","springdoc","management"); - private static final Set propertySourcesIgnoreesParDefaut = Set.of("systemProperties", "systemEnvironment"); - public static final PropertySelectorEnum PROPERTY_SELECTOR_PAR_DEFAUT = PropertySelectorEnum.PREFIX; - private static Set prefixForSelectedProps; - - private final Collection propertySourceNames=new ArrayList<>(); - private Set hiddensProps; - private Set ignoredPropertySources; - private PropertySelector propertySelector; - - @Override - public void onApplicationEvent(@NonNull ApplicationEnvironmentPreparedEvent event) { - Environment environment=event.getEnvironment(); - - var props= new StringBuilder(); - this.hiddensProps = getMoreHiddenPropsFromPropertyAndMerge(environment); - prefixForSelectedProps = environment.getProperty(PROPERTY_KEY_FOR_PREFIXES, Set.class, prefixesAffichesParDefaut); - this.ignoredPropertySources = environment.getProperty(PROPERTY_KEY_FOR_SOURCES_IGNORED, Set.class, propertySourcesIgnoreesParDefaut); - var propertySelectorType=this.getSelectorFromProperty(environment.getProperty(PROPERTY_KEY_FOR_SOURCES_SELECT)) - .orElse(PROPERTY_SELECTOR_PAR_DEFAUT); - log.atDebug().log(()->"Logging "+propertySelectorType.forLogging()); - this.propertySelector=propertySelectorType.propertySelector(); - - ((AbstractEnvironment) environment).getPropertySources().stream() - .filter(this::isEnumerable) - .filter(this::sourceWillBeProcessed) - .map(this::rememberPropertySourceNameThenCast) - .map(EnumerablePropertySource::getPropertyNames) - .flatMap(Arrays::stream) - .distinct() - .filter(Objects::nonNull) - .filter(this::filterFromPropertySelector) - .forEach(key-> props.append(key).append(" = ") - .append(resoutValeurAvecMasquePwd(key, environment)) - .append(System.lineSeparator())); - props.append("============================================================================"); - props.insert(0, """ - =============================================================================================== - Valeurs des properties pour : - %s - =============================================================================================== - """.formatted(this.propertySourceNames.stream().reduce("",(l, e)->l+System.lineSeparator()+"- "+e ))); - log.info(props.toString()); - - } - - private static Set getMoreHiddenPropsFromPropertyAndMerge(Environment environment) { - var moreProps = environment.getProperty(PROPERTY_KEY_FOR_MORE_HIDDEN, Set.class); - var retour = baseMotsCaches; - if (moreProps != null){ - retour=new HashSet<>(moreProps); - retour.addAll(baseMotsCaches); - } - return retour; - } - - private Optional getSelectorFromProperty(String property) { - if(property!=null){ - try{ - return Optional.of(PropertySelectorEnum.valueOf(property)); - }catch (IllegalArgumentException ie){ - log.atTrace().log(()->"Impossible de convertir "+property+" en une constante de PropertySelectorEnum. Le PropertySelector par défaut sera utilisé."); - } - } - return Optional.empty(); - } - - private boolean filterFromPropertySelector(@NonNull String s) { - if (! this.propertySelector.filter(s)){ - log.atDebug().log(()->s+ " ne commence pas par un des prefix retenus pour être loguée"); - return false; - } - return true; - } - - private boolean sourceWillBeProcessed(PropertySource propertySource) { - - if (ignoredPropertySources.contains(propertySource.getName())){ - log.atDebug().log(()->propertySource+ " sera ignorée"); - return false; - } - return true; - } - - private EnumerablePropertySource rememberPropertySourceNameThenCast(PropertySource propertySource) { - this.propertySourceNames.add(propertySource.getName()); - return (EnumerablePropertySource) propertySource; - } - - private boolean isEnumerable(PropertySource propertySource) { - if (! (propertySource instanceof EnumerablePropertySource)){ - log.atDebug().log(()->propertySource+ " n'est pas EnumerablePropertySource : impossible à lister"); - return false; - } - return true; - } - - private Object resoutValeurAvecMasquePwd(String key, Environment environment) { - if (hiddensProps.stream().anyMatch(key::contains)) { - return "******"; - } - return environment.getProperty(key); - - } - - - @FunctionalInterface - private interface PropertySelector { - boolean filter(String s); - } - - @AllArgsConstructor(access = AccessLevel.PRIVATE) - private enum PropertySelectorEnum { - ALL(s->true, ()->"all properties"), - NONE(s->false, ()->"no properties"), - PREFIX(k->prefixForSelectedProps.stream().anyMatch(k::startsWith), () -> "properties starting with "+ prefixForSelectedProps); - - private final PropertySelector propertySelector; - private final Supplier logString; - - public PropertySelector propertySelector() { - return propertySelector; - } - - public String forLogging(){ - return logString.get(); - } - - } -} - diff --git a/src/main/java/fr/insee/protools/backend/configuration/SchedulerCondition.java b/src/main/java/fr/insee/protools/backend/configuration/SchedulerCondition.java new file mode 100644 index 00000000..d4bd5104 --- /dev/null +++ b/src/main/java/fr/insee/protools/backend/configuration/SchedulerCondition.java @@ -0,0 +1,13 @@ +package fr.insee.protools.backend.configuration; + +import org.springframework.context.annotation.Condition; +import org.springframework.context.annotation.ConditionContext; +import org.springframework.core.type.AnnotatedTypeMetadata; + +public class SchedulerCondition implements Condition { + @Override + public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { + return false; + } + +} \ No newline at end of file diff --git a/src/main/java/fr/insee/protools/backend/configuration/SpringDocConfiguration.java b/src/main/java/fr/insee/protools/backend/configuration/SpringDocConfiguration.java index 6df81cb4..ee20ab57 100644 --- a/src/main/java/fr/insee/protools/backend/configuration/SpringDocConfiguration.java +++ b/src/main/java/fr/insee/protools/backend/configuration/SpringDocConfiguration.java @@ -8,9 +8,9 @@ import io.swagger.v3.oas.models.security.OAuthFlows; import io.swagger.v3.oas.models.security.SecurityRequirement; import io.swagger.v3.oas.models.security.SecurityScheme; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springdoc.core.customizers.OperationCustomizer; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.info.BuildProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -19,13 +19,11 @@ @Configuration @Slf4j +@RequiredArgsConstructor public class SpringDocConfiguration { - @Autowired - private InseeSpringdocProperties springdocProperties; - - @Autowired(required = false) - private Optional buildProperties; + private final InseeSpringdocProperties springdocProperties; + private final Optional buildProperties; public static final String OAUTHSCHEME = "oAuth"; @@ -86,7 +84,12 @@ private OpenAPI createOpenAPI() { .info( new Info() .title(buildProperties.map(BuildProperties::getName).orElse("n.a")) - .description(springdocProperties.getDescription()) + .description( + String.format("`Application version : %s`\n\n%s", + buildProperties.map(BuildProperties::getVersion).orElse("n.a"), + springdocProperties.getDescription() + ) + ) .version(buildProperties.map(BuildProperties::getVersion).orElse("n.a")) /*.license( new License() diff --git a/src/main/java/fr/insee/protools/backend/controller/ProtoolsProcessController.java b/src/main/java/fr/insee/protools/backend/controller/ProtoolsProcessController.java index bf445c9c..c3397da4 100644 --- a/src/main/java/fr/insee/protools/backend/controller/ProtoolsProcessController.java +++ b/src/main/java/fr/insee/protools/backend/controller/ProtoolsProcessController.java @@ -1,6 +1,6 @@ package fr.insee.protools.backend.controller; -import fr.insee.protools.backend.service.context.ContextService; +import fr.insee.protools.backend.service.context.IContextService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.responses.ApiResponse; @@ -21,7 +21,7 @@ @RequiredArgsConstructor public class ProtoolsProcessController { - private final ContextService contextService; + private final IContextService contextService; @PostMapping(value = "/upload-context", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) @Operation(summary = "Upload of the context file", diff --git a/src/main/java/fr/insee/protools/backend/controller/ProtoolsProcessControllerAdvice.java b/src/main/java/fr/insee/protools/backend/controller/ProtoolsProcessControllerAdvice.java index 6249690b..085c1726 100644 --- a/src/main/java/fr/insee/protools/backend/controller/ProtoolsProcessControllerAdvice.java +++ b/src/main/java/fr/insee/protools/backend/controller/ProtoolsProcessControllerAdvice.java @@ -1,11 +1,11 @@ package fr.insee.protools.backend.controller; +import fr.insee.protools.backend.restclient.exception.runtime.HttpClient4xxBPMNError; +import fr.insee.protools.backend.restclient.exception.runtime.HttpClient5xxBPMNError; import fr.insee.protools.backend.service.context.exception.BadContextIOException; import fr.insee.protools.backend.service.context.exception.BadContextIncorrectBPMNError; import fr.insee.protools.backend.service.context.exception.BadContextNotJSONBPMNError; import fr.insee.protools.backend.service.exception.*; -import fr.insee.protools.backend.webclient.exception.runtime.WebClient4xxBPMNError; -import fr.insee.protools.backend.webclient.exception.runtime.WebClient5xxBPMNError; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -49,14 +49,14 @@ public ResponseEntity exeptionProcessDefinitionNotFoundHandler(/*final H return new ResponseEntity<>(exception.getMessage(), HttpStatus.NOT_FOUND); } - @ExceptionHandler({ WebClient4xxBPMNError.class }) - public ResponseEntity exceptionWebClient4xxHandler(/*final HttpServletRequest req, */final WebClient4xxBPMNError exception) { + @ExceptionHandler({ HttpClient4xxBPMNError.class }) + public ResponseEntity exceptionWebClient4xxHandler(/*final HttpServletRequest req, */final HttpClient4xxBPMNError exception) { log.error("exceptionWebClient4xxHandler : "+exception.getMessage()); return new ResponseEntity<>(exception.getMessage(), exception.getHttpStatusCodeError()); } - @ExceptionHandler({ WebClient5xxBPMNError.class }) - public ResponseEntity exceptionWebClient5xxHandler(/*final HttpServletRequest req, */final WebClient5xxBPMNError exception) { + @ExceptionHandler({ HttpClient5xxBPMNError.class }) + public ResponseEntity exceptionWebClient5xxHandler(/*final HttpServletRequest req, */final HttpClient5xxBPMNError exception) { log.error("exceptionWebClient5xxHandler : "+exception.getMessage()); return new ResponseEntity<>(exception.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); } diff --git a/src/main/java/fr/insee/protools/backend/controller/StarterController.java b/src/main/java/fr/insee/protools/backend/controller/StarterController.java index b6c9cce9..08aa5213 100644 --- a/src/main/java/fr/insee/protools/backend/controller/StarterController.java +++ b/src/main/java/fr/insee/protools/backend/controller/StarterController.java @@ -1,8 +1,8 @@ package fr.insee.protools.backend.controller; import com.fasterxml.jackson.databind.JsonNode; -import fr.insee.protools.backend.webclient.WebClientHelper; -import org.springframework.beans.factory.annotation.Autowired; +import fr.insee.protools.backend.restclient.RestClientHelper; +import lombok.RequiredArgsConstructor; import org.springframework.boot.info.BuildProperties; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; @@ -17,13 +17,12 @@ @RequestMapping("/starter") @RestController +@RequiredArgsConstructor public class StarterController { - @Autowired(required = false) - private Optional buildProperties; + private final Optional buildProperties; - @Autowired - private WebClientHelper webClientHelper; + private final RestClientHelper restClientHelper; @GetMapping("/healthcheck") public ResponseEntity healthcheck(){ @@ -59,7 +58,7 @@ public ResponseEntity healthcheckadmin(){ @GetMapping("/token_details_by_api") public ResponseEntity tokensDetailsByAPI(){ StringBuilder result = new StringBuilder("List of tokens roles : "); - for(var x : webClientHelper.getTokenDetailsByAPI().entrySet()){ + for(var x : restClientHelper.getTokenDetailsByAPI().entrySet()){ result.append("\n").append(x.getKey()).append(" : ").append(x.getValue()); } return ResponseEntity.ok(result.toString()); @@ -67,7 +66,7 @@ public ResponseEntity tokensDetailsByAPI(){ @GetMapping("/api_configuration") public ResponseEntity apiConfiguration(){ - return ResponseEntity.ok(webClientHelper.getAPIConfigDetails()); + return ResponseEntity.ok(restClientHelper.getAPIConfigDetails()); } @GetMapping(value="/changelog" , produces = MediaType.TEXT_PLAIN_VALUE) diff --git a/src/main/java/fr/insee/protools/backend/dto/era/CensusJsonDto.java b/src/main/java/fr/insee/protools/backend/dto/era/CensusJsonDto.java deleted file mode 100644 index db583670..00000000 --- a/src/main/java/fr/insee/protools/backend/dto/era/CensusJsonDto.java +++ /dev/null @@ -1,28 +0,0 @@ -package fr.insee.protools.backend.dto.era; - -import com.fasterxml.jackson.databind.node.BaseJsonNode; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.io.Serializable; - -@Data -@Builder -@AllArgsConstructor -@NoArgsConstructor -public class CensusJsonDto implements Serializable { - private Long id; - private String numvoiloc; - private String bisterloc; - private String typevoiloc; - private String nomvoiloc; - private String resloc; - private String car; - private String cpostloc; - private Long idinternaute; - private String mail; - private String identifiantCompte; - private BaseJsonNode externals; -} diff --git a/src/main/java/fr/insee/protools/backend/dto/era/GenderType.java b/src/main/java/fr/insee/protools/backend/dto/era/GenderType.java deleted file mode 100644 index 2b79f8da..00000000 --- a/src/main/java/fr/insee/protools/backend/dto/era/GenderType.java +++ /dev/null @@ -1,37 +0,0 @@ -package fr.insee.protools.backend.dto.era; - -import lombok.Getter; - -@Getter -public enum GenderType { - MALE("1", "hommes"), FEMALE("2", "femmes"); - - private final String value; - private final String label; - - GenderType(String value, String label) { - this.value = value; - this.label = label; - } - - public static GenderType fromValue(int value) { - return switch (value) { - case 1 -> MALE; - case 2 -> FEMALE; - default -> throw new IllegalStateException("Unexpected value for ERA gender: " + value); - }; - } - - public static GenderType fromLabel(String label) { - return switch (label) { - case "hommes" -> MALE; - case "femmes" -> FEMALE; - default -> throw new IllegalStateException("Unexpected value for ERA gender label: " + label); - }; - } - - public static String getAllValidLabels() { - return MALE.label + "," + FEMALE.label; - } - -} diff --git a/src/main/java/fr/insee/protools/backend/dto/meshuggah/MeshuggahComDetails.java b/src/main/java/fr/insee/protools/backend/dto/meshuggah/MeshuggahComDetails.java deleted file mode 100644 index 289eed28..00000000 --- a/src/main/java/fr/insee/protools/backend/dto/meshuggah/MeshuggahComDetails.java +++ /dev/null @@ -1,20 +0,0 @@ -package fr.insee.protools.backend.dto.meshuggah; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -@Data -@Builder -@NoArgsConstructor @AllArgsConstructor -public class MeshuggahComDetails { - String campaignId; - String partitioningId; - String medium; - String phase; - String operation; - String mode; - String protocol; - boolean avecQuestionnaire; -} \ No newline at end of file diff --git a/src/main/java/fr/insee/protools/backend/dto/platine/pilotage/PlatineAddressDto.java b/src/main/java/fr/insee/protools/backend/dto/platine/pilotage/PlatineAddressDto.java deleted file mode 100644 index 76a385f7..00000000 --- a/src/main/java/fr/insee/protools/backend/dto/platine/pilotage/PlatineAddressDto.java +++ /dev/null @@ -1,24 +0,0 @@ -package fr.insee.protools.backend.dto.platine.pilotage; - -import lombok.Getter; -import lombok.Setter; - -@Getter -@Setter -//Note: Mutualise the two Identical Adresses DTO used by platine (contact/questionning) -public class PlatineAddressDto { - - private String streetNumber; - private String repetitionIndex; - private String streetType; - private String streetName; - private String addressSupplement; - private String cityName; - private String zipCode; - private String cedexCode; - private String cedexName; - private String specialDistribution; - private String countryCode; - private String countryName; - -} diff --git a/src/main/java/fr/insee/protools/backend/dto/platine/pilotage/PlatinePilotageCommunicationEventDto.java b/src/main/java/fr/insee/protools/backend/dto/platine/pilotage/PlatinePilotageCommunicationEventDto.java new file mode 100644 index 00000000..a0e70db5 --- /dev/null +++ b/src/main/java/fr/insee/protools/backend/dto/platine/pilotage/PlatinePilotageCommunicationEventDto.java @@ -0,0 +1,8 @@ +package fr.insee.protools.backend.dto.platine.pilotage; + +public record PlatinePilotageCommunicationEventDto( + String interrogationId, + String communicationId, + String communicationRequestId, + PlatinePilotageCommunicationEventType state +) {} \ No newline at end of file diff --git a/src/main/java/fr/insee/protools/backend/dto/platine/pilotage/PlatinePilotageCommunicationEventType.java b/src/main/java/fr/insee/protools/backend/dto/platine/pilotage/PlatinePilotageCommunicationEventType.java new file mode 100644 index 00000000..f305675c --- /dev/null +++ b/src/main/java/fr/insee/protools/backend/dto/platine/pilotage/PlatinePilotageCommunicationEventType.java @@ -0,0 +1,14 @@ +package fr.insee.protools.backend.dto.platine.pilotage; + +import lombok.Getter; + +@Getter +public enum PlatinePilotageCommunicationEventType { + COMMUNICATION_STATE_SENT("SENT"); + + public final String label; + + PlatinePilotageCommunicationEventType(String label) { + this.label = label; + } +} diff --git a/src/main/java/fr/insee/protools/backend/dto/platine/pilotage/PlatinePilotageEligibleDto.java b/src/main/java/fr/insee/protools/backend/dto/platine/pilotage/PlatinePilotageEligibleDto.java deleted file mode 100644 index 8a9696c0..00000000 --- a/src/main/java/fr/insee/protools/backend/dto/platine/pilotage/PlatinePilotageEligibleDto.java +++ /dev/null @@ -1,9 +0,0 @@ -package fr.insee.protools.backend.dto.platine.pilotage; - -import lombok.Data; - -@Data -public class PlatinePilotageEligibleDto { - - private String eligible; -} diff --git a/src/main/java/fr/insee/protools/backend/dto/platine/pilotage/PlatinePilotageGenderType.java b/src/main/java/fr/insee/protools/backend/dto/platine/pilotage/PlatinePilotageGenderType.java deleted file mode 100644 index 59c9e64e..00000000 --- a/src/main/java/fr/insee/protools/backend/dto/platine/pilotage/PlatinePilotageGenderType.java +++ /dev/null @@ -1,17 +0,0 @@ -package fr.insee.protools.backend.dto.platine.pilotage; - -import lombok.Getter; - -@Getter -@SuppressWarnings("java:S115") //allow constants not in capital letters -public enum PlatinePilotageGenderType { - Female("1", "Female"), Male("2", "Male"),Undefined("3","Undefined") ; - - private final String value; - private final String label; - - PlatinePilotageGenderType(String value, String label) { - this.value = value; - this.label = label; - } -} diff --git a/src/main/java/fr/insee/protools/backend/dto/platine/pilotage/contact/PlatineContactDto.java b/src/main/java/fr/insee/protools/backend/dto/platine/pilotage/contact/PlatineContactDto.java deleted file mode 100644 index f183a937..00000000 --- a/src/main/java/fr/insee/protools/backend/dto/platine/pilotage/contact/PlatineContactDto.java +++ /dev/null @@ -1,23 +0,0 @@ -package fr.insee.protools.backend.dto.platine.pilotage.contact; - -import fr.insee.protools.backend.dto.platine.pilotage.PlatineAddressDto; -import fr.insee.protools.backend.dto.platine.pilotage.PlatinePilotageGenderType; -import lombok.*; - -@Getter -@Setter -@Builder -@AllArgsConstructor @NoArgsConstructor -public class PlatineContactDto { - - private String identifier; - private String externalId; - private PlatinePilotageGenderType civility; - private String lastName; - private String firstName; - private String function; - private String email; - private String phone; - private PlatineAddressDto address; - -} \ No newline at end of file diff --git a/src/main/java/fr/insee/protools/backend/dto/platine/pilotage/query/ContactAccreditationDto.java b/src/main/java/fr/insee/protools/backend/dto/platine/pilotage/query/ContactAccreditationDto.java deleted file mode 100644 index 95750c92..00000000 --- a/src/main/java/fr/insee/protools/backend/dto/platine/pilotage/query/ContactAccreditationDto.java +++ /dev/null @@ -1,22 +0,0 @@ -package fr.insee.protools.backend.dto.platine.pilotage.query; - -import fr.insee.protools.backend.dto.platine.pilotage.PlatineAddressDto; -import lombok.Builder; -import lombok.Data; - -@Data -@Builder -public class ContactAccreditationDto { - - private String identifier; - private String externalId; - private boolean isMain; - private String civility; - private String lastName; - private String firstName; - private String function; - private String email; - private String phone; - private PlatineAddressDto address; - -} diff --git a/src/main/java/fr/insee/protools/backend/dto/platine/pilotage/query/QuestioningWebclientDto.java b/src/main/java/fr/insee/protools/backend/dto/platine/pilotage/query/QuestioningWebclientDto.java deleted file mode 100644 index 6f2cb0fb..00000000 --- a/src/main/java/fr/insee/protools/backend/dto/platine/pilotage/query/QuestioningWebclientDto.java +++ /dev/null @@ -1,18 +0,0 @@ -package fr.insee.protools.backend.dto.platine.pilotage.query; - -import fr.insee.protools.backend.dto.platine.pilotage.questioning.PlatineQuestioningSurveyUnitDto; -import lombok.Builder; -import lombok.Data; - -import java.util.List; - -@Data -@Builder -public class QuestioningWebclientDto { - - private String idPartitioning; - private String modelName; - private PlatineQuestioningSurveyUnitDto surveyUnit; - private List contacts; - -} diff --git a/src/main/java/fr/insee/protools/backend/dto/platine/pilotage/questioning/PlatineQuestioningSurveyUnitDto.java b/src/main/java/fr/insee/protools/backend/dto/platine/pilotage/questioning/PlatineQuestioningSurveyUnitDto.java deleted file mode 100644 index 88e80fc1..00000000 --- a/src/main/java/fr/insee/protools/backend/dto/platine/pilotage/questioning/PlatineQuestioningSurveyUnitDto.java +++ /dev/null @@ -1,17 +0,0 @@ -package fr.insee.protools.backend.dto.platine.pilotage.questioning; - -import fr.insee.protools.backend.dto.platine.pilotage.PlatineAddressDto; -import lombok.Builder; -import lombok.Getter; -import lombok.Setter; - -@Getter -@Setter -@Builder -public class PlatineQuestioningSurveyUnitDto { - - private String idSu; - private String identificationCode; - private String identificationName; - private PlatineAddressDto address; -} diff --git a/src/main/java/fr/insee/protools/backend/dto/platine_sabiane_questionnaire/MetadataConstants.java b/src/main/java/fr/insee/protools/backend/dto/platine_sabiane_questionnaire/MetadataConstants.java deleted file mode 100644 index 958e05e3..00000000 --- a/src/main/java/fr/insee/protools/backend/dto/platine_sabiane_questionnaire/MetadataConstants.java +++ /dev/null @@ -1,27 +0,0 @@ -package fr.insee.protools.backend.dto.platine_sabiane_questionnaire; - -/** - * Class defining names of the meta data to pass to the questionnaire - * suppress warning on var names so it can match with the values - */ -@java.lang.SuppressWarnings("squid:S115") -public class MetadataConstants { - - public static final String Enq_LibelleEnquete="Enq_LibelleEnquete"; - public static final String Enq_ObjectifsCourts="Enq_ObjectifsCourts"; - public static final String Enq_CaractereObligatoire="Enq_CaractereObligatoire"; - public static final String Enq_NumeroVisa="Enq_NumeroVisa"; - public static final String Enq_MinistereTutelle="Enq_MinistereTutelle"; - public static final String Enq_ParutionJo="Enq_ParutionJo"; - public static final String Enq_DateParutionJo="Enq_DateParutionJo"; - public static final String Enq_RespOperationnel="Enq_RespOperationnel"; - public static final String Enq_RespTraitement="Enq_RespTraitement"; - public static final String Enq_AnneeVisa="Enq_AnneeVisa"; - public static final String Enq_QualiteStatistique="Enq_QualiteStatistique"; - public static final String Enq_TestNonLabellise="Enq_TestNonLabellise"; - public static final String Loi_statistique="Loi_statistique"; - public static final String Loi_rgpd="Loi_rgpd"; - public static final String Loi_informatique="Loi_informatique"; - - private MetadataConstants(){} -} diff --git a/src/main/java/fr/insee/protools/backend/dto/platine_sabiane_questionnaire/NomenclatureDto.java b/src/main/java/fr/insee/protools/backend/dto/platine_sabiane_questionnaire/NomenclatureDto.java deleted file mode 100644 index b5c6fa8e..00000000 --- a/src/main/java/fr/insee/protools/backend/dto/platine_sabiane_questionnaire/NomenclatureDto.java +++ /dev/null @@ -1,14 +0,0 @@ -package fr.insee.protools.backend.dto.platine_sabiane_questionnaire; - -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.databind.JsonNode; -import lombok.AllArgsConstructor; -import lombok.Data; - -@Data @AllArgsConstructor -@JsonInclude(JsonInclude.Include.NON_NULL) -public class NomenclatureDto { - private String id; - private String label; - private JsonNode value; -} diff --git a/src/main/java/fr/insee/protools/backend/dto/platine_sabiane_questionnaire/QuestionnaireModelCreateDto.java b/src/main/java/fr/insee/protools/backend/dto/platine_sabiane_questionnaire/QuestionnaireModelCreateDto.java deleted file mode 100644 index 67c9ccf2..00000000 --- a/src/main/java/fr/insee/protools/backend/dto/platine_sabiane_questionnaire/QuestionnaireModelCreateDto.java +++ /dev/null @@ -1,19 +0,0 @@ -package fr.insee.protools.backend.dto.platine_sabiane_questionnaire; - -import com.fasterxml.jackson.databind.JsonNode; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.util.Set; - -@Data -@AllArgsConstructor -@NoArgsConstructor -public class QuestionnaireModelCreateDto { - - private String idQuestionnaireModel; - private String label; - private JsonNode value; - private Set requiredNomenclatureIds; -} \ No newline at end of file diff --git a/src/main/java/fr/insee/protools/backend/dto/platine_sabiane_questionnaire/campaign/CampaignDto.java b/src/main/java/fr/insee/protools/backend/dto/platine_sabiane_questionnaire/campaign/CampaignDto.java deleted file mode 100644 index bfd0e3fe..00000000 --- a/src/main/java/fr/insee/protools/backend/dto/platine_sabiane_questionnaire/campaign/CampaignDto.java +++ /dev/null @@ -1,23 +0,0 @@ -package fr.insee.protools.backend.dto.platine_sabiane_questionnaire.campaign; - -import com.fasterxml.jackson.annotation.JsonInclude; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; - -import java.util.Set; - -@Builder -@AllArgsConstructor -@Data -@JsonInclude(JsonInclude.Include.NON_NULL) -public class CampaignDto { - String id; - String label; - Set questionnaireIds; - MetadataValue metadata; - - - - -} \ No newline at end of file diff --git a/src/main/java/fr/insee/protools/backend/dto/platine_sabiane_questionnaire/campaign/MetadataValue.java b/src/main/java/fr/insee/protools/backend/dto/platine_sabiane_questionnaire/campaign/MetadataValue.java deleted file mode 100644 index 0beac878..00000000 --- a/src/main/java/fr/insee/protools/backend/dto/platine_sabiane_questionnaire/campaign/MetadataValue.java +++ /dev/null @@ -1,15 +0,0 @@ -package fr.insee.protools.backend.dto.platine_sabiane_questionnaire.campaign; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -@Builder -@Data -@AllArgsConstructor -@NoArgsConstructor -public -class MetadataValue { - MetadataVariables value; -} \ No newline at end of file diff --git a/src/main/java/fr/insee/protools/backend/dto/platine_sabiane_questionnaire/campaign/MetadataValueItem.java b/src/main/java/fr/insee/protools/backend/dto/platine_sabiane_questionnaire/campaign/MetadataValueItem.java deleted file mode 100644 index d92a0c27..00000000 --- a/src/main/java/fr/insee/protools/backend/dto/platine_sabiane_questionnaire/campaign/MetadataValueItem.java +++ /dev/null @@ -1,16 +0,0 @@ -package fr.insee.protools.backend.dto.platine_sabiane_questionnaire.campaign; - -import lombok.Data; -import lombok.NoArgsConstructor; - -@Data -@NoArgsConstructor -public class MetadataValueItem{ - String name; - Object value; - - public MetadataValueItem(String name, Object value) { - this.name = name; - this.value = value; - } -} \ No newline at end of file diff --git a/src/main/java/fr/insee/protools/backend/dto/platine_sabiane_questionnaire/campaign/MetadataVariables.java b/src/main/java/fr/insee/protools/backend/dto/platine_sabiane_questionnaire/campaign/MetadataVariables.java deleted file mode 100644 index 2059ffff..00000000 --- a/src/main/java/fr/insee/protools/backend/dto/platine_sabiane_questionnaire/campaign/MetadataVariables.java +++ /dev/null @@ -1,17 +0,0 @@ -package fr.insee.protools.backend.dto.platine_sabiane_questionnaire.campaign; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.util.List; - -@Builder -@Data -@NoArgsConstructor@AllArgsConstructor -public -class MetadataVariables{ - List variables; - String inseeContext; -} \ No newline at end of file diff --git a/src/main/java/fr/insee/protools/backend/dto/platine_sabiane_questionnaire/surveyunit/SurveyUnitResponseDto.java b/src/main/java/fr/insee/protools/backend/dto/platine_sabiane_questionnaire/surveyunit/SurveyUnitResponseDto.java deleted file mode 100644 index ba4dad45..00000000 --- a/src/main/java/fr/insee/protools/backend/dto/platine_sabiane_questionnaire/surveyunit/SurveyUnitResponseDto.java +++ /dev/null @@ -1,19 +0,0 @@ -package fr.insee.protools.backend.dto.platine_sabiane_questionnaire.surveyunit; - - -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.databind.JsonNode; -import lombok.Builder; -import lombok.Data; - -@Builder -@Data -@JsonInclude(JsonInclude.Include.NON_NULL) -public class SurveyUnitResponseDto { - String id; - String questionnaireId; - private JsonNode personalization; - private JsonNode data; - private JsonNode comment; -// private JsonNode stateData; -} \ No newline at end of file diff --git a/src/main/java/fr/insee/protools/backend/dto/rem/AdditionalInformationDto.java b/src/main/java/fr/insee/protools/backend/dto/rem/AdditionalInformationDto.java deleted file mode 100644 index 9599987d..00000000 --- a/src/main/java/fr/insee/protools/backend/dto/rem/AdditionalInformationDto.java +++ /dev/null @@ -1,15 +0,0 @@ -package fr.insee.protools.backend.dto.rem; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -@Builder -@Data -@NoArgsConstructor @AllArgsConstructor -public class AdditionalInformationDto { - - private String key; - private String value; -} \ No newline at end of file diff --git a/src/main/java/fr/insee/protools/backend/dto/rem/EmailDto.java b/src/main/java/fr/insee/protools/backend/dto/rem/EmailDto.java deleted file mode 100644 index 02a58cd5..00000000 --- a/src/main/java/fr/insee/protools/backend/dto/rem/EmailDto.java +++ /dev/null @@ -1,16 +0,0 @@ -package fr.insee.protools.backend.dto.rem; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -@Builder -@Data -@NoArgsConstructor -@AllArgsConstructor -public class EmailDto { - - private Boolean favorite; - private String mailAddress; -} \ No newline at end of file diff --git a/src/main/java/fr/insee/protools/backend/dto/rem/LocationHelpDto.java b/src/main/java/fr/insee/protools/backend/dto/rem/LocationHelpDto.java deleted file mode 100644 index 029bcb03..00000000 --- a/src/main/java/fr/insee/protools/backend/dto/rem/LocationHelpDto.java +++ /dev/null @@ -1,23 +0,0 @@ -package fr.insee.protools.backend.dto.rem; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -@Builder -@Data -@NoArgsConstructor -@AllArgsConstructor -public class LocationHelpDto { - - private String cityCode; - private String building; - private String floor; - private String staircase; - private String door; - private String iris; - private String sector; - private Boolean elevator; - private Boolean cityPriorityDistrict; -} \ No newline at end of file diff --git a/src/main/java/fr/insee/protools/backend/dto/rem/OtherIdentifierDto.java b/src/main/java/fr/insee/protools/backend/dto/rem/OtherIdentifierDto.java deleted file mode 100644 index d2a77507..00000000 --- a/src/main/java/fr/insee/protools/backend/dto/rem/OtherIdentifierDto.java +++ /dev/null @@ -1,26 +0,0 @@ -package fr.insee.protools.backend.dto.rem; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -@Builder -@Data -@AllArgsConstructor -@NoArgsConstructor -public class OtherIdentifierDto { - - private String numfa; - private String rges; - private String ssech; - private String cle; - private String le; - private String ec; - private String bs; - private String nograp; - private String nolog; - private String noi; - private String nole; - private String autre; -} diff --git a/src/main/java/fr/insee/protools/backend/dto/rem/PersonDto.java b/src/main/java/fr/insee/protools/backend/dto/rem/PersonDto.java deleted file mode 100644 index c3d8ac90..00000000 --- a/src/main/java/fr/insee/protools/backend/dto/rem/PersonDto.java +++ /dev/null @@ -1,31 +0,0 @@ -package fr.insee.protools.backend.dto.rem; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.util.List; - -@Builder -@Data -@NoArgsConstructor -@AllArgsConstructor -public class PersonDto { - - private Integer index; - private String externalId; - private String function; - private String gender; - private String firstName; - private String lastName; - private String birthName; - private String dateOfBirth; - private Boolean surveyed; - private Boolean main; - private Boolean coDeclarant; - private List phoneNumbers; - private List emails; - //private REMAddressDto address; //Will be used for buisness; not for household - -} \ No newline at end of file diff --git a/src/main/java/fr/insee/protools/backend/dto/rem/PhoneNumberDto.java b/src/main/java/fr/insee/protools/backend/dto/rem/PhoneNumberDto.java deleted file mode 100644 index 5b60e41b..00000000 --- a/src/main/java/fr/insee/protools/backend/dto/rem/PhoneNumberDto.java +++ /dev/null @@ -1,16 +0,0 @@ -package fr.insee.protools.backend.dto.rem; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -@Builder -@Data -@NoArgsConstructor -@AllArgsConstructor -public class PhoneNumberDto { - private REMPhoneSource source; - private Boolean favorite; - private String number; -} \ No newline at end of file diff --git a/src/main/java/fr/insee/protools/backend/dto/rem/REMAddressDto.java b/src/main/java/fr/insee/protools/backend/dto/rem/REMAddressDto.java deleted file mode 100644 index 534266ae..00000000 --- a/src/main/java/fr/insee/protools/backend/dto/rem/REMAddressDto.java +++ /dev/null @@ -1,28 +0,0 @@ -package fr.insee.protools.backend.dto.rem; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -@Builder -@Data -@NoArgsConstructor -@AllArgsConstructor -public class REMAddressDto { - - private String streetNumber; - private String repetitionIndex; - private String streetType; - private String streetName; - private String addressSupplement; - private String cityName; - private String zipCode; - private String cedexCode; - private String cedexName; - private String specialDistribution; - private String countryCode; - private String countryName; - - private LocationHelpDto locationHelp; -} \ No newline at end of file diff --git a/src/main/java/fr/insee/protools/backend/dto/rem/REMPhoneSource.java b/src/main/java/fr/insee/protools/backend/dto/rem/REMPhoneSource.java deleted file mode 100644 index 2a2d7eda..00000000 --- a/src/main/java/fr/insee/protools/backend/dto/rem/REMPhoneSource.java +++ /dev/null @@ -1,5 +0,0 @@ -package fr.insee.protools.backend.dto.rem; - -public enum REMPhoneSource { - OTHER, INITIAL, INTERVIEWER, DIRECTORY -} \ No newline at end of file diff --git a/src/main/java/fr/insee/protools/backend/dto/rem/REMSurveyUnitDto.java b/src/main/java/fr/insee/protools/backend/dto/rem/REMSurveyUnitDto.java deleted file mode 100644 index e1a733b2..00000000 --- a/src/main/java/fr/insee/protools/backend/dto/rem/REMSurveyUnitDto.java +++ /dev/null @@ -1,36 +0,0 @@ -package fr.insee.protools.backend.dto.rem; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import lombok.*; - -import java.util.List; - -@Builder -@Data -@NoArgsConstructor -@AllArgsConstructor -public class REMSurveyUnitDto { - - private Long repositoryId; - - private String externalId; - - private String externalName; - - private REMAddressDto address; - - private List persons; - private OtherIdentifierDto otherIdentifier; - - private List additionalInformations; - - @Getter(AccessLevel.NONE) - private JsonNode externals; - - public JsonNode getExternals() { - if(externals==null || externals.isNull()) - externals= new ObjectMapper().createObjectNode(); - return this.externals; - } -} \ No newline at end of file diff --git a/src/main/java/fr/insee/protools/backend/dto/rem/SampleDto.java b/src/main/java/fr/insee/protools/backend/dto/rem/SampleDto.java deleted file mode 100644 index 3649cad7..00000000 --- a/src/main/java/fr/insee/protools/backend/dto/rem/SampleDto.java +++ /dev/null @@ -1,18 +0,0 @@ -package fr.insee.protools.backend.dto.rem; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -@Builder -@Data -@NoArgsConstructor -@AllArgsConstructor -public class SampleDto { - - private Long id; - - private String label; - -} \ No newline at end of file diff --git a/src/main/java/fr/insee/protools/backend/dto/rem/SuIdMappingJson.java b/src/main/java/fr/insee/protools/backend/dto/rem/SuIdMappingJson.java deleted file mode 100644 index 5c21efae..00000000 --- a/src/main/java/fr/insee/protools/backend/dto/rem/SuIdMappingJson.java +++ /dev/null @@ -1,18 +0,0 @@ -package fr.insee.protools.backend.dto.rem; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.util.List; - -@Data -@NoArgsConstructor -@AllArgsConstructor -@Builder -public class SuIdMappingJson { - private long partitionId; - private List data; - private int count; -} diff --git a/src/main/java/fr/insee/protools/backend/dto/rem/SuIdMappingRecord.java b/src/main/java/fr/insee/protools/backend/dto/rem/SuIdMappingRecord.java deleted file mode 100644 index cd7b0129..00000000 --- a/src/main/java/fr/insee/protools/backend/dto/rem/SuIdMappingRecord.java +++ /dev/null @@ -1,5 +0,0 @@ -package fr.insee.protools.backend.dto.rem; - -public record SuIdMappingRecord(Long repositoryId, String externalId) { - -} diff --git a/src/main/java/fr/insee/protools/backend/dto/rem_tmp/InterrogationAccountDto.java b/src/main/java/fr/insee/protools/backend/dto/rem_tmp/InterrogationAccountDto.java new file mode 100644 index 00000000..842e681f --- /dev/null +++ b/src/main/java/fr/insee/protools/backend/dto/rem_tmp/InterrogationAccountDto.java @@ -0,0 +1,164 @@ +package fr.insee.protools.backend.dto.rem_tmp; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonTypeName; +import jakarta.annotation.Generated; +import jakarta.validation.Valid; + +import java.util.Objects; +import java.util.UUID; + +/** + * InterrogationAccountDto + */ + +@JsonTypeName("InterrogationAccount") +@Generated(value = "org.openapitools.codegen.languages.SpringCodegen", date = "2024-08-30T10:25:29.966974800+02:00[Europe/Paris]", comments = "Generator version: 7.8.0") +public class InterrogationAccountDto { + + private UUID interrogationId; + + private String account; + + public InterrogationAccountDto interrogationId(UUID interrogationId) { + this.interrogationId = interrogationId; + return this; + } + + /** + * Get interrogationId + * @return interrogationId + */ + @Valid + @JsonProperty("interrogationId") + public UUID getInterrogationId() { + return interrogationId; + } + + public void setInterrogationId(UUID interrogationId) { + this.interrogationId = interrogationId; + } + + public InterrogationAccountDto account(String account) { + this.account = account; + return this; + } + + /** + * Get account + * @return account + */ + + @JsonProperty("account") + public String getAccount() { + return account; + } + + public void setAccount(String account) { + this.account = account; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + InterrogationAccountDto interrogationAccount = (InterrogationAccountDto) o; + return Objects.equals(this.interrogationId, interrogationAccount.interrogationId) && + Objects.equals(this.account, interrogationAccount.account); + } + + @Override + public int hashCode() { + return Objects.hash(interrogationId, account); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class InterrogationAccountDto {\n"); + sb.append(" interrogationId: ").append(toIndentedString(interrogationId)).append("\n"); + sb.append(" account: ").append(toIndentedString(account)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + public static class Builder { + + private InterrogationAccountDto instance; + + public Builder() { + this(new InterrogationAccountDto()); + } + + protected Builder(InterrogationAccountDto instance) { + this.instance = instance; + } + + protected Builder copyOf(InterrogationAccountDto value) { + this.instance.setInterrogationId(value.interrogationId); + this.instance.setAccount(value.account); + return this; + } + + public Builder interrogationId(UUID interrogationId) { + this.instance.interrogationId(interrogationId); + return this; + } + + public Builder account(String account) { + this.instance.account(account); + return this; + } + + /** + * returns a built InterrogationAccountDto instance. + * + * The builder is not reusable (NullPointerException) + */ + public InterrogationAccountDto build() { + try { + return this.instance; + } finally { + // ensure that this.instance is not reused + this.instance = null; + } + } + + @Override + public String toString() { + return getClass() + "=(" + instance + ")"; + } + } + + /** + * Create a builder with no initialized field (except for the default values). + */ + public static Builder builder() { + return new Builder(); + } + + /** + * Create a builder with a shallow copy of this instance. + */ + public Builder toBuilder() { + Builder builder = new Builder(); + return builder.copyOf(this); + } + +} + diff --git a/src/main/java/fr/insee/protools/backend/dto/rem_tmp/InterrogationIdentifiersDto.java b/src/main/java/fr/insee/protools/backend/dto/rem_tmp/InterrogationIdentifiersDto.java new file mode 100644 index 00000000..3e1f30f9 --- /dev/null +++ b/src/main/java/fr/insee/protools/backend/dto/rem_tmp/InterrogationIdentifiersDto.java @@ -0,0 +1,193 @@ +package fr.insee.protools.backend.dto.rem_tmp; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonTypeName; +import jakarta.annotation.Generated; +import jakarta.validation.Valid; + +import java.util.Objects; +import java.util.UUID; + +/** + * InterrogationIdentifiersDto + */ + +@JsonTypeName("InterrogationIdentifiers") +@Generated(value = "org.openapitools.codegen.languages.SpringCodegen", date = "2024-08-30T10:25:29.966974800+02:00[Europe/Paris]", comments = "Generator version: 7.8.0") +public class InterrogationIdentifiersDto { + + private UUID interrogationId; + + private UUID surveyUnitId; + + private String originId; + + public InterrogationIdentifiersDto interrogationId(UUID interrogationId) { + this.interrogationId = interrogationId; + return this; + } + + /** + * Get interrogationId + * @return interrogationId + */ + @Valid + @JsonProperty("interrogationId") + public UUID getInterrogationId() { + return interrogationId; + } + + public void setInterrogationId(UUID interrogationId) { + this.interrogationId = interrogationId; + } + + public InterrogationIdentifiersDto surveyUnitId(UUID surveyUnitId) { + this.surveyUnitId = surveyUnitId; + return this; + } + + /** + * Get surveyUnitId + * @return surveyUnitId + */ + @Valid + @JsonProperty("surveyUnitId") + public UUID getSurveyUnitId() { + return surveyUnitId; + } + + public void setSurveyUnitId(UUID surveyUnitId) { + this.surveyUnitId = surveyUnitId; + } + + public InterrogationIdentifiersDto originId(String originId) { + this.originId = originId; + return this; + } + + /** + * Get originId + * @return originId + */ + + @JsonProperty("originId") + public String getOriginId() { + return originId; + } + + public void setOriginId(String originId) { + this.originId = originId; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + InterrogationIdentifiersDto interrogationIdentifiers = (InterrogationIdentifiersDto) o; + return Objects.equals(this.interrogationId, interrogationIdentifiers.interrogationId) && + Objects.equals(this.surveyUnitId, interrogationIdentifiers.surveyUnitId) && + Objects.equals(this.originId, interrogationIdentifiers.originId); + } + + @Override + public int hashCode() { + return Objects.hash(interrogationId, surveyUnitId, originId); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class InterrogationIdentifiersDto {\n"); + sb.append(" interrogationId: ").append(toIndentedString(interrogationId)).append("\n"); + sb.append(" surveyUnitId: ").append(toIndentedString(surveyUnitId)).append("\n"); + sb.append(" originId: ").append(toIndentedString(originId)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + public static class Builder { + + private InterrogationIdentifiersDto instance; + + public Builder() { + this(new InterrogationIdentifiersDto()); + } + + protected Builder(InterrogationIdentifiersDto instance) { + this.instance = instance; + } + + protected Builder copyOf(InterrogationIdentifiersDto value) { + this.instance.setInterrogationId(value.interrogationId); + this.instance.setSurveyUnitId(value.surveyUnitId); + this.instance.setOriginId(value.originId); + return this; + } + + public Builder interrogationId(UUID interrogationId) { + this.instance.interrogationId(interrogationId); + return this; + } + + public Builder surveyUnitId(UUID surveyUnitId) { + this.instance.surveyUnitId(surveyUnitId); + return this; + } + + public Builder originId(String originId) { + this.instance.originId(originId); + return this; + } + + /** + * returns a built InterrogationIdentifiersDto instance. + * + * The builder is not reusable (NullPointerException) + */ + public InterrogationIdentifiersDto build() { + try { + return this.instance; + } finally { + // ensure that this.instance is not reused + this.instance = null; + } + } + + @Override + public String toString() { + return getClass() + "=(" + instance + ")"; + } + } + + /** + * Create a builder with no initialized field (except for the default values). + */ + public static Builder builder() { + return new Builder(); + } + + /** + * Create a builder with a shallow copy of this instance. + */ + public Builder toBuilder() { + Builder builder = new Builder(); + return builder.copyOf(this); + } + +} + diff --git a/src/main/java/fr/insee/protools/backend/dto/sabiane/pilotage/AddressDto.java b/src/main/java/fr/insee/protools/backend/dto/sabiane/pilotage/AddressDto.java deleted file mode 100644 index cd330d1c..00000000 --- a/src/main/java/fr/insee/protools/backend/dto/sabiane/pilotage/AddressDto.java +++ /dev/null @@ -1,57 +0,0 @@ -package fr.insee.protools.backend.dto.sabiane.pilotage; - -import com.fasterxml.jackson.annotation.JsonInclude; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -@Data -@AllArgsConstructor -@Builder -@NoArgsConstructor -@JsonInclude(JsonInclude.Include.NON_NULL) -public class AddressDto { - - /** - * First line of the AdressDto - */ - private String l1; - - /** - * Second line of the AdressDto - */ - private String l2; - - /** - * Third line of the AdressDto - */ - private String l3; - - /** - * Fourth line of the AdressDto - */ - private String l4; - - /** - * Fifth line of the AdressDto - */ - private String l5; - - /** - * Sixtth line of the AdressDto - */ - private String l6; - - /** - * Seventh line of the AdressDto - */ - private String l7; - - private Boolean elevator; - private String building; - private String floor; - private String door; - private String staircase; - private Boolean cityPriorityDistrict; -} \ No newline at end of file diff --git a/src/main/java/fr/insee/protools/backend/dto/sabiane/pilotage/CampaignContextDto.java b/src/main/java/fr/insee/protools/backend/dto/sabiane/pilotage/CampaignContextDto.java deleted file mode 100644 index dbc66489..00000000 --- a/src/main/java/fr/insee/protools/backend/dto/sabiane/pilotage/CampaignContextDto.java +++ /dev/null @@ -1,23 +0,0 @@ -package fr.insee.protools.backend.dto.sabiane.pilotage; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.util.List; - -@Data -@AllArgsConstructor -@Builder -@NoArgsConstructor -public class CampaignContextDto { - private String campaign; - private String campaignLabel; - private List visibilities; - private List referents; - private String email; - private IdentificationConfiguration identificationConfiguration; - private ContactOutcomeConfiguration contactOutcomeConfiguration; - private ContactAttemptConfiguration contactAttemptConfiguration; -} \ No newline at end of file diff --git a/src/main/java/fr/insee/protools/backend/dto/sabiane/pilotage/ContactAttemptConfiguration.java b/src/main/java/fr/insee/protools/backend/dto/sabiane/pilotage/ContactAttemptConfiguration.java deleted file mode 100644 index 904aa294..00000000 --- a/src/main/java/fr/insee/protools/backend/dto/sabiane/pilotage/ContactAttemptConfiguration.java +++ /dev/null @@ -1,47 +0,0 @@ -package fr.insee.protools.backend.dto.sabiane.pilotage; - -public enum ContactAttemptConfiguration { - F2F("faf"), TEL("tel"); - - /** - * label of the ContactAttemptConfiguration - */ - private final String label; - - /** - * Defaut constructor for a ContactAttemptConfiguration - * - * @param label - */ - ContactAttemptConfiguration(String label) { - this.label = label; - } - - /** - * Get the label for a ContactAttemptConfiguration - * - * @return label - */ - public String getLabel() { - return label; - } - - public static ContactAttemptConfiguration valueOfLabel(String label) { - for (ContactAttemptConfiguration e : values()) { - if (e.label.equalsIgnoreCase(label)) { - return e; - } - } - throw new IllegalArgumentException("No enum constant with value="+label+ " for class " + ContactAttemptConfiguration.class.getCanonicalName()); - } - public static String[] labels(){ - String[] results = new String[values().length]; - int i=0; - for (var e : values()) { - results[i]=e.label; - i++; - } - return results; - } - -} \ No newline at end of file diff --git a/src/main/java/fr/insee/protools/backend/dto/sabiane/pilotage/ContactOutcomeConfiguration.java b/src/main/java/fr/insee/protools/backend/dto/sabiane/pilotage/ContactOutcomeConfiguration.java deleted file mode 100644 index 2d00cb44..00000000 --- a/src/main/java/fr/insee/protools/backend/dto/sabiane/pilotage/ContactOutcomeConfiguration.java +++ /dev/null @@ -1,47 +0,0 @@ -package fr.insee.protools.backend.dto.sabiane.pilotage; - -public enum ContactOutcomeConfiguration { - F2F("faf"), TEL("tel"); - - /** - * label of the ContactOutcomeConfiguration - */ - private final String label; - - /** - * Defaut constructor for a ContactOutcomeConfiguration - * - * @param label - */ - ContactOutcomeConfiguration(String label) { - this.label = label; - } - - /** - * Get the label for a ContactOutcomeConfiguration - * - * @return label - */ - public String getLabel() { - return label; - } - - public static ContactOutcomeConfiguration valueOfLabel(String label) { - for (ContactOutcomeConfiguration e : values()) { - if (e.label.equalsIgnoreCase(label)) { - return e; - } - } - throw new IllegalArgumentException("No enum constant with value="+label+ " for class " + ContactOutcomeConfiguration.class.getCanonicalName()); - } - - public static String[] labels(){ - String[] results = new String[values().length]; - int i=0; - for (var e : values()) { - results[i]=e.label; - i++; - } - return results; - } -} \ No newline at end of file diff --git a/src/main/java/fr/insee/protools/backend/dto/sabiane/pilotage/IdentificationConfiguration.java b/src/main/java/fr/insee/protools/backend/dto/sabiane/pilotage/IdentificationConfiguration.java deleted file mode 100644 index a8a10735..00000000 --- a/src/main/java/fr/insee/protools/backend/dto/sabiane/pilotage/IdentificationConfiguration.java +++ /dev/null @@ -1,49 +0,0 @@ -package fr.insee.protools.backend.dto.sabiane.pilotage; - -public enum IdentificationConfiguration { - //"Identification - Access - Situation - Category - Occupant" - IASCO("faf_logement"), - NOIDENT("aucun"); - - /** - * label of the IdentificationConfiguration - */ - private final String label; - - /** - * Defaut constructor for a IdentificationConfiguration - * - * @param label - */ - IdentificationConfiguration(String label) { - this.label = label; - } - - /** - * Get the label for a IdentificationConfiguration - * - * @return label - */ - public String getLabel() { - return label; - } - - public static IdentificationConfiguration valueOfLabel(String label) { - for (IdentificationConfiguration e : values()) { - if (e.label.equalsIgnoreCase(label)) { - return e; - } - } - throw new IllegalArgumentException("No enum constant with value="+label+ " for class " + IdentificationConfiguration.class.getCanonicalName()); - } - - public static String[] labels(){ - String[] results = new String[values().length]; - int i=0; - for (var e : values()) { - results[i]=e.label; - i++; - } - return results; - } -} \ No newline at end of file diff --git a/src/main/java/fr/insee/protools/backend/dto/sabiane/pilotage/PhoneNumber.java b/src/main/java/fr/insee/protools/backend/dto/sabiane/pilotage/PhoneNumber.java deleted file mode 100644 index 16d354b6..00000000 --- a/src/main/java/fr/insee/protools/backend/dto/sabiane/pilotage/PhoneNumber.java +++ /dev/null @@ -1,10 +0,0 @@ -package fr.insee.protools.backend.dto.sabiane.pilotage; - - -public class PhoneNumber { - - Source source; - boolean favorite; - String number; - -} \ No newline at end of file diff --git a/src/main/java/fr/insee/protools/backend/dto/sabiane/pilotage/ReferentDto.java b/src/main/java/fr/insee/protools/backend/dto/sabiane/pilotage/ReferentDto.java deleted file mode 100644 index 91a96adc..00000000 --- a/src/main/java/fr/insee/protools/backend/dto/sabiane/pilotage/ReferentDto.java +++ /dev/null @@ -1,17 +0,0 @@ -package fr.insee.protools.backend.dto.sabiane.pilotage; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -@Data -@Builder -@AllArgsConstructor -@NoArgsConstructor -public class ReferentDto { - private String firstName; - private String lastName; - private String phoneNumber; - private String role; -} \ No newline at end of file diff --git a/src/main/java/fr/insee/protools/backend/dto/sabiane/pilotage/SabianePersonDto.java b/src/main/java/fr/insee/protools/backend/dto/sabiane/pilotage/SabianePersonDto.java deleted file mode 100644 index fe0948e6..00000000 --- a/src/main/java/fr/insee/protools/backend/dto/sabiane/pilotage/SabianePersonDto.java +++ /dev/null @@ -1,29 +0,0 @@ -package fr.insee.protools.backend.dto.sabiane.pilotage; - -import com.fasterxml.jackson.annotation.JsonInclude; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.util.List; - -@JsonInclude(JsonInclude.Include.NON_NULL) -@Data -@AllArgsConstructor -@Builder -@NoArgsConstructor -public class SabianePersonDto { - private Long id; - private SabianeTitle title; - private String firstName; - private String lastName; - private String email; - private Long birthdate; - - private Boolean favoriteEmail; - private Boolean privileged; - private List phoneNumbers; - - -} diff --git a/src/main/java/fr/insee/protools/backend/dto/sabiane/pilotage/SabianePhoneNumberDto.java b/src/main/java/fr/insee/protools/backend/dto/sabiane/pilotage/SabianePhoneNumberDto.java deleted file mode 100644 index 4c64641f..00000000 --- a/src/main/java/fr/insee/protools/backend/dto/sabiane/pilotage/SabianePhoneNumberDto.java +++ /dev/null @@ -1,18 +0,0 @@ -package fr.insee.protools.backend.dto.sabiane.pilotage; - - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -@Data -@AllArgsConstructor -@Builder -@NoArgsConstructor -public class SabianePhoneNumberDto { - - private Source source; - private boolean favorite; - private String number; -} \ No newline at end of file diff --git a/src/main/java/fr/insee/protools/backend/dto/sabiane/pilotage/SabianeTitle.java b/src/main/java/fr/insee/protools/backend/dto/sabiane/pilotage/SabianeTitle.java deleted file mode 100644 index 4f3d5233..00000000 --- a/src/main/java/fr/insee/protools/backend/dto/sabiane/pilotage/SabianeTitle.java +++ /dev/null @@ -1,15 +0,0 @@ -package fr.insee.protools.backend.dto.sabiane.pilotage; - -import lombok.Getter; - -@Getter -public enum SabianeTitle { - MISTER("M","Mister"), MISS("MME","MISS"); - - private final String frenchCivility; - private final String sabianeTitle; - SabianeTitle(String frenchCivility, String sabianeTitle) { - this.frenchCivility = frenchCivility; - this.sabianeTitle = sabianeTitle; - } -} \ No newline at end of file diff --git a/src/main/java/fr/insee/protools/backend/dto/sabiane/pilotage/SampleIdentifiersDto.java b/src/main/java/fr/insee/protools/backend/dto/sabiane/pilotage/SampleIdentifiersDto.java deleted file mode 100644 index 7e5a196e..00000000 --- a/src/main/java/fr/insee/protools/backend/dto/sabiane/pilotage/SampleIdentifiersDto.java +++ /dev/null @@ -1,26 +0,0 @@ -package fr.insee.protools.backend.dto.sabiane.pilotage; - - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -@Data -@NoArgsConstructor -@AllArgsConstructor -@Builder -public class SampleIdentifiersDto { - private Integer bs; - private String ec; - private Integer le; - private Integer noi; - private Integer numfa; - private Integer rges; - private Long ssech; - private Integer nolog; - private Integer nole; - private String autre; - private String nograp; - -} \ No newline at end of file diff --git a/src/main/java/fr/insee/protools/backend/dto/sabiane/pilotage/Source.java b/src/main/java/fr/insee/protools/backend/dto/sabiane/pilotage/Source.java deleted file mode 100644 index 36eb27ab..00000000 --- a/src/main/java/fr/insee/protools/backend/dto/sabiane/pilotage/Source.java +++ /dev/null @@ -1,5 +0,0 @@ -package fr.insee.protools.backend.dto.sabiane.pilotage; - -public enum Source { - FISCAL, DIRECTORY, INTERVIEWER -} \ No newline at end of file diff --git a/src/main/java/fr/insee/protools/backend/dto/sabiane/pilotage/StateDto.java b/src/main/java/fr/insee/protools/backend/dto/sabiane/pilotage/StateDto.java deleted file mode 100644 index c20db44d..00000000 --- a/src/main/java/fr/insee/protools/backend/dto/sabiane/pilotage/StateDto.java +++ /dev/null @@ -1,16 +0,0 @@ -package fr.insee.protools.backend.dto.sabiane.pilotage; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -@Data -@NoArgsConstructor -@AllArgsConstructor -@Builder -public class StateDto { - - private Long date; - private StateType type; -} \ No newline at end of file diff --git a/src/main/java/fr/insee/protools/backend/dto/sabiane/pilotage/StateType.java b/src/main/java/fr/insee/protools/backend/dto/sabiane/pilotage/StateType.java deleted file mode 100644 index 8ba34dc2..00000000 --- a/src/main/java/fr/insee/protools/backend/dto/sabiane/pilotage/StateType.java +++ /dev/null @@ -1,51 +0,0 @@ -package fr.insee.protools.backend.dto.sabiane.pilotage; - -import lombok.NoArgsConstructor; - -/** - * The possible types of a State entity - * @author scorcaud - * - */ -@NoArgsConstructor -public enum StateType { - - NVM("Not visible to management"), - NNS("Not Assigned, not started"), - ANV("Assigned Not visible to interviewer"), - VIN("Visible to the interviewer and not clickable"), - VIC("Visible to the interviewer and clickable"), - PRC("Preparing contact"), - AOC("At least one contact made"), - APS("Appointment scheduled"), - INS("Interview started"), - WFT("Waiting for transmission"), - WFS("Waiting for synchronization"), - TBR("To be reviewed"), - FIN("Finalized"), - CLO("Closed"), - NVA("Not Available to All"); - - /** - * label of the State type - */ - private String label; - - /** - * Defaut constructor for a StateType - * - * @param label - */ - StateType(String label) { - this.label = label; - } - - /** - * Get the label for a StateType - * - * @return label - */ - public String getLabel() { - return label; - } -} \ No newline at end of file diff --git a/src/main/java/fr/insee/protools/backend/dto/sabiane/pilotage/SurveyUnitContextDto.java b/src/main/java/fr/insee/protools/backend/dto/sabiane/pilotage/SurveyUnitContextDto.java deleted file mode 100644 index 9a309a3b..00000000 --- a/src/main/java/fr/insee/protools/backend/dto/sabiane/pilotage/SurveyUnitContextDto.java +++ /dev/null @@ -1,25 +0,0 @@ -package fr.insee.protools.backend.dto.sabiane.pilotage; - -import java.util.List; - -import com.fasterxml.jackson.annotation.JsonInclude; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -@Data -@AllArgsConstructor -@Builder -@NoArgsConstructor -@JsonInclude(JsonInclude.Include.NON_NULL) -public class SurveyUnitContextDto { - private String id; - private List persons; - private AddressDto address; - private String organizationUnitId; - private Boolean priority; - private String campaign; - private SampleIdentifiersDto sampleIdentifiers; - private List states; -} \ No newline at end of file diff --git a/src/main/java/fr/insee/protools/backend/dto/sabiane/pilotage/VisibilityContextDto.java b/src/main/java/fr/insee/protools/backend/dto/sabiane/pilotage/VisibilityContextDto.java deleted file mode 100644 index 8536dba5..00000000 --- a/src/main/java/fr/insee/protools/backend/dto/sabiane/pilotage/VisibilityContextDto.java +++ /dev/null @@ -1,51 +0,0 @@ -package fr.insee.protools.backend.dto.sabiane.pilotage; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; - -@AllArgsConstructor -@Data -@Builder -@NoArgsConstructor -public class VisibilityContextDto { - - - /** - * Organizational unit of the visibility - */ - private String organizationalUnit; - - /** - * Collection start date of the visibility - */ - private Long collectionStartDate; - - /** - * Collection end date of the visibility - */ - private Long collectionEndDate; - - /** - * Identification phase start date of the visibility - */ - private Long identificationPhaseStartDate; - - /** - * interviewer start date of the visibility - */ - private Long interviewerStartDate; - - /** - * Manager start date of the visibility - */ - private Long managementStartDate; - - /** - * End date of the visibility - */ - private Long endDate; - - -} \ No newline at end of file diff --git a/src/main/java/fr/insee/protools/backend/exception/ProtoolsProcessFlowBPMNError.java b/src/main/java/fr/insee/protools/backend/exception/ProtoolsProcessFlowBPMNError.java new file mode 100644 index 00000000..da390eb4 --- /dev/null +++ b/src/main/java/fr/insee/protools/backend/exception/ProtoolsProcessFlowBPMNError.java @@ -0,0 +1,9 @@ +package fr.insee.protools.backend.exception; + +import static fr.insee.protools.backend.service.BPMNErrorCode.BPMNERROR_CODE_DEFAULT; + +public class ProtoolsProcessFlowBPMNError extends ProtoolsBpmnError { + public ProtoolsProcessFlowBPMNError(String message) { + super(BPMNERROR_CODE_DEFAULT, message); + } +} diff --git a/src/main/java/fr/insee/protools/backend/flowable/types/ListLong.java b/src/main/java/fr/insee/protools/backend/flowable/types/ListLong.java index 0b9a6f79..6af0f907 100644 --- a/src/main/java/fr/insee/protools/backend/flowable/types/ListLong.java +++ b/src/main/java/fr/insee/protools/backend/flowable/types/ListLong.java @@ -1,13 +1,13 @@ package fr.insee.protools.backend.flowable.types; -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; - import org.flowable.common.engine.api.FlowableIllegalArgumentException; import org.flowable.variable.api.types.ValueFields; import org.flowable.variable.api.types.VariableType; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + public class ListLong implements VariableType { @@ -39,7 +39,7 @@ public Object getValue(ValueFields valueFields) { try { return Arrays.stream(valStr.split(",")) .map(Long::parseLong) - .collect(Collectors.toList()); + .toList(); } catch (NumberFormatException e) { throw new FlowableIllegalArgumentException("The given variable value is not comma separated list of Long: '" + valStr+ "'", e); } diff --git a/src/main/java/fr/insee/protools/backend/flowcontrol/FlowcontrolIsSUToFollowUp.java b/src/main/java/fr/insee/protools/backend/flowcontrol/FlowcontrolIsSUToFollowUp.java deleted file mode 100644 index e33efc96..00000000 --- a/src/main/java/fr/insee/protools/backend/flowcontrol/FlowcontrolIsSUToFollowUp.java +++ /dev/null @@ -1,52 +0,0 @@ -package fr.insee.protools.backend.flowcontrol; - -import com.fasterxml.jackson.databind.JsonNode; -import fr.insee.protools.backend.service.DelegateContextVerifier; -import fr.insee.protools.backend.service.context.ContextService; -import fr.insee.protools.backend.service.utils.FlowableVariableUtils; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.tuple.Triple; -import org.flowable.engine.delegate.DelegateExecution; -import org.flowable.engine.delegate.JavaDelegate; -import org.springframework.stereotype.Service; - -import java.time.Instant; - -import static fr.insee.protools.backend.service.FlowableVariableNameConstants.*; - -@Service -@Slf4j -@RequiredArgsConstructor -public class FlowcontrolIsSUToFollowUp implements JavaDelegate, DelegateContextVerifier { - - private final ContextService protoolsContext; - - @Override - public void execute(DelegateExecution execution) { - Boolean isToFollowUp = false; - - JsonNode contextRootNode = protoolsContext.getContextByProcessInstance(execution.getProcessInstanceId()); - checkContextOrThrow(log, execution.getProcessInstanceId(), contextRootNode); - - Long currentPartitionId = FlowableVariableUtils.getVariableOrThrow(execution, VARNAME_CURRENT_PARTITION_ID, Long.class); - // checkContextOrThrow(log,execution.getProcessInstanceId(), contextRootNode); - - Triple suItem = FlowableVariableUtils.getVariableOrThrow(execution, VARNAME_SU_CREATION_ITEM, Triple.class); - log.info("ProcessInstanceId={} - suItem={} begin", execution.getProcessInstanceId(), suItem); - - Instant openingInstant = suItem.getLeft(); - //TODO : à enlever ; mettre de la conf (période ou date fixe) sur la partition et récupérer la conf de la partition - Instant dateRelance = openingInstant.plusSeconds(3 * 60l); - - if (openingInstant != null && dateRelance.isBefore(Instant.now())) { - isToFollowUp = true; - } - execution.getParent().setVariableLocal(VARNAME_SU_IS_TO_FOLLOWUP, isToFollowUp); - - //Extract SU id and partition id as it will be used in following tasks - execution.getParent().setVariableLocal(VARNAME_REM_SURVEY_UNIT_IDENTIFIER, suItem.getRight()); - execution.getParent().setVariableLocal(VARNAME_CURRENT_PARTITION_ID, suItem.getMiddle()); - log.info("ProcessInstanceId={} - suItem={} - isToFollowUp={} end", execution.getProcessInstanceId(), suItem, isToFollowUp); - } -} diff --git a/src/main/java/fr/insee/protools/backend/logging/LoggingHelper.java b/src/main/java/fr/insee/protools/backend/logging/LoggingHelper.java new file mode 100644 index 00000000..013e1f55 --- /dev/null +++ b/src/main/java/fr/insee/protools/backend/logging/LoggingHelper.java @@ -0,0 +1,41 @@ +package fr.insee.protools.backend.logging; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.slf4j.Logger; +import org.slf4j.event.Level; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + + + +public class LoggingHelper { + + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.METHOD) + public @interface ExcludeFromJacocoGeneratedReport {} + + @ExcludeFromJacocoGeneratedReport + public static void logJson(String msg, Object dto, Logger logger, Level level) { + if (logger.isEnabledForLevel(level)) { + try { + String json = new ObjectMapper().writeValueAsString(dto); + String logLine = msg +" - " + json; + switch (level) { + case TRACE -> logger.trace(logLine); + case DEBUG -> logger.debug(logLine); + case INFO -> logger.info(logLine); + case WARN -> logger.warn(logLine); + case ERROR -> logger.error(logLine); + default -> logger.trace(logLine); + } + } catch (JsonProcessingException e) { + throw new RuntimeException("Failed to parse json"); + } + } + } + private LoggingHelper(){} +} diff --git a/src/main/java/fr/insee/protools/backend/repository/IUniteEnquetee.java b/src/main/java/fr/insee/protools/backend/repository/IUniteEnquetee.java new file mode 100644 index 00000000..136a6f1c --- /dev/null +++ b/src/main/java/fr/insee/protools/backend/repository/IUniteEnquetee.java @@ -0,0 +1,20 @@ +package fr.insee.protools.backend.repository; + +import com.fasterxml.jackson.databind.JsonNode; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +public interface IUniteEnquetee { + + @Transactional + void addManyUniteEnquetee(List listeUe); + + void addManyUniteEnquetee(List listeUe, String processInstanceId, String currentActivityId); + + void addManyUniteEnqueteeDeleteColonneClass(List listeUe); + + boolean isTerminated(String processInstanceId, String currentActivityId, long numberCommandes); + + long getCommandesByProcessInstanceIdAndCurrentActivityId(String processInstanceId, String currentActivityId); +} \ No newline at end of file diff --git a/src/main/java/fr/insee/protools/backend/repository/UniteEnqueteeImpl.java b/src/main/java/fr/insee/protools/backend/repository/UniteEnqueteeImpl.java new file mode 100644 index 00000000..5b358063 --- /dev/null +++ b/src/main/java/fr/insee/protools/backend/repository/UniteEnqueteeImpl.java @@ -0,0 +1,132 @@ +package fr.insee.protools.backend.repository; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.mongodb.BasicDBObject; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.convert.DefaultMongoTypeMapper; +import org.springframework.data.mongodb.core.convert.MappingMongoConverter; +import org.springframework.data.mongodb.core.mapping.MongoMappingContext; +import org.springframework.data.mongodb.core.query.Criteria; +import org.springframework.data.mongodb.core.query.Query; +import org.springframework.stereotype.Repository; + +import java.util.HashMap; +import java.util.List; +import java.util.UUID; + +import static com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_MISSING_CREATOR_PROPERTIES; +import static com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES; +import static org.codehaus.groovy.runtime.DefaultGroovyMethods.collect; +import static org.springframework.data.mongodb.core.query.Criteria.where; +import static org.springframework.data.mongodb.core.query.Query.query; + +@RequiredArgsConstructor +@Repository +@Slf4j +public class UniteEnqueteeImpl implements IUniteEnquetee { + + private final MongoTemplate mongoTemplate; + + @Setter + @Getter + private String processInstanceId; + @Setter + @Getter + private String currentActivityId; + + private static final ObjectMapper objectMapper = + new ObjectMapper() + .configure(FAIL_ON_UNKNOWN_PROPERTIES, false) + .configure(FAIL_ON_MISSING_CREATOR_PROPERTIES, true); + + + private BasicDBObject getUEUpdate(JsonNode test){ + String correlationID = UUID.randomUUID().toString(); + BasicDBObject dbObject = new BasicDBObject(); + HashMap keyValuePairs = null; + keyValuePairs = new HashMap<>(); + try { + keyValuePairs.put("payload", new ObjectMapper().writeValueAsString(test)); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + keyValuePairs.put("correlationID", correlationID); + keyValuePairs.put("inProgress", false); + keyValuePairs.put("done", false); + keyValuePairs.put("processInstanceID", getProcessInstanceId()); + keyValuePairs.put("currentActivityID", getCurrentActivityId()); + dbObject.putAll(keyValuePairs); + return dbObject; + } + + + @Override + public void addManyUniteEnquetee(List listeUe) { + List bo = listeUe.parallelStream() + .map(this::getUEUpdate) + .toList(); + mongoTemplate.insert(bo, "commandes"); + } + + @Override + public void addManyUniteEnqueteeDeleteColonneClass(List listeUe) { + List bo = listeUe.parallelStream() + .map(this::getUEUpdate) + .toList(); + //remove _class + MappingMongoConverter converter = + new MappingMongoConverter(mongoTemplate.getMongoDatabaseFactory(), new MongoMappingContext()); + converter.setTypeMapper(new DefaultMongoTypeMapper(null)); + MongoTemplate mongoTemplate2 = new MongoTemplate(mongoTemplate.getMongoDatabaseFactory(), converter); + mongoTemplate2.insert(bo, "commandes"); + } + + @Override + public void addManyUniteEnquetee(List listeUe, String processInstanceId, String currentActivityId) { + this.setProcessInstanceId(processInstanceId); + this.setCurrentActivityId(currentActivityId); +// List bo = listeUe.parallelStream() +// .map(this::getUEUpdate) +// .toList(); + //remove _class + MappingMongoConverter converter = + new MappingMongoConverter(mongoTemplate.getMongoDatabaseFactory(), new MongoMappingContext()); + converter.setTypeMapper(new DefaultMongoTypeMapper(null)); + MongoTemplate mongoTemplate2 = new MongoTemplate(mongoTemplate.getMongoDatabaseFactory(), converter); + mongoTemplate2.insert(listeUe, "commandes"); + } + + @Override + public boolean isTerminated(String processInstanceId, String currentActivityId, long numberCommandes) { + log.debug("UniteEnqueteeImpl.isTerminated."); + boolean result=false; + Query query = new Query(); + query.addCriteria(Criteria.where("processInstanceID").is(processInstanceId)); + query.addCriteria(Criteria.where("currentActivityID").is(currentActivityId)); + query.addCriteria(where("inProgress").is(true).and("done").is(true)); + List listeCommandes = mongoTemplate.find(query, String.class, "commandes"); + if(!listeCommandes.isEmpty() && listeCommandes.size()==numberCommandes){ + result=true; + } + return result; + } + + @Override + public long getCommandesByProcessInstanceIdAndCurrentActivityId(String processInstanceId, String currentActivityId) { + log.debug("getCommandesByProcessInstanceIdAndCurrentActivityId : " + processInstanceId + "|" + currentActivityId); + long result=0; + Query query = new Query(); + query.addCriteria(Criteria.where("processInstanceID").is(processInstanceId)); + query.addCriteria(Criteria.where("currentActivityID").is(currentActivityId)); + result = mongoTemplate.count(query, String.class, "commandes"); + return result; + } + +} \ No newline at end of file diff --git a/src/main/java/fr/insee/protools/backend/restclient/RestClientHelper.java b/src/main/java/fr/insee/protools/backend/restclient/RestClientHelper.java new file mode 100644 index 00000000..b7966cba --- /dev/null +++ b/src/main/java/fr/insee/protools/backend/restclient/RestClientHelper.java @@ -0,0 +1,218 @@ +package fr.insee.protools.backend.restclient; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import fr.insee.protools.backend.restclient.configuration.APIProperties; +import fr.insee.protools.backend.restclient.configuration.ApiConfigProperties; +import fr.insee.protools.backend.restclient.exception.ApiNotConfiguredBPMNError; +import fr.insee.protools.backend.restclient.exception.KeycloakTokenConfigBPMNError; +import fr.insee.protools.backend.restclient.exception.runtime.HttpClient4xxBPMNError; +import fr.insee.protools.backend.restclient.exception.runtime.HttpClient5xxBPMNError; +import fr.insee.protools.backend.restclient.keycloak.KeycloakService; +import io.netty.handler.logging.LogLevel; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpRequest; +import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; +import org.springframework.http.client.ClientHttpResponse; +import org.springframework.http.client.ReactorNettyClientRequestFactory; +import org.springframework.lang.Nullable; +import org.springframework.stereotype.Component; +import org.springframework.util.StreamUtils; +import org.springframework.web.client.RestClient; +import reactor.netty.http.client.HttpClient; +import reactor.netty.transport.logging.AdvancedByteBufFormat; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.*; + +/** + * Helper class for RestClient + */ +@Component +@Slf4j +public class RestClientHelper { + private final KeycloakService keycloakService; + private final ApiConfigProperties apiConfigProperties; + + private final EnumMap initializedClients = new EnumMap<>(ApiConfigProperties.KNOWN_API.class); + + public RestClientHelper(KeycloakService keycloakService, ApiConfigProperties apiConfigProperties) { + this.keycloakService = keycloakService; + this.apiConfigProperties = apiConfigProperties; + } + + //I cannot have a single builder and store it in a private variable because every call to .filter(...) append a new filter to the builder + //Still true for Restclient? + public RestClient.Builder getBuilder() { + return RestClient.builder() + .defaultStatusHandler(HttpStatusCode::isError, this::handleError) + .requestFactory(new ReactorNettyClientRequestFactory(HttpClient.create() + //Handles a proxy conf passed on system properties + .proxyWithSystemProperties() + //enable logging of request/responses + //configurable in properties as if it was this class logers + .wiretap(this.getClass().getCanonicalName(), LogLevel.DEBUG, AdvancedByteBufFormat.TEXTUAL))); + } + + private void handleError(HttpRequest httpRequest, ClientHttpResponse clientResponse) throws IOException { + String errorMsg = String.format("request=[%s %s] - statusCode=[%s]", + httpRequest.getMethod(),httpRequest.getURI(), clientResponse.getStatusCode()); + if (clientResponse.getStatusCode().equals(HttpStatusCode.valueOf(HttpStatus.UNAUTHORIZED.value()))) { + errorMsg = "HttpStatus.UNAUTHORIZED. WWW-Authenticate=[" + String.join("", clientResponse.getHeaders().get("WWW-Authenticate")) + "]"; + } + + String finalErrorMsg = errorMsg; + String errorMessage = StreamUtils.copyToString(clientResponse.getBody(), StandardCharsets.UTF_8); + if(errorMessage.isBlank()){ + errorMessage= "No error message provided by API"; + } + if (clientResponse.getStatusCode().is4xxClientError()) { + throw new HttpClient4xxBPMNError(finalErrorMsg + " - " + errorMessage, clientResponse.getStatusCode()); + } else { + throw new HttpClient5xxBPMNError(finalErrorMsg + " - " + errorMessage); + } + } + + + /** + * init a new RestClient proxy aware (default one ignore system proxy) + */ + public RestClient getRestClient() { + return getBuilder() + .build(); + } + + + /** + * Get a RestClient preconfigured for proxy and able to get the JWT token required for authentication + * + * @param api the client will connect to this api + * @return preconfigured RestClient for the api + */ + public RestClient getRestClient(ApiConfigProperties.KNOWN_API api) { + APIProperties apiProperties = apiConfigProperties.getAPIProperties(api); + if (apiProperties == null) { + throw new ApiNotConfiguredBPMNError(String.format("API %s is not configured in properties", api)); + } else if (Boolean.FALSE.equals(apiProperties.getEnabled())) { + throw new ApiNotConfiguredBPMNError(String.format("API %s is disabled in properties", api)); + } + return initializedClients.computeIfAbsent(api, + knownApi -> + getBuilder() + .baseUrl(apiProperties.getUrl()) + .requestInitializer(new RestClientKeycloakHeadersInitializer(keycloakService, apiProperties.getAuth())) + .build()); + } + + + public Map getTokenDetailsByAPI(){ + Map result = new HashMap<>(); + for (var api :ApiConfigProperties.KNOWN_API.values() ) { + try { + APIProperties apiProperties = apiConfigProperties.getAPIProperties(api); + if (apiProperties == null) { + throw new ApiNotConfiguredBPMNError(String.format("API %s is not configured in properties", api)); + } else if (Boolean.FALSE.equals(apiProperties.getEnabled())) { + throw new ApiNotConfiguredBPMNError(String.format("API %s is disabled in properties", api)); + } + var token = keycloakService.getToken(apiProperties.getAuth()); + if(token !=null && !token.isBlank()) { + String details = analyseToken(token); + result.put(api.name(),details); + + } + } catch (KeycloakTokenConfigBPMNError | ApiNotConfiguredBPMNError e) { + result.put(api.name(),e.getMessage()); + } + catch (Exception e){ + result.put(api.name(),"Internal error with token"); + } + } + return result; + } + + /** + * @return A json with the configuration of the APIs handled by protools + */ + public JsonNode getAPIConfigDetails(){ + ObjectMapper objectMapper = new ObjectMapper(); + ArrayNode rootNode = objectMapper.createArrayNode(); + for (var api :ApiConfigProperties.KNOWN_API.values() ) { + APIProperties apiProperties = apiConfigProperties.getAPIProperties(api); + ObjectNode apiNode = objectMapper.valueToTree(apiProperties); + apiNode.put("name",api.name()); + rootNode.add(apiNode); + } + return rootNode; + } + + //analyse a single token to retrieve roles + private static String analyseToken(String token) { + String result; + String[] chunks = token.split("\\."); + if(chunks.length<2){ + return "Token size is incorrect. It should contain at least one dot"; + } + Base64.Decoder decoder = Base64.getUrlDecoder(); + String payload = new String(decoder.decode(chunks[1])); + ObjectMapper objectMapper = new ObjectMapper(); + try { + JsonNode tokenPayloadNode = objectMapper.readTree(payload); + JsonNode roles = tokenPayloadNode.path("realm_access").path("roles"); + if(roles.isEmpty()){ + result="No Role found in token"; + } + else{ + result= roles.toString(); + } + } catch (JsonProcessingException e) { + result="Exception during json token parsing"; + } + return result; + } + + /** + * special version of NestedRuntimeException.contains accepting a list of types : + * Check whether the Ex exception contains an exception of the given list of types: + * either it is of the given class itself or it contains a nested cause of one of these types. + * @param ex : The exception + * @param exTypes : The searched types + * @return true if a matching exception type has been found + */ + @SuppressWarnings("java:S3776") + public static boolean containsCauseOfType(Exception ex, @Nullable List> exTypes) { + if (exTypes == null || exTypes.isEmpty()) { + return false; + } else { + if (exTypes.stream().anyMatch(exType -> exType.isInstance(ex))) { + return true; + } + + //Current exception is not of the configured types ; check parents + Throwable cause = ex.getCause(); + if (cause == ex) { + return false; + } else { + while (cause != null) { + Throwable finalCause = cause; //to be used in lambda + if (exTypes.stream().anyMatch(exType -> exType.isInstance(finalCause))) { + return true; + } + + if (cause.getCause() == cause) { + break; + } + + cause = cause.getCause(); + } + + return false; + } + } + } +} diff --git a/src/main/java/fr/insee/protools/backend/restclient/RestClientKeycloakHeadersInitializer.java b/src/main/java/fr/insee/protools/backend/restclient/RestClientKeycloakHeadersInitializer.java new file mode 100644 index 00000000..3389ecd4 --- /dev/null +++ b/src/main/java/fr/insee/protools/backend/restclient/RestClientKeycloakHeadersInitializer.java @@ -0,0 +1,36 @@ +package fr.insee.protools.backend.restclient; + + +import fr.insee.protools.backend.restclient.configuration.APIProperties; +import fr.insee.protools.backend.restclient.exception.KeycloakTokenConfigBPMNError; +import fr.insee.protools.backend.restclient.exception.KeycloakTokenConfigUncheckedBPMNError; +import fr.insee.protools.backend.restclient.keycloak.KeycloakService; +import org.springframework.http.MediaType; +import org.springframework.http.client.ClientHttpRequest; +import org.springframework.http.client.ClientHttpRequestInitializer; + +/** + * Class in charge of adding the correct bearer token for API calls + * It will retrieve a fresh token if needed using our KeycloakService + */ +class RestClientKeycloakHeadersInitializer implements ClientHttpRequestInitializer { + + final KeycloakService keycloakService; + //Configuration of the connexion to the auth server + private final APIProperties.AuthProperties authProperties; + + public RestClientKeycloakHeadersInitializer(KeycloakService keycloakService, APIProperties.AuthProperties authProperties) { + this.keycloakService = keycloakService; + this.authProperties = authProperties; + } + + @Override + public void initialize(ClientHttpRequest request) { + try { + request.getHeaders().setBearerAuth(keycloakService.getToken(authProperties)); + } catch (KeycloakTokenConfigBPMNError e) { + throw new KeycloakTokenConfigUncheckedBPMNError(e); + } + request.getHeaders().setContentType(MediaType.APPLICATION_JSON); + } +} diff --git a/src/main/java/fr/insee/protools/backend/webclient/configuration/APIProperties.java b/src/main/java/fr/insee/protools/backend/restclient/configuration/APIProperties.java similarity index 96% rename from src/main/java/fr/insee/protools/backend/webclient/configuration/APIProperties.java rename to src/main/java/fr/insee/protools/backend/restclient/configuration/APIProperties.java index 37734c3c..ae079920 100644 --- a/src/main/java/fr/insee/protools/backend/webclient/configuration/APIProperties.java +++ b/src/main/java/fr/insee/protools/backend/restclient/configuration/APIProperties.java @@ -1,4 +1,4 @@ -package fr.insee.protools.backend.webclient.configuration; +package fr.insee.protools.backend.restclient.configuration; import com.fasterxml.jackson.annotation.JsonIgnore; import jakarta.validation.Valid; diff --git a/src/main/java/fr/insee/protools/backend/webclient/configuration/ApiConfigProperties.java b/src/main/java/fr/insee/protools/backend/restclient/configuration/ApiConfigProperties.java similarity index 88% rename from src/main/java/fr/insee/protools/backend/webclient/configuration/ApiConfigProperties.java rename to src/main/java/fr/insee/protools/backend/restclient/configuration/ApiConfigProperties.java index b15867d3..4b8ce460 100644 --- a/src/main/java/fr/insee/protools/backend/webclient/configuration/ApiConfigProperties.java +++ b/src/main/java/fr/insee/protools/backend/restclient/configuration/ApiConfigProperties.java @@ -1,4 +1,4 @@ -package fr.insee.protools.backend.webclient.configuration; +package fr.insee.protools.backend.restclient.configuration; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; @@ -16,7 +16,8 @@ public enum KNOWN_API { KNOWN_API_SABIANE_QUESTIONNAIRE, KNOWN_API_REM, KNOWN_API_MESHUGGAH, - KNOWN_API_SUGOI + KNOWN_API_SUGOI, + KNOWN_API_TRAITERXXX } public APIProperties getAPIProperties(KNOWN_API api){ @@ -29,6 +30,7 @@ public APIProperties getAPIProperties(KNOWN_API api){ case KNOWN_API_REM -> remApiProperties(); case KNOWN_API_MESHUGGAH -> meshuggahApiProperties(); case KNOWN_API_SUGOI -> sugoiApiProperties(); + case KNOWN_API_TRAITERXXX -> traiterXXXApiProperties(); }; } @@ -81,4 +83,10 @@ public APIProperties sugoiApiProperties() { return new APIProperties(); } + @Bean("traiterXXXApiProperties") + @ConfigurationProperties("fr.insee.protools.api.traiterxxx") + public APIProperties traiterXXXApiProperties() { + return new APIProperties(); + } + } diff --git a/src/main/java/fr/insee/protools/backend/webclient/exception/ApiNotConfiguredBPMNError.java b/src/main/java/fr/insee/protools/backend/restclient/exception/ApiNotConfiguredBPMNError.java similarity index 85% rename from src/main/java/fr/insee/protools/backend/webclient/exception/ApiNotConfiguredBPMNError.java rename to src/main/java/fr/insee/protools/backend/restclient/exception/ApiNotConfiguredBPMNError.java index 0b5c99ea..c164c6c6 100644 --- a/src/main/java/fr/insee/protools/backend/webclient/exception/ApiNotConfiguredBPMNError.java +++ b/src/main/java/fr/insee/protools/backend/restclient/exception/ApiNotConfiguredBPMNError.java @@ -1,4 +1,4 @@ -package fr.insee.protools.backend.webclient.exception; +package fr.insee.protools.backend.restclient.exception; import fr.insee.protools.backend.exception.ProtoolsBpmnError; diff --git a/src/main/java/fr/insee/protools/backend/webclient/exception/KeycloakTokenConfigBPMNError.java b/src/main/java/fr/insee/protools/backend/restclient/exception/KeycloakTokenConfigBPMNError.java similarity index 85% rename from src/main/java/fr/insee/protools/backend/webclient/exception/KeycloakTokenConfigBPMNError.java rename to src/main/java/fr/insee/protools/backend/restclient/exception/KeycloakTokenConfigBPMNError.java index a4306881..596bfd77 100644 --- a/src/main/java/fr/insee/protools/backend/webclient/exception/KeycloakTokenConfigBPMNError.java +++ b/src/main/java/fr/insee/protools/backend/restclient/exception/KeycloakTokenConfigBPMNError.java @@ -1,4 +1,4 @@ -package fr.insee.protools.backend.webclient.exception; +package fr.insee.protools.backend.restclient.exception; import fr.insee.protools.backend.exception.ProtoolsBpmnError; diff --git a/src/main/java/fr/insee/protools/backend/webclient/exception/KeycloakTokenConfigUncheckedBPMNError.java b/src/main/java/fr/insee/protools/backend/restclient/exception/KeycloakTokenConfigUncheckedBPMNError.java similarity index 86% rename from src/main/java/fr/insee/protools/backend/webclient/exception/KeycloakTokenConfigUncheckedBPMNError.java rename to src/main/java/fr/insee/protools/backend/restclient/exception/KeycloakTokenConfigUncheckedBPMNError.java index 925739ee..6360006a 100644 --- a/src/main/java/fr/insee/protools/backend/webclient/exception/KeycloakTokenConfigUncheckedBPMNError.java +++ b/src/main/java/fr/insee/protools/backend/restclient/exception/KeycloakTokenConfigUncheckedBPMNError.java @@ -1,4 +1,4 @@ -package fr.insee.protools.backend.webclient.exception; +package fr.insee.protools.backend.restclient.exception; import fr.insee.protools.backend.exception.ProtoolsBpmnError; diff --git a/src/main/java/fr/insee/protools/backend/webclient/exception/runtime/WebClient4xxBPMNError.java b/src/main/java/fr/insee/protools/backend/restclient/exception/runtime/HttpClient4xxBPMNError.java similarity index 68% rename from src/main/java/fr/insee/protools/backend/webclient/exception/runtime/WebClient4xxBPMNError.java rename to src/main/java/fr/insee/protools/backend/restclient/exception/runtime/HttpClient4xxBPMNError.java index a8a2a908..2fa65498 100644 --- a/src/main/java/fr/insee/protools/backend/webclient/exception/runtime/WebClient4xxBPMNError.java +++ b/src/main/java/fr/insee/protools/backend/restclient/exception/runtime/HttpClient4xxBPMNError.java @@ -1,15 +1,15 @@ -package fr.insee.protools.backend.webclient.exception.runtime; +package fr.insee.protools.backend.restclient.exception.runtime; import fr.insee.protools.backend.exception.ProtoolsBpmnError; import org.springframework.http.HttpStatusCode; import static fr.insee.protools.backend.service.BPMNErrorCode.BPMNERROR_CODE_DEFAULT; -public class WebClient4xxBPMNError extends ProtoolsBpmnError { +public class HttpClient4xxBPMNError extends ProtoolsBpmnError { private final HttpStatusCode httpStatusCodeError; - public WebClient4xxBPMNError(String message, HttpStatusCode httpStatusCodeError) { + public HttpClient4xxBPMNError(String message, HttpStatusCode httpStatusCodeError) { super(BPMNERROR_CODE_DEFAULT, message); this.httpStatusCodeError = httpStatusCodeError; } diff --git a/src/main/java/fr/insee/protools/backend/webclient/exception/runtime/WebClientNullReturnBPMNError.java b/src/main/java/fr/insee/protools/backend/restclient/exception/runtime/HttpClient5xxBPMNError.java similarity index 51% rename from src/main/java/fr/insee/protools/backend/webclient/exception/runtime/WebClientNullReturnBPMNError.java rename to src/main/java/fr/insee/protools/backend/restclient/exception/runtime/HttpClient5xxBPMNError.java index 589f866f..4827862b 100644 --- a/src/main/java/fr/insee/protools/backend/webclient/exception/runtime/WebClientNullReturnBPMNError.java +++ b/src/main/java/fr/insee/protools/backend/restclient/exception/runtime/HttpClient5xxBPMNError.java @@ -1,12 +1,11 @@ -package fr.insee.protools.backend.webclient.exception.runtime; - +package fr.insee.protools.backend.restclient.exception.runtime; import fr.insee.protools.backend.exception.ProtoolsBpmnError; import static fr.insee.protools.backend.service.BPMNErrorCode.BPMNERROR_CODE_DEFAULT; -public class WebClientNullReturnBPMNError extends ProtoolsBpmnError { - public WebClientNullReturnBPMNError(String message) { +public class HttpClient5xxBPMNError extends ProtoolsBpmnError { + public HttpClient5xxBPMNError(String message) { super(BPMNERROR_CODE_DEFAULT, message); } } diff --git a/src/main/java/fr/insee/protools/backend/webclient/exception/runtime/WebClientNetworkExceptionBPMNError.java b/src/main/java/fr/insee/protools/backend/restclient/exception/runtime/HttpClientNetworkExceptionBPMNError.java similarity index 82% rename from src/main/java/fr/insee/protools/backend/webclient/exception/runtime/WebClientNetworkExceptionBPMNError.java rename to src/main/java/fr/insee/protools/backend/restclient/exception/runtime/HttpClientNetworkExceptionBPMNError.java index b2a8390d..209cf4e4 100644 --- a/src/main/java/fr/insee/protools/backend/webclient/exception/runtime/WebClientNetworkExceptionBPMNError.java +++ b/src/main/java/fr/insee/protools/backend/restclient/exception/runtime/HttpClientNetworkExceptionBPMNError.java @@ -1,4 +1,4 @@ -package fr.insee.protools.backend.webclient.exception.runtime; +package fr.insee.protools.backend.restclient.exception.runtime; import fr.insee.protools.backend.exception.ProtoolsBpmnError; import lombok.extern.slf4j.Slf4j; @@ -7,11 +7,11 @@ import static fr.insee.protools.backend.service.BPMNErrorCode.BPMNERROR_CODE_DEFAULT; @Slf4j -public class WebClientNetworkExceptionBPMNError extends ProtoolsBpmnError { +public class HttpClientNetworkExceptionBPMNError extends ProtoolsBpmnError { private final WebClientRequestException ex; - public WebClientNetworkExceptionBPMNError(WebClientRequestException ex) { + public HttpClientNetworkExceptionBPMNError(WebClientRequestException ex) { super(BPMNERROR_CODE_DEFAULT, computeMessage(ex)); this.ex = ex; log.error(this.getMessage()); diff --git a/src/main/java/fr/insee/protools/backend/restclient/exception/runtime/HttpClientNullReturnBPMNError.java b/src/main/java/fr/insee/protools/backend/restclient/exception/runtime/HttpClientNullReturnBPMNError.java new file mode 100644 index 00000000..314b3a8b --- /dev/null +++ b/src/main/java/fr/insee/protools/backend/restclient/exception/runtime/HttpClientNullReturnBPMNError.java @@ -0,0 +1,12 @@ +package fr.insee.protools.backend.restclient.exception.runtime; + + +import fr.insee.protools.backend.exception.ProtoolsBpmnError; + +import static fr.insee.protools.backend.service.BPMNErrorCode.BPMNERROR_CODE_DEFAULT; + +public class HttpClientNullReturnBPMNError extends ProtoolsBpmnError { + public HttpClientNullReturnBPMNError(String message) { + super(BPMNERROR_CODE_DEFAULT, message); + } +} diff --git a/src/main/java/fr/insee/protools/backend/webclient/exception/runtime/WebClientRequestExceptionBPMNError.java b/src/main/java/fr/insee/protools/backend/restclient/exception/runtime/HttpClientRequestExceptionBPMNError.java similarity index 81% rename from src/main/java/fr/insee/protools/backend/webclient/exception/runtime/WebClientRequestExceptionBPMNError.java rename to src/main/java/fr/insee/protools/backend/restclient/exception/runtime/HttpClientRequestExceptionBPMNError.java index a11c1aa0..2b38e2ce 100644 --- a/src/main/java/fr/insee/protools/backend/webclient/exception/runtime/WebClientRequestExceptionBPMNError.java +++ b/src/main/java/fr/insee/protools/backend/restclient/exception/runtime/HttpClientRequestExceptionBPMNError.java @@ -1,4 +1,4 @@ -package fr.insee.protools.backend.webclient.exception.runtime; +package fr.insee.protools.backend.restclient.exception.runtime; import fr.insee.protools.backend.exception.ProtoolsBpmnError; import lombok.extern.slf4j.Slf4j; @@ -7,11 +7,11 @@ import static fr.insee.protools.backend.service.BPMNErrorCode.BPMNERROR_CODE_DEFAULT; @Slf4j -public class WebClientRequestExceptionBPMNError extends ProtoolsBpmnError { +public class HttpClientRequestExceptionBPMNError extends ProtoolsBpmnError { private final WebClientRequestException ex; - public WebClientRequestExceptionBPMNError(WebClientRequestException ex) { + public HttpClientRequestExceptionBPMNError(WebClientRequestException ex) { super(BPMNERROR_CODE_DEFAULT, computeMessage(ex)); this.ex = ex; log.error(this.getMessage()); diff --git a/src/main/java/fr/insee/protools/backend/webclient/KeycloakResponse.java b/src/main/java/fr/insee/protools/backend/restclient/keycloak/KeycloakResponse.java similarity index 76% rename from src/main/java/fr/insee/protools/backend/webclient/KeycloakResponse.java rename to src/main/java/fr/insee/protools/backend/restclient/keycloak/KeycloakResponse.java index 615e675d..4563ce38 100644 --- a/src/main/java/fr/insee/protools/backend/webclient/KeycloakResponse.java +++ b/src/main/java/fr/insee/protools/backend/restclient/keycloak/KeycloakResponse.java @@ -1,19 +1,16 @@ -package fr.insee.protools.backend.webclient; +package fr.insee.protools.backend.restclient.keycloak; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; @Data -class KeycloakResponse { +public class KeycloakResponse { @JsonProperty("access_token") private String accesToken; @JsonProperty("expires_in") private Integer expiresIn; - public KeycloakResponse() { - } - public KeycloakResponse(String accesToken, Integer expiresIn) { this.accesToken = accesToken; this.expiresIn = expiresIn; diff --git a/src/main/java/fr/insee/protools/backend/webclient/KeycloakService.java b/src/main/java/fr/insee/protools/backend/restclient/keycloak/KeycloakService.java similarity index 72% rename from src/main/java/fr/insee/protools/backend/webclient/KeycloakService.java rename to src/main/java/fr/insee/protools/backend/restclient/keycloak/KeycloakService.java index 02d2f31b..47a2a125 100644 --- a/src/main/java/fr/insee/protools/backend/webclient/KeycloakService.java +++ b/src/main/java/fr/insee/protools/backend/restclient/keycloak/KeycloakService.java @@ -1,7 +1,7 @@ -package fr.insee.protools.backend.webclient; +package fr.insee.protools.backend.restclient.keycloak; -import fr.insee.protools.backend.webclient.configuration.APIProperties; -import fr.insee.protools.backend.webclient.exception.KeycloakTokenConfigBPMNError; +import fr.insee.protools.backend.restclient.configuration.APIProperties; +import fr.insee.protools.backend.restclient.exception.KeycloakTokenConfigBPMNError; import io.netty.handler.logging.LogLevel; import jakarta.annotation.PostConstruct; import lombok.Data; @@ -10,12 +10,11 @@ import org.springframework.core.env.Environment; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; -import org.springframework.http.client.reactive.ReactorClientHttpConnector; +import org.springframework.http.client.ReactorNettyClientRequestFactory; import org.springframework.stereotype.Service; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; -import org.springframework.web.reactive.function.BodyInserters; -import org.springframework.web.reactive.function.client.WebClient; +import org.springframework.web.client.RestClient; import reactor.netty.http.client.HttpClient; import reactor.netty.transport.logging.AdvancedByteBufFormat; @@ -34,7 +33,7 @@ public class KeycloakService { private final Environment environment; - private WebClient webClient; + private RestClient restClient; public static final int TOKEN_REFRESH_LIMIT_MILLISECONDS = 30*1000; //We will keep one token by auth server / realm / clientId @@ -54,11 +53,11 @@ public String getToken(APIProperties.AuthProperties authProperties) throws Keycl logToken(token); //We refresh any expired token or that will expire within TOKEN_REFRESH_LIMIT_MILISECONDS - if(token==null || Instant.now().toEpochMilli() >= (token.endValidityTimeMillis- TOKEN_REFRESH_LIMIT_MILLISECONDS)){ + if(token==null || Instant.now().toEpochMilli() >= (token.endValidityTimeMillis()- TOKEN_REFRESH_LIMIT_MILLISECONDS)){ log.trace("Refresh the token"); refreshToken(authProperties); } - return tokenByAuthRealm.get(authProperties).value; + return tokenByAuthRealm.get(authProperties).value(); } private void refreshToken(APIProperties.AuthProperties authProperties) throws KeycloakTokenConfigBPMNError { @@ -68,6 +67,7 @@ private void refreshToken(APIProperties.AuthProperties authProperties) throws Ke try { uri = new URI(uri).normalize().toString(); } catch (URISyntaxException e) { + //Will probably never be reached if URL is tests before throw new KeycloakTokenConfigBPMNError(String.format("Auth is not correctly configured for [%s]",authProperties)); } MultiValueMap requestBody = new LinkedMultiValueMap<>(); @@ -77,15 +77,12 @@ private void refreshToken(APIProperties.AuthProperties authProperties) throws Ke long endValidityTimeMillis = Instant.now().toEpochMilli(); - KeycloakResponse response = webClient.post() + KeycloakResponse response = restClient.post() .uri(uri) .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE) - .body(BodyInserters.fromValue(requestBody)) + .body(requestBody) .retrieve() - //.onStatus(httpStatus -> HttpStatus.NOT_FOUND.equals(httpStatus), - // clientResponse -> Mono.empty()) - .bodyToMono(KeycloakResponse.class) - .block(); + .toEntity(KeycloakResponse.class).getBody(); //TODO: timeout configurable ; handling des exceptions (ex: block) ; codes erreur http //TODO : voir aussi cette histoire de timeout if(response!=null) { @@ -98,16 +95,14 @@ private void refreshToken(APIProperties.AuthProperties authProperties) throws Ke } @PostConstruct - void initialize() { - webClient = WebClient.builder() - .clientConnector( - new ReactorClientHttpConnector( - HttpClient.create() - //Handles a proxy conf passed on system properties - .proxyWithSystemProperties() - //enable logging of request/responses - //configurable in properties as if it was this class logers - .wiretap(this.getClass().getCanonicalName(), LogLevel.DEBUG, AdvancedByteBufFormat.TEXTUAL))) + public void initialize() { + restClient = RestClient.builder() + .requestFactory(new ReactorNettyClientRequestFactory(HttpClient.create() + //Handles a proxy conf passed on system properties + .proxyWithSystemProperties() + //enable logging of request/responses + //configurable in properties as if it was this class logers + .wiretap(this.getClass().getCanonicalName(), LogLevel.DEBUG, AdvancedByteBufFormat.TEXTUAL))) .build(); } @@ -123,12 +118,13 @@ boolean isValidURL(String url) { } } +// @ExcludeFromJacocoGeneratedReport private void logToken(Token token){ if(log.isTraceEnabled()){ var currentDt = Instant.now().toEpochMilli(); if(token!=null) { log.trace("token.endValidityTimeMillis = {} - currentTimeMillis={} - diff={}", - token.endValidityTimeMillis,currentDt, token.endValidityTimeMillis-currentDt); + token.endValidityTimeMillis(),currentDt, token.endValidityTimeMillis()-currentDt); } else log.trace("token=null - currentTimeMillis={}",currentDt); diff --git a/src/main/java/fr/insee/protools/backend/restclient/keycloak/Token.java b/src/main/java/fr/insee/protools/backend/restclient/keycloak/Token.java new file mode 100644 index 00000000..dce403c0 --- /dev/null +++ b/src/main/java/fr/insee/protools/backend/restclient/keycloak/Token.java @@ -0,0 +1,4 @@ +package fr.insee.protools.backend.restclient.keycloak; + +record Token(String value, long endValidityTimeMillis) { +} diff --git a/src/main/java/fr/insee/protools/backend/restclient/pagination/PageResponse.java b/src/main/java/fr/insee/protools/backend/restclient/pagination/PageResponse.java new file mode 100644 index 00000000..a150c125 --- /dev/null +++ b/src/main/java/fr/insee/protools/backend/restclient/pagination/PageResponse.java @@ -0,0 +1,35 @@ +package fr.insee.protools.backend.restclient.pagination; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import lombok.*; + +import java.util.ArrayList; +import java.util.List; + +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@ToString +@JsonIgnoreProperties(ignoreUnknown=true) +public class PageResponse { + @Builder.Default + private List content = new ArrayList<>(); + @Builder.Default + private Integer currentPage=0; + @Builder.Default + private Integer pageSize=5000; + @Builder.Default + private Long totalElements=0L; + @Builder.Default + private Integer pageCount=0; + + public Boolean isLastPage(){ + if(currentPage==null || pageCount==null){ + return true; + } + else return ((currentPage+1)>=pageCount); + } + +} + diff --git a/src/main/java/fr/insee/protools/backend/service/DelegateContextVerifier.java b/src/main/java/fr/insee/protools/backend/service/DelegateContextVerifier.java index 02a379c9..6b134bb7 100644 --- a/src/main/java/fr/insee/protools/backend/service/DelegateContextVerifier.java +++ b/src/main/java/fr/insee/protools/backend/service/DelegateContextVerifier.java @@ -1,10 +1,10 @@ package fr.insee.protools.backend.service; -import com.fasterxml.jackson.databind.JsonNode; +import fr.insee.protools.backend.dto.ContexteProcessus; +import fr.insee.protools.backend.service.context.exception.BadContexMissingBPMNError; import fr.insee.protools.backend.service.context.exception.BadContextIncorrectBPMNError; import org.slf4j.Logger; -import java.util.HashSet; import java.util.Set; /** @@ -13,7 +13,9 @@ */ public interface DelegateContextVerifier { - default Set getContextErrors(JsonNode contextRootNode) {return Set.of();} + default Set getContextErrors(ContexteProcessus context) { + return Set.of(); + } static String computeMissingMessage(String missingElement, Class classUsingThisElement){ return String.format("Class=%s : Missing Context element name=%s ", classUsingThisElement.getSimpleName(),missingElement); @@ -29,24 +31,12 @@ static String computeIncorrectEnumMessage(String incorrectElement,String value, , value ,enumValues); } - static Set computeMissingChildrenMessages(Set requiredChildren, JsonNode parentNode, Class classUsingThisElement){ - if(parentNode == null){ - return new HashSet<>(); - } - Set missingNodes = new HashSet<>(); - for (String child: requiredChildren ) { - if(parentNode.get(child) == null){ - missingNodes.add(computeMissingMessage(child,classUsingThisElement)); - } - } - return missingNodes; - } - default void checkContextOrThrow(Logger log,String processInstanceId, JsonNode contextRootNode) { - if(contextRootNode==null) - throw new BadContextIncorrectBPMNError(String.format("ProcessInstanceId=%s - context is missing", processInstanceId)); + default void checkContextOrThrow(Logger log,String processInstanceId, ContexteProcessus context) { + if(context==null) + throw new BadContexMissingBPMNError(String.format("ProcessInstanceId=%s - context is missing", processInstanceId)); - var errors = getContextErrors(contextRootNode); + var errors = getContextErrors(context); if(!errors.isEmpty()){ for (var msg: errors) { log.error(msg); diff --git a/src/main/java/fr/insee/protools/backend/service/FlowableVariableNameConstants.java b/src/main/java/fr/insee/protools/backend/service/FlowableVariableNameConstants.java index 0b728d5c..a1c49076 100644 --- a/src/main/java/fr/insee/protools/backend/service/FlowableVariableNameConstants.java +++ b/src/main/java/fr/insee/protools/backend/service/FlowableVariableNameConstants.java @@ -8,31 +8,37 @@ public class FlowableVariableNameConstants { //TODO : renommer toutes ces variables pour remplacer les - par des _ (comme ca ca sera utilisable dans les resolvers) //Protools context public static final String VARNAME_CONTEXT="context"; - public static final String VARNAME_CONTEXT_PARTITION_ID_LIST="contexte_partition_id_list"; - public static final String VARNAME_CONTEXT_PARTITION_VARIABLES_BY_ID="contexte_partition_variables_by_partitionid"; //To treat partitions one by one (Long) public static final String VARNAME_CURRENT_PARTITION_ID="current_partition_id"; - //to pass a list of REM survey ids (List) - public static final String VARNAME_REM_SU_ID_LIST="rem_survey_unit_id_list"; - //to pass a single REM survey unit's ID (Long) - public static final String VARNAME_REM_SURVEY_UNIT_IDENTIFIER ="rem_survey_unit_id"; - //to pass a REM survey unit content (JsonNode) - public static final String VARNAME_REM_SURVEY_UNIT ="rem_survey_unit"; + //Sugoi ID/PWD - public static final String VARNAME_DIRECTORYACCESS_ID_CONTACT ="directory_access_id_contact"; public static final String VARNAME_DIRECTORYACCESS_PWD_CONTACT ="directory_access_pwd_contact"; - //ERA response - public static final String VARNAME_ERA_RESPONSE="era_response_list"; - public static final String VARNAME_ERA_QUERY_START_DATE="era_query_start_date"; - public static final String VARNAME_ERA_QUERY_END_DATE="era_query_end_date"; - //Platine Contact details - public static final String VARNAME_PLATINE_CONTACT="platine_contact"; - //Indicates whether a questioning should be follow up or not - public static final String VARNAME_SU_IS_TO_FOLLOWUP="survey_unit_is_to_follow_up"; - //List with for each SU the Instant when the opening communication has been sent - //each row is Tuple - public static final String VARNAME_SU_CREATION_ITEM="su_creation_date_item"; + public static final String VARNAME_DIRECTORYACCESS_PWD_FOR_INTERRO_ID_MAP ="directory_access_pwd_contact_by_interroration_id"; + + //For communication + public static final String VARNAME_CURRENT_COMMUNICATION_ID="current_communication_id"; + public static final String VARNAME_COMMUNICATION_REQUEST_ID_FOR_INTERRO_ID_MAP="communication_request_id_by_interrogation_id"; + //List of the UUIDs of the communications that have already been scheduled + public static final String VARNAME_ALREADY_SCHEDULED_COMMUNICATION_ID_SET = "communication_already_scheduled_id_set"; + //List of the UUIDs of the communcation that are in error (echeance was too far past) + public static final String VARNAME_COMMUNICATION_ERROR_ID_SET = "communication_in_error_id_set"; + + + //To pass a list of REM interrogations content (JsonNode) + public static final String VARNAME_REM_INTERRO_LIST ="rem_interrogation_list"; + //REM PAGEABLE + public static final String VARNAME_INTERRO_LIST_PAGEABLE_IS_LAST_PAGE ="interro_list_page_is_last"; + public static final String VARNAME_INTERRO_LIST_PAGEABLE_CURRENT_PAGE ="interro_list_page_current"; + + + //Contacts + public static final String VARNAME_PLATINE_CONTACT_LIST ="platine_contact_list"; + + //Remise en collecte + public static final String VARNAME_INTERRO_REMISE_EN_COLLECTE_LIST ="interro_remise_en_collecte_list"; + + private FlowableVariableNameConstants(){} } diff --git a/src/main/java/fr/insee/protools/backend/service/common/platine_sabiane/QuestionnaireHelper.java b/src/main/java/fr/insee/protools/backend/service/common/platine_sabiane/QuestionnaireHelper.java deleted file mode 100644 index 26f7e1ea..00000000 --- a/src/main/java/fr/insee/protools/backend/service/common/platine_sabiane/QuestionnaireHelper.java +++ /dev/null @@ -1,332 +0,0 @@ -package fr.insee.protools.backend.service.common.platine_sabiane; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ArrayNode; -import fr.insee.protools.backend.service.DelegateContextVerifier; -import fr.insee.protools.backend.dto.platine_sabiane_questionnaire.campaign.CampaignDto; -import fr.insee.protools.backend.dto.platine_sabiane_questionnaire.campaign.MetadataValue; -import fr.insee.protools.backend.dto.platine_sabiane_questionnaire.surveyunit.SurveyUnitResponseDto; -import fr.insee.protools.backend.service.context.ContextService; -import fr.insee.protools.backend.service.exception.JsonParsingBPMNError; -import fr.insee.protools.backend.service.nomenclature.NomenclatureService; -import fr.insee.protools.backend.service.platine.utils.PlatineHelper; -import fr.insee.protools.backend.service.questionnaire_model.QuestionnaireModelService; -import fr.insee.protools.backend.dto.rem.REMSurveyUnitDto; -import fr.insee.protools.backend.service.sabiane.SabianeIdHelper; -import fr.insee.protools.backend.service.utils.FlowableVariableUtils; -import lombok.extern.slf4j.Slf4j; -import org.flowable.engine.delegate.DelegateExecution; - -import java.util.HashSet; -import java.util.Iterator; -import java.util.Set; - -import static com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_MISSING_CREATOR_PROPERTIES; -import static com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES; -import static fr.insee.protools.backend.service.FlowableVariableNameConstants.VARNAME_CURRENT_PARTITION_ID; -import static fr.insee.protools.backend.service.FlowableVariableNameConstants.VARNAME_REM_SURVEY_UNIT; -import static fr.insee.protools.backend.service.context.ContextConstants.*; -import static fr.insee.protools.backend.service.utils.ContextUtils.getCurrentPartitionNode; - -@Slf4j -public class QuestionnaireHelper { - - private static final ObjectMapper objectMapper = - new ObjectMapper() - .configure(FAIL_ON_UNKNOWN_PROPERTIES, false) - .configure(FAIL_ON_MISSING_CREATOR_PROPERTIES, true); - - private QuestionnaireHelper() { - } - - public static void createQuestionnaire(JsonNode contextRootNode, - QuestionnairePlatineSabianeService questionnairePlatineSabianeService, - NomenclatureService nomenclatureService, - QuestionnaireModelService questionnaireModelService, - String processInstanceId, - MetadataValue metadataDto - ) { - //Get the list of nomenclatures defined in Protools Context - //Create them if needed - var nomenclatureIterator = contextRootNode.path(CTX_NOMENCLATURES).elements(); - if (!nomenclatureIterator.hasNext()) { - log.info("ProcessInstanceId={} - does not declare any nomenclature", processInstanceId); - } else { - initRequiredNomenclatures(questionnairePlatineSabianeService, nomenclatureService, processInstanceId, nomenclatureIterator); - } - - //Get the list of Questionnaire Models defined in Protools Context - Set questionnaireModelIds = initQuestionnaireModels(questionnairePlatineSabianeService, questionnaireModelService, processInstanceId, contextRootNode); - CampaignDto campaignDto = CampaignDto.builder() - .id(contextRootNode.path(CTX_CAMPAGNE_ID).textValue()) - .label(contextRootNode.path(CTX_CAMPAGNE_LABEL).textValue()) - .metadata(metadataDto) - .questionnaireIds(questionnaireModelIds) - .build(); - questionnairePlatineSabianeService.postCampaign(campaignDto); - } - - static void initRequiredNomenclatures(QuestionnairePlatineSabianeService questionnairePlatineSabianeService, NomenclatureService nomenclatureService, String processInstanceId, Iterator nomenclatureIterator) { - //Get the list of existing nomenclatures on platine - Set existingNomenclatures = questionnairePlatineSabianeService.getNomenclaturesId(); - - //Create the nomenclatures not existing yet on platine - while (nomenclatureIterator.hasNext()) { - var node = nomenclatureIterator.next(); - String nomenclatureId = node.get(CTX_NOMENCLATURE_ID).asText(); - String nomenclatureCheminRepertoire = node.path(CTX_NOMENCLATURE_CHEMIN_REPERTOIRE).asText(); - String nomenclatureLabel = node.get(CTX_NOMENCLATURE_LABEL).asText(); - //check if platine know this nomenclature - if (existingNomenclatures.contains(nomenclatureId)) { - log.info("ProcessInstanceId={} - nomenclature ID={} already exists in collect platform ", processInstanceId, nomenclatureId); - } else { - //Retrieve the nomenclature from remote source - String nomenclatureValueStr = nomenclatureService.getNomenclatureContent(nomenclatureId, nomenclatureCheminRepertoire); - JsonNode nomenclatureValue; - try { - nomenclatureValue = objectMapper.readTree(nomenclatureValueStr); - } catch (JsonProcessingException e) { - throw new JsonParsingBPMNError("Error while parsing the json retrieved for nomenclatureId=" + nomenclatureId, e); - } - - //Write this nomenclature to platine/sabiane - questionnairePlatineSabianeService.postNomenclature(nomenclatureId, nomenclatureLabel, nomenclatureValue); - //TODO : handles the exceptions here? - log.info("ProcessInstanceId={} - nomenclature ID={} created in remote collect platform", processInstanceId, nomenclatureId); - } - } - } - - /** - * For every questionnaireModel defined in context : check if it exists in platine/sabiane questionnaire. - * If it does not exists : retrieve it from questionnaireModelService and create it in platine/sabiane - * - * @param questionnairePlatineSabianeService : the service object used to access Sabiane Or Platine - * @param questionnaireModelService : The service object used to retrieve questionnaire models (ex: from gitlab) - * @param processInstanceId : used in logs - * @param contextRootNode : the protools context - * @return the set of questionnaireModel ids - */ - public static Set initQuestionnaireModels(QuestionnairePlatineSabianeService questionnairePlatineSabianeService, QuestionnaireModelService questionnaireModelService, String processInstanceId, JsonNode contextRootNode) { - var questionnaireModelIterator = contextRootNode.path(CTX_QUESTIONNAIRE_MODELS).elements(); - Set questionnaireModelIds = new HashSet<>(); //Used to build the CampaignDto later - while (questionnaireModelIterator.hasNext()) { - var node = questionnaireModelIterator.next(); - String questionnaireId = node.get(CTX_QUESTIONNAIRE_MODEL_ID).asText(); - String questionnaireCheminRepertoire = node.get(CTX_QUESTIONNAIRE_MODEL_CHEMIN_REPERTOIRE).asText(); - String questionnaireLabel = node.get(CTX_QUESTIONNAIRE_MODEL_LABEL).asText(); - questionnaireModelIds.add(questionnaireId); - - //check if platine/sabiane know this questionnaire - if (questionnairePlatineSabianeService.questionnaireModelExists(questionnaireId)) { - log.info("getProcessInstanceId={} - questionnaireId ID={} already exists", processInstanceId, questionnaireId); - } else { - //Get the questionnaire model from remote source - String questionnaireValueStr = questionnaireModelService.getQuestionnaireModel(questionnaireId, questionnaireCheminRepertoire); - - JsonNode questionnaireValue; - try { - questionnaireValue = objectMapper.readTree(questionnaireValueStr); - } catch (JsonProcessingException e) { - throw new JsonParsingBPMNError("Error while parsing the json retrieved for Model questionnaireId=" + questionnaireId, e); - } - //get the list of nomenclatures needed by this Questionnaire Model - JsonNode nomenclaturesArrayNode = node.get(CTX_QUESTIONNAIRE_MODEL_REQUIRED_NOMENCLATURES); - Set requiredNomenclatures = new HashSet<>(nomenclaturesArrayNode.size()); - nomenclaturesArrayNode.forEach(jsonNode -> requiredNomenclatures.add(jsonNode.asText())); - - //TODO : should we check context coherence here and verify that we dont have any unknown nomenclature? - //Write this questionnaire model to platine/sabiane - questionnairePlatineSabianeService.postQuestionnaireModel(questionnaireId, questionnaireLabel, questionnaireValue, requiredNomenclatures); - //TODO : handles the exceptions here? - } - } - return questionnaireModelIds; - } - - @SuppressWarnings("java:S3776") //disable the warning about cognitive complexity as it is long but simple - public static Set getCreateCtxContextErrors(JsonNode contextRootNode) { - if (contextRootNode == null) { - return Set.of(String.format("Class=%s : Context is missing ", QuestionnaireHelper.class.getSimpleName())); - } - - Set requiredNodes = - Set.of(CTX_CAMPAGNE_ID, CTX_CAMPAGNE_LABEL, CTX_NOMENCLATURES, CTX_QUESTIONNAIRE_MODELS, CTX_METADONNEES); - Set missingNodes = new HashSet<>(DelegateContextVerifier.computeMissingChildrenMessages(requiredNodes, contextRootNode, QuestionnaireHelper.class)); - - if (contextRootNode.get(CTX_NOMENCLATURES) != null) { - //Check on nomenclatures - var nomenclatureIterator = contextRootNode.path(CTX_NOMENCLATURES).elements(); - int i = 0; - while (nomenclatureIterator.hasNext()) { - i++; - var nomenclatureNode = nomenclatureIterator.next(); - if (nomenclatureNode.get(CTX_NOMENCLATURE_ID) == null || nomenclatureNode.get(CTX_NOMENCLATURE_ID).asText().isEmpty()) { - missingNodes.add(missingCTXMessage(CTX_NOMENCLATURES, i, CTX_NOMENCLATURE_ID)); - } - if (nomenclatureNode.get(CTX_NOMENCLATURE_LABEL) == null || nomenclatureNode.get(CTX_NOMENCLATURE_LABEL).asText().isEmpty()) { - missingNodes.add(missingCTXMessage(CTX_NOMENCLATURES, i, CTX_NOMENCLATURE_LABEL)); - } - if (nomenclatureNode.get(CTX_NOMENCLATURE_CHEMIN_REPERTOIRE) == null || nomenclatureNode.get(CTX_NOMENCLATURE_CHEMIN_REPERTOIRE).asText().isEmpty()) { - missingNodes.add(missingCTXMessage(CTX_NOMENCLATURES, i, CTX_NOMENCLATURE_CHEMIN_REPERTOIRE)); - } - } - - } - - if (contextRootNode.get(CTX_QUESTIONNAIRE_MODELS) != null) { - //Check on questionnaire models - var questionnaireModelsIterator = contextRootNode.get(CTX_QUESTIONNAIRE_MODELS).elements(); - int i = 0; - while (questionnaireModelsIterator.hasNext()) { - i++; - var nomenclatureNode = questionnaireModelsIterator.next(); - if (nomenclatureNode.get(CTX_QUESTIONNAIRE_MODEL_ID) == null || nomenclatureNode.get(CTX_QUESTIONNAIRE_MODEL_ID).asText().isEmpty()) { - missingNodes.add(missingCTXMessage(CTX_QUESTIONNAIRE_MODELS, i, CTX_QUESTIONNAIRE_MODEL_ID)); - } - if (nomenclatureNode.get(CTX_QUESTIONNAIRE_MODEL_LABEL) == null || nomenclatureNode.get(CTX_QUESTIONNAIRE_MODEL_LABEL).asText().isEmpty()) { - missingNodes.add(missingCTXMessage(CTX_QUESTIONNAIRE_MODELS, i, CTX_QUESTIONNAIRE_MODEL_LABEL)); - } - if (nomenclatureNode.get(CTX_QUESTIONNAIRE_MODEL_CHEMIN_REPERTOIRE) == null || nomenclatureNode.get(CTX_QUESTIONNAIRE_MODEL_CHEMIN_REPERTOIRE).asText().isEmpty()) { - missingNodes.add(missingCTXMessage(CTX_QUESTIONNAIRE_MODELS, i, CTX_QUESTIONNAIRE_MODEL_CHEMIN_REPERTOIRE)); - } - } - } - return missingNodes; - } - - private static String missingCTXMessage(String parent, int index, String child) { - return DelegateContextVerifier.computeMissingMessage(String.format("%s[%s].%s", parent, index, child), QuestionnaireHelper.class); - } - - private static SurveyUnitResponseDto computeDtoPlatine(JsonNode remSUNode, JsonNode currentPartitionNode) { - REMSurveyUnitDto remSurveyUnitDto = PlatineHelper.parseRemSUNode(objectMapper, VARNAME_REM_SURVEY_UNIT, remSUNode); - String id = remSurveyUnitDto.getRepositoryId().toString(); - String nameKey = "name"; - String valueKey = "value"; - - ArrayNode personalizationNode = objectMapper.createArrayNode(); - personalizationNode.add(objectMapper.createObjectNode() - .put(nameKey, "whoAnswers1") - .put(valueKey, currentPartitionNode.path(CTX_PARTITION_QUIREPOND1).asText())); - personalizationNode.add(objectMapper.createObjectNode() - .put(nameKey, "whoAnswers2") - .put(valueKey, currentPartitionNode.path(CTX_PARTITION_QUIREPOND2).asText())); - personalizationNode.add(objectMapper.createObjectNode() - .put(nameKey, "whoAnswers3") - .put(valueKey, currentPartitionNode.path(CTX_PARTITION_QUIREPOND3).asText())); - - return SurveyUnitResponseDto.builder() - .id(id) //Platine - .questionnaireId(currentPartitionNode.path(CTX_PARTITION_QUESTIONNAIRE_MODEL).asText()) - .data(remSurveyUnitDto.getExternals()) - .personalization(personalizationNode) - .comment(objectMapper.createObjectNode()) - //.stateData(objectMapper.createObjectNode()) - .build(); - } - - private static SurveyUnitResponseDto computeDtoSabiane(JsonNode remSUNode, JsonNode currentPartitionNode) { - REMSurveyUnitDto remSurveyUnitDto = PlatineHelper.parseRemSUNode(objectMapper, VARNAME_REM_SURVEY_UNIT, remSUNode); - String id = SabianeIdHelper.computeSabianeID(currentPartitionNode.path(CTX_PARTITION_ID).asText(),remSurveyUnitDto.getRepositoryId().toString()); - - return SurveyUnitResponseDto.builder() - .id(id)//Sabiane uses identified of the form IdPartition P idREM - .questionnaireId(currentPartitionNode.path(CTX_PARTITION_QUESTIONNAIRE_MODEL).asText()) - .data(remSurveyUnitDto.getExternals()) - .personalization(objectMapper.createObjectNode())//No personalization for sabiane - .comment(objectMapper.createObjectNode()) - //.stateData(objectMapper.createObjectNode()) - .build(); - } - - /** - * Create a SU in Platine Questionnaire - * @param execution - * @param protoolsContext - * @param service - */ - public static void createSUTaskPlatine(DelegateExecution execution, ContextService protoolsContext, QuestionnairePlatineSabianeService service) { - createSUTaskPlatineSabiane(execution, protoolsContext, service, false); - } - - /** - * Create a SU in Sabiane Questionnaire - * @param execution - * @param protoolsContext - * @param service - */ - public static void createSUTaskSabiane(DelegateExecution execution, ContextService protoolsContext, QuestionnairePlatineSabianeService service) { - createSUTaskPlatineSabiane(execution, protoolsContext, service, true); - } - - private static void createSUTaskPlatineSabiane(DelegateExecution execution, ContextService protoolsContext, QuestionnairePlatineSabianeService service, boolean modeSabiane) { - JsonNode contextRootNode = protoolsContext.getContextByProcessInstance(execution.getProcessInstanceId()); - - Long currentPartitionId = FlowableVariableUtils.getVariableOrThrow(execution, VARNAME_CURRENT_PARTITION_ID, Long.class); - JsonNode remSUNode = FlowableVariableUtils.getVariableOrThrow(execution, VARNAME_REM_SURVEY_UNIT, JsonNode.class); - JsonNode currentPartitionNode = getCurrentPartitionNode(contextRootNode, currentPartitionId); - - //Create the DTO object - SurveyUnitResponseDto dto = - (modeSabiane) - ? - QuestionnaireHelper.computeDtoSabiane(remSUNode, currentPartitionNode) - : - QuestionnaireHelper.computeDtoPlatine(remSUNode, currentPartitionNode); - - log.info("ProcessInstanceId={} - mode={} - currentPartitionId={} - remSU.id={}", - execution.getProcessInstanceId(), modeSabiane ? "sabiane" : "platine", currentPartitionId, dto.getId()); - - //Call service - service.postSurveyUnit(dto, contextRootNode.path(CTX_CAMPAGNE_ID).asText()); - - log.debug("ProcessInstanceId={} end", execution.getProcessInstanceId()); - } - - /** - * Get the context errors for an SU creation in Platine - * @param contextRootNode : the context to verify - * @return a Set with the errors - */ - public static Set getCreateSUContextErrorsPlatine(JsonNode contextRootNode){ - Set requiredPartition = - Set.of(CTX_PARTITION_ID,CTX_PARTITION_QUESTIONNAIRE_MODEL,CTX_PARTITION_QUIREPOND1,CTX_PARTITION_QUIREPOND2,CTX_PARTITION_QUIREPOND3); - return getCreateSUContextErrorsCommonPlatineSabiane(contextRootNode,requiredPartition); - } - - /** - * Get the context errors for an SU creation in Sabiane - * @param contextRootNode : the context to verify - * @return a Set with the errors - */ - public static Set getCreateSUContextErrorsSabiane(JsonNode contextRootNode){ - Set requiredPartition = - Set.of(CTX_PARTITION_ID,CTX_PARTITION_QUESTIONNAIRE_MODEL); - return getCreateSUContextErrorsCommonPlatineSabiane(contextRootNode,requiredPartition); - } - - private static Set getCreateSUContextErrorsCommonPlatineSabiane(JsonNode contextRootNode, Set requiredPartition){ - if(contextRootNode==null){ - return Set.of("Context is missing"); - } - Set results=new HashSet<>(); - Set requiredNodes = - Set.of( - //Global & Campaign - CTX_PARTITIONS, CTX_QUESTIONNAIRE_MODELS - ); - - results.addAll(DelegateContextVerifier.computeMissingChildrenMessages(requiredNodes,contextRootNode,QuestionnaireHelper.class)); - //Maybe one day we will have partitions for platine and partitions for sabiane and we will only validate the platine ones - //Partitions - var partitionIterator =contextRootNode.path(CTX_PARTITIONS).elements(); - while (partitionIterator.hasNext()) { - var partitionNode = partitionIterator.next(); - results.addAll(DelegateContextVerifier.computeMissingChildrenMessages(requiredPartition,partitionNode,QuestionnaireHelper.class)); - } - return results; - } -} diff --git a/src/main/java/fr/insee/protools/backend/service/common/platine_sabiane/QuestionnairePlatineSabianeService.java b/src/main/java/fr/insee/protools/backend/service/common/platine_sabiane/QuestionnairePlatineSabianeService.java deleted file mode 100644 index d3752adf..00000000 --- a/src/main/java/fr/insee/protools/backend/service/common/platine_sabiane/QuestionnairePlatineSabianeService.java +++ /dev/null @@ -1,181 +0,0 @@ -package fr.insee.protools.backend.service.common.platine_sabiane; - -import com.fasterxml.jackson.databind.JsonNode; -import fr.insee.protools.backend.dto.platine_sabiane_questionnaire.NomenclatureDto; -import fr.insee.protools.backend.dto.platine_sabiane_questionnaire.QuestionnaireModelCreateDto; -import fr.insee.protools.backend.dto.platine_sabiane_questionnaire.campaign.CampaignDto; -import fr.insee.protools.backend.dto.platine_sabiane_questionnaire.surveyunit.SurveyUnitResponseDto; -import fr.insee.protools.backend.webclient.WebClientHelper; -import fr.insee.protools.backend.webclient.exception.runtime.WebClient4xxBPMNError; -import fr.insee.protools.backend.webclient.exception.runtime.WebClient5xxBPMNError; -import fr.insee.protools.backend.webclient.exception.runtime.WebClientNullReturnBPMNError; -import org.slf4j.event.Level; -import org.springframework.http.HttpStatus; -import org.springframework.web.reactive.function.client.WebClient; - -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; - -public interface QuestionnairePlatineSabianeService { - - //Internal methods - WebClient webClient(); - org.slf4j.Logger getLogger(); - - /** Create a new nomenclature **/ - default void postNomenclature(String nomenclatureId, String nomenclatureLabel , JsonNode nomenclatureValue) { - NomenclatureDto dto = new NomenclatureDto(nomenclatureId,nomenclatureLabel,nomenclatureValue); - NomenclatureDto response = - webClient() - .post() - .uri("/api/nomenclature") - .bodyValue(dto) - .retrieve() - .bodyToMono(NomenclatureDto.class) - .block(); - getLogger().info("postNomenclature: nomenclatureId={} - response={}",nomenclatureId,response); - //TODO: gestion des erreurs (ex: 403...) - } - - /** Create a new questionnaireModel **/ - default void postQuestionnaireModel(String questionnaireId, String questionnaireLabel, JsonNode questionnaireValue, Set requiredNomenclatures) { - QuestionnaireModelCreateDto dto = - new QuestionnaireModelCreateDto(questionnaireId,questionnaireLabel,questionnaireValue,requiredNomenclatures); - - QuestionnaireModelCreateDto response = - webClient() - .post() - .uri("/api/questionnaire-models") - .bodyValue(dto) - .retrieve() - .bodyToMono(QuestionnaireModelCreateDto.class) - .block(); - getLogger().info("postQuestionnaireModel: questionnaireId={} - response={}",questionnaireId,response); - //TODO: gestion des erreurs (ex: 403...) - - } - - /** Get the list of existing nomenclatures */ - default Set getNomenclaturesId() { - List response = webClient() - .get() - .uri("/api/nomenclatures") - .retrieve() - .bodyToMono(List.class) - .block(); - getLogger().info("getNomenclaturesId: response= {}",response); - return (response==null)?new HashSet<>():response.stream().collect(Collectors.toSet()); - } - - /** Checks if the questionnaireModel exists **/ - default boolean questionnaireModelExists(String idQuestionnaireModel) { - getLogger().info("questionnaireModelExists: idQuestionnaireModel={} ",idQuestionnaireModel); - boolean modelExists = false; - try{ - var response = webClient() - .get() - .uri(uriBuilder -> uriBuilder - .path("/api/questionnaire/{id}") - .build(idQuestionnaireModel)) - .retrieve().toBodilessEntity().block(); - if(response==null) { - throw new WebClientNullReturnBPMNError("Error while checking if questionnaireModel exists - null result"); - } - - if(response.getStatusCode().is2xxSuccessful()) { - modelExists = true; - } - else if(response.getStatusCode().is4xxClientError()){ - if(response.getStatusCode()==HttpStatus.NOT_FOUND){ - modelExists=false; - } - else{ - throw new WebClient4xxBPMNError("Error while checking if questionnaireModel exists ", response.getStatusCode()); - } - } - else{ - throw new WebClient5xxBPMNError("Error while checking if questionnaireModel exists "); - } - getLogger().debug("response code={}",response.getStatusCode()); - } - catch (WebClient4xxBPMNError e){ - if(e.getHttpStatusCodeError().equals(HttpStatus.NOT_FOUND)){ - modelExists=false; - } - else { - throw e; - } - } - getLogger().info("questionnaireModelExists: idQuestionnaireModel={} - modelExists={}",idQuestionnaireModel,modelExists); - return modelExists; - } - - /** Create the campaign **/ - default void postCampaign(CampaignDto campaignDto) { - WebClientHelper.logJson("postCampaign: ", campaignDto,getLogger(), Level.DEBUG); - //Http Status Codes : https://github.com/InseeFr/Queen-Back-Office/blob/3.5.36-rc/src/main/java/fr/insee/queen/api/controller/CampaignController.java - // HttpStatus.BAD_REQUEST(400) if campaign already exists - // HttpStatus.FORBIDDEN (403) if the questionnaire does not exist or is already associated (Request to change it to 409) - // WARNING : 403 will also be returned if user does not have an authorized role - try { - var response = webClient() - .post() - .uri("/api/campaigns") - .bodyValue(campaignDto) - .retrieve() - .bodyToMono(String.class) - .block(); - getLogger().info("postCampaign: idCampaign={} - response={} ", campaignDto.getId(), response); - } - catch (WebClient4xxBPMNError e){ - if(e.getHttpStatusCodeError().equals(HttpStatus.FORBIDDEN)){ - String msg= - "Error 403/FORBIDEN during Questionnaire postCampaign." - + " It can be caused by a missing permission or if a questionnaire model" - + " "+campaignDto.getQuestionnaireIds() - +" is already assigned to another campaign." - + " msg="+e.getMessage(); - getLogger().error(msg); - throw new WebClient4xxBPMNError(msg,e.getHttpStatusCodeError()); - } - else if(e.getHttpStatusCodeError().equals(HttpStatus.BAD_REQUEST)){ - String msg="Error 400/BAD_REQUEST during Questionnaire postCampaign." - + " One possible cause is that the campaign already exists " - + " msg="+e.getMessage(); - getLogger().error(msg); - throw new WebClient4xxBPMNError(msg,e.getHttpStatusCodeError()); - } - //Currently no remediation so just rethrow - throw e; - } - } - - /** Create a survey Unit **/ - default void postSurveyUnit(SurveyUnitResponseDto suDto, String idCampaign) { - WebClientHelper.logJson("postSurveyUnit: idCampaign="+idCampaign, suDto,getLogger(),Level.DEBUG); - try { - var response = webClient() - .post() - .uri(uriBuilder -> uriBuilder - .path("/api/campaign/{id}/survey-unit") - .build(idCampaign)) - .bodyValue(suDto) - .retrieve() - .bodyToMono(String.class) - .block(); - getLogger().info("postSurveyUnit: idCampaign={} - idSu={} - response={} ", idCampaign,suDto.getId(), response); - } - catch (WebClient4xxBPMNError e){ - if(e.getHttpStatusCodeError().equals(HttpStatus.BAD_REQUEST)){ - String msg="Error 400/BAD_REQUEST during Questionnaire postSurveyUnit." - + " msg="+e.getMessage(); - getLogger().error(msg); - throw new WebClient4xxBPMNError(msg,e.getHttpStatusCodeError()); - } - //Currently no remediation so just rethrow - throw e; - } - } -} diff --git a/src/main/java/fr/insee/protools/backend/service/context/ContextConstants.java b/src/main/java/fr/insee/protools/backend/service/context/ContextConstants.java deleted file mode 100644 index ad129b9e..00000000 --- a/src/main/java/fr/insee/protools/backend/service/context/ContextConstants.java +++ /dev/null @@ -1,135 +0,0 @@ -package fr.insee.protools.backend.service.context; - -public final class ContextConstants { - - // Campaign context constants - Metadata - public static final String CTX_CAMPAGNE_ID = "id"; - public static final String CTX_CAMPAGNE_LABEL = "label"; - public static final String CTX_CAMPAGNE_CONTEXTE = "contexte"; //Values: Enum CampaignContext... - - - //Metadonnees Part - public static final String CTX_METADONNEES = "metadonnees"; - public static final String CTX_META_OPERATION_ID = "operationId";//== platine : Survey - public static final String CTX_META_SERIE_ID = "serieId"; //== platine : source - public static final String CTX_META_ANNEE = "annee"; - public static final String CTX_META_PERIODE = "periode"; - public static final String CTX_META_PERIODICITE = "periodicite"; - - public static final String CTX_META_LABEL_COURT_OPERATION = "operationLabelCourt"; - public static final String CTX_META_LABEL_LONG_OPERATION = "operationLabelLong"; - public static final String CTX_META_SERIE_LABEL_COURT = "serieLabelCourt"; - public static final String CTX_META_SERIE_LABEL_LONG = "serieLabelLong"; - public static final String CTX_META_PORTAIL_MES_ENQUETE_OPERATION = "portailMesEnquetesOperation"; - public static final String CTX_META_OBJECTIFS_COURTS = "objectifsCourts"; - public static final String CTX_META_OBJECTIFS_LONGS = "objectifsLongs"; - public static final String CTX_META_CARACTERE_OBLIGATOIRE = "caractereObligatoire"; - public static final String CTX_META_QUALITE_STATISTIQUE = "qualiteStatistique"; - public static final String CTX_META_TEST_NON_LABELLISE = "testNonLabellise"; - public static final String CTX_META_ANNEE_VISA = "anneeVisa"; - public static final String CTX_META_NUMERO_VISA = "numeroVisa"; - public static final String CTX_META_MINISTERE_TUTELLE = "ministereTutelle"; - public static final String CTX_META_PARUTION_JO = "parutionJo"; - public static final String CTX_META_DATE_PARUTION_JO = "dateParutionJo"; - public static final String CTX_META_RESPONSABLE_OPERATIONNEL = "responsableOperationnel"; - public static final String CTX_META_RESPONSABLE_TRAITEMENT = "responsableTraitement"; - public static final String CTX_META_CNIS_URL = "cnisUrl"; - public static final String CTX_META_DIFFUSION_URL = "diffusionUrl"; - public static final String CTX_META_NOTICE_URL = "noticeUrl"; - public static final String CTX_META_SPECIMENT_URL = "specimenUrl"; - //Metadonnees proprietaire (platine) - public static final String CTX_META_PROPRIETAIRE_ID = "proprietaireId"; - public static final String CTX_META_PROPRIETAIRE_LABEL = "proprietaireLabel"; - public static final String CTX_META_PROPRIETAIRE_LOGO = "proprietaireLogo"; - //Metadonnees assistance (platine) - public static final String CTX_META_ASSISTANCE_NIVO2_ID = "assistanceNiveau2Id"; - public static final String CTX_META_ASSISTANCE_NIVO2_LABEL = "assistanceNiveau2Label"; - public static final String CTX_META_ASSISTANCE_NIVO2_TEL = "assistanceNiveau2Tel"; - public static final String CTX_META_ASSISTANCE_NIVO2_MAIL = "assitanceNiveau2Mail"; - public static final String CTX_META_ASSISTANCE_NIVO2_PAYS = "asssistanceNiveau2Pays"; - public static final String CTX_META_ASSISTANCE_NIVO2_NUMERO_VOIE = "assistanceNiveau2NumeroVoie"; - public static final String CTX_META_ASSISTANCE_NIVO2_NOM_VOIE = "assistanceNiveau2NomVoie"; - public static final String CTX_META_ASSISTANCE_NIVO2_COMMUNE = "assistanceNiveau2Commune"; - public static final String CTX_META_ASSISTANCE_NIVO2_CODE_POSTAL = "assistanceNiveau2CodePostal"; - public static final String CTX_META_MAIL_BOITE_RETOUR = "mailBoiteRetour"; - public static final String CTX_META_URL_ENQUETE = "urlEnquete"; - public static final String CTX_META_THEME_MIEUX_CONNAITRE_MAIL = "themeMieuxConnaitreMail"; - public static final String CTX_META_SRVC_COL_SIGN_FONCTION = "serviceCollecteurSignataireFonction"; - public static final String CTX_META_SRVC_COL_SIGN_NOM = "serviceCollecteurSignataireNom"; - public static final String CTX_META_PRESTATAIRE = "prestataire"; - public static final String CTX_META_MAIL_RESP_OPERATIONNEL = "mailResponsableOperationnel"; - public static final String CTX_META_LOGO_PRESTATAIRE = "logoPrestataire"; - //Metadonnes platine - public static final String CTX_META_URL_LOI_RGPD = "urlLoiRGPD"; - public static final String CTX_META_URL_LOI_STATISTIQUE = "urlLoiStatistique"; - public static final String CTX_META_URL_LOI_INFORMATIQUE = "urlLoiInformatique"; - - - //Pour sabiane - public static final String CTX_META_REPERAGE = "reperage"; - public static final String CTX_META_ESSAIS_CONTACT = "essaisContact"; - public static final String CTX_META_BILAN_CONTACT = "bilanContact"; - public static final String CTX_META_REFERENTS_PRINCIPAUX = "referentsPrincipaux"; - public static final String CTX_META_REFERENTS_SECONDAIRES = "referentsSecondaires"; - public static final String CTX_META_SITES_GESTION = "sitesGestion"; - //Referents principaux et secondaires (sabiane) - public static final String CTX_META_REFERENT_NOM = "nom"; - public static final String CTX_META_REFERENT_PRENOM = "prenom"; - public static final String CTX_META_REFERENT_TELEPHONE = "telephone"; - - // Partitions - public static final String CTX_PARTITIONS = "partitions"; - public static final String CTX_PARTITION_ID = "id"; - public static final String CTX_PARTITION_LABEL = "label"; - public static final String CTX_PARTITION_TYPE_ECHANTILLON = "typeEchantillon"; - public static final String CTX_PARTITION_DATE_DEBUT_COLLECTE = "dateDebutCollecte"; - public static final String CTX_PARTITION_DATE_FIN_COLLECTE = "dateFinCollecte"; - public static final String CTX_PARTITION_DATE_RETOUR = "dateRetour"; - public static final String CTX_PARTITION_QUESTIONNAIRE_MODEL = "questionnaireModel"; - public static final String CTX_PARTITION_QUIREPOND1 = "quiRepond1"; - public static final String CTX_PARTITION_QUIREPOND2 = "quiRepond2"; - public static final String CTX_PARTITION_QUIREPOND3 = "quiRepond3"; - public static final String CTX_PARTITION_PRIORITAIRE = "prioritaire"; - - // Partitions Communications - public static final String CTX_PARTITION_COMMUNICATIONS = "communications"; - public static final String CTX_PARTITION_COMMUNICATION_MOYEN = "moyenCommunication"; - public static final String CTX_PARTITION_COMMUNICATION_PHASE = "phaseCommunication"; - public static final String CTX_PARTITION_COMMUNICATION_AVEC_QUESTIONNAIRE_PAPIER = "avecQuestionnairePapier"; - public static final String CTX_PARTITION_COMMUNICATION_PROTOCOLE = "protocole"; - public static final String CTX_PARTITION_COMMUNICATION_MODE = "mode"; - public static final String CTX_PARTITION_COMMUNICATION_TYPE_MODELE = "typeModele"; - public static final String CTX_PARTITION_COMMUNICATION_OBJET_MAIL = "objetMail"; - public static final String CTX_PARTITION_COMMUNICATION_RELANCE_LIBRE_PARAGRAPHE1 = "relanceLibreMailParagraphe1"; - public static final String CTX_PARTITION_COMMUNICATION_RELANCE_LIBRE_PARAGRAPHE2 = "relanceLibreMailParagraphe2"; - public static final String CTX_PARTITION_COMMUNICATION_RELANCE_LIBRE_PARAGRAPHE3 = "relanceLibreMailParagraphe3"; - public static final String CTX_PARTITION_COMMUNICATION_RELANCE_LIBRE_PARAGRAPHE4 = "relanceLibreMailParagraphe4"; - public static final String CTX_PARTITION_COMMUNICATION_COMPLEMENT_CONNEXION = "complementConnexion"; - - - - //Partitions, specific sabiane - public static final String CTX_PARTITION_SABIANE_DATE_DEBUT_VISIBILITE_GESTIONNAIRE = "dateDebutVisibiliteGestionnaire"; - public static final String CTX_PARTITION_SABIANE_DATE_DEBUT_VISIBILITE_ENQUETEUR = "dateDebutVisibiliteEnqueteur"; - public static final String CTX_PARTITION_SABIANE_DATE_DEBUT_REPERAGE = "dateDebutReperage"; - public static final String CTX_PARTITION_SABIANE_DATE_FIN_TRAITEMENT = "dateFinTraitement"; - - //Partitions, specific ERA - public static final String CTX_PARTITION_ERA_SEXE = "sexe"; - - // QuestionnaireModels - public static final String CTX_QUESTIONNAIRE_MODELS = "questionnaireModels"; - public static final String CTX_QUESTIONNAIRE_MODEL_ID = "id"; - public static final String CTX_QUESTIONNAIRE_MODEL_CHEMIN_REPERTOIRE = "cheminRepertoire"; - public static final String CTX_QUESTIONNAIRE_MODEL_LABEL = "label"; - public static final String CTX_QUESTIONNAIRE_MODEL_REQUIRED_NOMENCLATURES = "requiredNomenclatureIds"; - - // Nomenclatures - public static final String CTX_NOMENCLATURES = "nomenclatures"; - public static final String CTX_NOMENCLATURE_ID = "id"; - public static final String CTX_NOMENCLATURE_CHEMIN_REPERTOIRE = "cheminRepertoire"; - public static final String CTX_NOMENCLATURE_LABEL = "label"; - //Constants class should not be initialized - private ContextConstants() { - } - } \ No newline at end of file diff --git a/src/main/java/fr/insee/protools/backend/service/context/ContextServiceImpl.java b/src/main/java/fr/insee/protools/backend/service/context/ContextServiceImpl.java index 7f3a5a7c..b3434938 100644 --- a/src/main/java/fr/insee/protools/backend/service/context/ContextServiceImpl.java +++ b/src/main/java/fr/insee/protools/backend/service/context/ContextServiceImpl.java @@ -4,8 +4,14 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectReader; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import com.networknt.schema.JsonSchema; +import com.networknt.schema.JsonSchemaFactory; +import com.networknt.schema.SpecVersion; +import com.networknt.schema.ValidationMessage; +import fr.insee.protools.backend.dto.ContexteProcessus; import fr.insee.protools.backend.service.DelegateContextVerifier; -import fr.insee.protools.backend.service.context.exception.BadContextDateTimeParseBPMNError; +import fr.insee.protools.backend.service.context.exception.BadContexMissingBPMNError; import fr.insee.protools.backend.service.context.exception.BadContextIOException; import fr.insee.protools.backend.service.context.exception.BadContextIncorrectBPMNError; import fr.insee.protools.backend.service.context.exception.BadContextNotJSONBPMNError; @@ -14,7 +20,6 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.tuple.Pair; import org.flowable.bpmn.model.BpmnModel; import org.flowable.bpmn.model.FlowElement; import org.flowable.bpmn.model.ServiceTask; @@ -33,33 +38,30 @@ import org.springframework.web.multipart.MultipartFile; import java.io.IOException; -import java.io.Serializable; import java.nio.charset.StandardCharsets; -import java.time.Instant; -import java.time.LocalDateTime; -import java.time.ZoneId; -import java.time.format.DateTimeFormatter; -import java.time.format.DateTimeParseException; import java.util.*; import java.util.concurrent.ConcurrentHashMap; -import static fr.insee.protools.backend.service.FlowableVariableNameConstants.*; -import static fr.insee.protools.backend.service.context.ContextConstants.*; +import static fr.insee.protools.backend.service.FlowableVariableNameConstants.VARNAME_CONTEXT; @Service @Slf4j @RequiredArgsConstructor -public class ContextServiceImpl implements ContextService { - +public class ContextServiceImpl implements IContextService { + + private static final ObjectReader defaultReader = new ObjectMapper().registerModule(new JavaTimeModule()).reader(); // maybe with configs + //Key : processInstanceID + //Value: Pair + private static final Map contextCache = new ConcurrentHashMap<>(); + //TODO: Peut être que ca va sortir dans une dépendance externe + private static final String SCHEMA_VALIDATION_FILE = "/schema/contexte-processus.json"; private final RuntimeService runtimeService; private final TaskService taskService; private final RepositoryService repositoryService; private final ApplicationContext springApplicationContext; - - private static final ObjectMapper mapper = new ObjectMapper(); - private static final ObjectReader defaultReader = mapper.reader(); // maybe with configs - - private static final Map contextCache = new ConcurrentHashMap<>(); + private static final JsonSchema contextJsonSchema = JsonSchemaFactory + .getInstance(SpecVersion.VersionFlag.V202012) + .getSchema(ContextServiceImpl.class.getResourceAsStream(SCHEMA_VALIDATION_FILE)); @Override public void processContextFileAndCompleteTask(MultipartFile file, String taskId) { @@ -75,11 +77,14 @@ public void processContextFileAndCompleteTask(MultipartFile file, String taskId) } //check context - Pair, JsonNode> contextPair = processContextFile(file, task.getProcessDefinitionId()); + ContextPair contextPair = processContextFile(file, task.getProcessDefinitionId()); //Store context in cache - contextCache.put(task.getProcessInstanceId(), contextPair.getValue()); - // Complete task and store context within process variables - taskService.complete(taskId, contextPair.getKey()); + contextCache.put(task.getProcessInstanceId(), contextPair); + + // Complete task and store context raw json as string within process variables + Map variables = new HashMap<>(); + variables.put(VARNAME_CONTEXT, contextPair.contextAsString); + taskService.complete(taskId, variables); } @Override @@ -91,17 +96,21 @@ public String processContextFileAndCreateProcessInstance(MultipartFile file, Str try { //check context - Pair, JsonNode> contextPair = processContextFile(file, processDefinitionId); + ContextPair contextPair = processContextFile(file, processDefinitionId); //Create process instance ProcessInstance processInstance; + Map variables = new HashMap<>(); + variables.put(VARNAME_CONTEXT, contextPair.contextAsString); + if (StringUtils.isBlank(businessKey)) { - processInstance = runtimeService.startProcessInstanceByKey(processDefinitionId, contextPair.getKey()); + processInstance = runtimeService.startProcessInstanceByKey(processDefinitionId, variables); } else { - processInstance = runtimeService.startProcessInstanceByKey(processDefinitionId, businessKey, contextPair.getKey()); + processInstance = runtimeService.startProcessInstanceByKey(processDefinitionId, businessKey, variables); } log.info("Created new process instance with processDefinitionId={} - ProcessInstanceId={}", processDefinitionId, processInstance.getProcessInstanceId()); //Store context in cache - contextCache.put(processInstance.getProcessInstanceId(), contextPair.getValue()); + contextCache.put(processInstance.getProcessInstanceId(), contextPair); + return processInstance.getProcessInstanceId(); } catch (FlowableObjectNotFoundException e) { log.error("processDefinitionId={} is unknown", processDefinitionId); @@ -109,32 +118,63 @@ public String processContextFileAndCreateProcessInstance(MultipartFile file, Str } } + @Override + public JsonNode getContextJsonNodeByProcessInstance(String processInstanceId) { + try { + return defaultReader.readTree(getContextByProcessInstance(processInstanceId).contextAsString); + } catch (JsonProcessingException e) { + throw new BadContextIncorrectBPMNError(String.format("Context retrieved from engine cannot be parsed for processInstanceId=[%s] ", processInstanceId)); + } + } @Override - public JsonNode getContextByProcessInstance(String processInstanceId) { + public ContexteProcessus getContextDtoByProcessInstance(String processInstanceId) { + return getContextByProcessInstance(processInstanceId).contextSchema(); + } + + private ContextPair getContextByProcessInstance(String processInstanceId) { ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult(); if (processInstance == null) { throw new FlowableObjectNotFoundException("Could not find a process instance with id '" + processInstanceId + "'.", ProcessInstance.class); } - JsonNode result = contextCache.get(processInstanceId); + + ContextPair result = contextCache.get(processInstanceId); //If value does not exist in cache yet : Retrieve it and update cache if (result == null) { String contextStr = runtimeService.getVariable(processInstanceId, VARNAME_CONTEXT, String.class); - if(contextStr == null || contextStr.isBlank()){ - throw new BadContextIncorrectBPMNError(String.format("Context retrieved from engine is null or empty processInstanceId=[%s] ", processInstanceId)); + if (contextStr == null || contextStr.isBlank()) { + throw new BadContexMissingBPMNError(String.format("Context retrieved from engine is null or empty processInstanceId=[%s] ", processInstanceId)); } - try { - result = defaultReader.readTree(contextStr); - } catch (JsonProcessingException e) { - throw new BadContextIncorrectBPMNError(String.format("Context retrieved from engine could not be parsed for processInstanceId=[%s] - Exception : %s", processInstanceId, e.getMessage())); + ContexteProcessus schema = defaultReader.readValue(contextStr, ContexteProcessus.class); + result = new ContextPair(contextStr, schema); + contextCache.put(processInstanceId, result); + } catch (IOException e) { + throw new BadContextIncorrectBPMNError(String.format("Context cannot be parsed for processInstanceId=[%s] ", processInstanceId)); } - contextCache.put(processInstanceId, result); } return result; } - private Pair, JsonNode> processContextFile(MultipartFile file, String processDefinitionKey) { + protected ContexteProcessus jsonReadAndSchemaValidation(JsonNode rootContext) { + //Validate that the Json is valid regarding the json-schema + Set jsonValidationErrors = contextJsonSchema.validate(rootContext); + if (!jsonValidationErrors.isEmpty()) { + String message = String.format("Uploaded context is not correct according to the json-schema. Errors: %s", + jsonValidationErrors); + log.warn(message); + throw new BadContextNotJSONBPMNError(message); + } else { + try { + return defaultReader.treeToValue(rootContext, ContexteProcessus.class); + } catch (IllegalArgumentException | JsonProcessingException e) { + log.warn("Uploaded context cannot be parsed correctly {}", e.getMessage()); + throw new BadContextNotJSONBPMNError("Uploaded context cannot be parsed correctly"); + } + } + } + + protected ContextPair processContextFile(MultipartFile file, String processDefinitionKey) { //Validate file name (JSON) var fileExtension = getFileExtension(file.getOriginalFilename()); if (fileExtension.isEmpty()) { @@ -148,47 +188,17 @@ private Pair, JsonNode> processContextFile(MultipartFile fil log.debug("Context File content : " + content); JsonNode rootContext = defaultReader.readTree(content); - Set contextErrors = isContextOKForBPMN(processDefinitionKey, rootContext); + ContexteProcessus contexte = jsonReadAndSchemaValidation(rootContext); + + Set contextErrors = isContextOKForBPMN(processDefinitionKey, contexte); if (!contextErrors.isEmpty()) { throw new BadContextIncorrectBPMNError(contextErrors.toString()); } - log.info("idCampaign="+rootContext.path(CTX_CAMPAGNE_ID).textValue()); - - //Variables to store for this process - Map variables = new HashMap<>(); - //Store the raw json as string - variables.put(VARNAME_CONTEXT, content); - - // Extraction of campaign TIMER START/END dates - // Do extraction of important BPMN Variables in separates functions - JsonNode partitions = rootContext.path(CTX_PARTITIONS); - if (partitions.isMissingNode()) { - String msg = String.format("Missing %s in context", CTX_PARTITIONS); - log.error(msg); - throw new BadContextIncorrectBPMNError(msg); - } + log.info("idCampaign={}", contexte.getId()); - List partitionIds = new ArrayList<>(); - HashMap> variablesByPartition= new HashMap<>(); - - for (JsonNode partition : partitions) { - Pair startEndDT = getCollectionStartAndEndFromPartition(partition); - Long partitionId = partition.path(CTX_PARTITION_ID).asLong(); - partitionIds.add(partitionId); - - HashMap partitionVariables = new HashMap<>(); - partitionVariables.put(CTX_PARTITION_DATE_DEBUT_COLLECTE,startEndDT.getKey() ); - partitionVariables.put(CTX_PARTITION_DATE_FIN_COLLECTE,startEndDT.getValue() ); - - variablesByPartition.put(partitionId,partitionVariables); - } - - variables.put(VARNAME_CONTEXT_PARTITION_ID_LIST, partitionIds); - variables.put(VARNAME_CONTEXT_PARTITION_VARIABLES_BY_ID, variablesByPartition); - - return Pair.of(variables, rootContext); - } catch (IOException e) { - throw new BadContextIOException("Error while reading context content", e); + return new ContextPair(content, contexte); + } catch (IOException | IllegalArgumentException e) { + throw new BadContextIOException("Error while reading context content: " + e.getMessage(), e); } } @@ -198,96 +208,68 @@ private Optional getFileExtension(String filename) { .map(f -> f.substring(filename.lastIndexOf(".") + 1)); } - //TODO : soit les json schema permettent de valider les dates, soit il faudra valider toutes les dates comme ça - public static Pair getCollectionStartAndEndFromPartition(JsonNode partitionNode) { - String start = partitionNode.get(CTX_PARTITION_DATE_DEBUT_COLLECTE).asText(); - String end = partitionNode.get(CTX_PARTITION_DATE_DEBUT_COLLECTE).asText(); - - if(start==null || end==null){ - throw new BadContextIncorrectBPMNError(String.format("%s and %s must be defined on every partition", CTX_PARTITION_DATE_DEBUT_COLLECTE, CTX_PARTITION_DATE_FIN_COLLECTE)); - } - - try { - LocalDateTime collectionStart = LocalDateTime.parse(start, DateTimeFormatter.ISO_DATE_TIME); - LocalDateTime collectionEnd = LocalDateTime.parse(end, DateTimeFormatter.ISO_DATE_TIME); - log.info("partition_id={} - CollectionStartDate={} - CollectionEndDate={}", partitionNode.path(CTX_PARTITION_ID), collectionStart, collectionEnd); - return Pair.of(collectionStart.atZone(ZoneId.systemDefault()).toInstant(), - collectionEnd.atZone(ZoneId.systemDefault()).toInstant()); - - } catch (DateTimeParseException e) { - throw new BadContextIncorrectBPMNError(String.format("%s or %s cannot be casted to DateTime : %s", CTX_PARTITION_DATE_DEBUT_COLLECTE, CTX_PARTITION_DATE_FIN_COLLECTE, e.getMessage())); - } - } - - public static Instant getInstantFromPartition(JsonNode partitionNode, String subnode) throws BadContextDateTimeParseBPMNError { - JsonNode instantNode = partitionNode.get(subnode); - if (instantNode == null) { - throw new BadContextDateTimeParseBPMNError(String.format("node %s of partition %s does not exists", subnode, partitionNode.path(CTX_PARTITION_ID).asText())); - } - String valueTxt = partitionNode.path(subnode).asText(); - if (valueTxt.isBlank()) { - throw new BadContextDateTimeParseBPMNError(String.format("node %s of partition %s is blank", subnode, partitionNode.path(CTX_PARTITION_ID).asText())); - } - - try { - return Instant.parse(valueTxt); - } catch (DateTimeParseException e) { - throw new BadContextDateTimeParseBPMNError(String.format("node %s of partition %s having value [%s] cannot be parsed : %s", subnode, partitionNode.path(CTX_PARTITION_ID).asText(), valueTxt, e.getMessage())); - } - } - /** * Check if protoolsContextRootNode allows every Task implementing {@link fr.insee.protools.backend.service.DelegateContextVerifier#getContextErrors DelegateContextVerifier} interface to run correctly - * @param processDefinitionKey The process (BPMN) identifier - * @param protoolsContextRootNode The context to check + * + * @param processDefinitionKey The process (BPMN) identifier + * @param contexteProcessus The context to check * @return A list of the problems found * @throws FlowableObjectNotFoundException if no process definition (BPMN) matches processDefinitionKey */ - public Set isContextOKForBPMN(String processDefinitionKey, JsonNode protoolsContextRootNode) { + public Set isContextOKForBPMN(String processDefinitionKey, ContexteProcessus contexteProcessus) { //At least, the campaign ID should be defined so we can write it on process variables to be used un groovy scripts - Set errors=DelegateContextVerifier.computeMissingChildrenMessages(Set.of(CTX_CAMPAGNE_ID),protoolsContextRootNode,getClass()); + Set errors = new HashSet<>(); + if(contexteProcessus.getId()==null){ + errors.add("id is missing"); + } + if(contexteProcessus.getMetadonnees()==null){ + errors.add("metadonnees is missing"); + } ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery(); processDefinitionQuery.processDefinitionKey(processDefinitionKey); processDefinitionQuery.latestVersion(); ProcessDefinition definition = processDefinitionQuery.singleResult(); - if(definition==null){ + if (definition == null) { throw new FlowableObjectNotFoundException("Cannot find process definition with key " + processDefinitionKey, ProcessDefinition.class); } BpmnModel model = repositoryService.getBpmnModel(definition.getId()); - if(model==null){ + if (model == null) { throw new FlowableObjectNotFoundException("Cannot find process BPMN model definition with key " + processDefinitionKey, ProcessDefinition.class); } org.flowable.bpmn.model.Process processModel = model.getProcessById(processDefinitionKey); - if(processModel==null){ + if (processModel == null) { throw new FlowableObjectNotFoundException("Cannot find process Model with key " + processDefinitionKey, ProcessDefinition.class); } processModel.getFlowElements().stream() .filter(flowElement -> (flowElement instanceof ServiceTask || flowElement instanceof SubProcess)) - .forEach(flowElement -> errors.addAll(analyseProcess(flowElement,protoolsContextRootNode))); + .forEach(flowElement -> errors.addAll(analyseProcess(flowElement, contexteProcessus))); return errors; } - private Set analyseProcess(FlowElement flowElement, JsonNode protoolsContextRootNode){ + private Set analyseProcess(FlowElement flowElement, ContexteProcessus contexteProcessus) { if (flowElement instanceof ServiceTask serviceTask) { if (serviceTask.getImplementationType().equals("delegateExpression")) { String delegateExpression = serviceTask.getImplementation().replace("${", "").replace("}", ""); try { Object bean = springApplicationContext.getBean(delegateExpression); if (bean instanceof DelegateContextVerifier beanDelegateCtxVerifier) { - return beanDelegateCtxVerifier.getContextErrors(protoolsContextRootNode); + return beanDelegateCtxVerifier.getContextErrors(contexteProcessus); } + } catch (NoSuchBeanDefinitionException e) { } - catch (NoSuchBeanDefinitionException e){} } } else if (flowElement instanceof SubProcess subProcessFlowElement) { Set errors = new HashSet<>(); - subProcessFlowElement.getFlowElements().stream() - .forEach(subFlowElement -> errors.addAll(analyseProcess(subFlowElement,protoolsContextRootNode))); + subProcessFlowElement.getFlowElements() + .forEach(subFlowElement -> errors.addAll(analyseProcess(subFlowElement, contexteProcessus))); return errors; } return Set.of(); } + + protected record ContextPair(String contextAsString, ContexteProcessus contextSchema) { + } } diff --git a/src/main/java/fr/insee/protools/backend/service/context/ContextService.java b/src/main/java/fr/insee/protools/backend/service/context/IContextService.java similarity index 60% rename from src/main/java/fr/insee/protools/backend/service/context/ContextService.java rename to src/main/java/fr/insee/protools/backend/service/context/IContextService.java index f13d0003..183574b2 100644 --- a/src/main/java/fr/insee/protools/backend/service/context/ContextService.java +++ b/src/main/java/fr/insee/protools/backend/service/context/IContextService.java @@ -1,9 +1,11 @@ package fr.insee.protools.backend.service.context; import com.fasterxml.jackson.databind.JsonNode; +import fr.insee.protools.backend.dto.ContexteProcessus; +import fr.insee.protools.backend.service.context.exception.BadContexMissingBPMNError; import org.springframework.web.multipart.MultipartFile; -public interface ContextService { +public interface IContextService { /** * Process the uploaded file and store it's content in VARIABLE_NAME_SERIALIZED_CONTEXT_FILE engine variable. * If ok pass the task referenced by *taskId* to completed @@ -24,12 +26,21 @@ public interface ContextService { String processContextFileAndCreateProcessInstance(MultipartFile file, String processDefinitionId, String businessKey); /** - * Retrieve Protools Context from of a given processInstance ID + * Retrieve Protools Context as JsonNode from of a given processInstance ID * * @param processInstanceId * @return the Json context of the process associated with process Instance - * @throws + * @throws BadContexMissingBPMNError */ - JsonNode getContextByProcessInstance(String processInstanceId) ; + JsonNode getContextJsonNodeByProcessInstance(String processInstanceId); + + /** + * Retrieve Protools Context as DTO from of a given processInstance ID + * + * @param processInstanceId + * @return the Dto context of the process associated with process Instance + * @throws BadContexMissingBPMNError + */ + ContexteProcessus getContextDtoByProcessInstance(String processInstanceId); } diff --git a/src/main/java/fr/insee/protools/backend/service/context/enums/CampaignContextEnum.java b/src/main/java/fr/insee/protools/backend/service/context/enums/CampaignContextEnum.java deleted file mode 100644 index 1ff1c1f8..00000000 --- a/src/main/java/fr/insee/protools/backend/service/context/enums/CampaignContextEnum.java +++ /dev/null @@ -1,16 +0,0 @@ -package fr.insee.protools.backend.service.context.enums; - -public enum CampaignContextEnum { - HOUSEHOLD("household"), - BUSINESS("business"); - - final String contexte; - - CampaignContextEnum(String contexte) { - this.contexte = contexte; - } - - public String getAsString() { - return contexte; - } -} diff --git a/src/main/java/fr/insee/protools/backend/service/context/enums/PartitionTypeEchantillon.java b/src/main/java/fr/insee/protools/backend/service/context/enums/PartitionTypeEchantillon.java deleted file mode 100644 index bedf304a..00000000 --- a/src/main/java/fr/insee/protools/backend/service/context/enums/PartitionTypeEchantillon.java +++ /dev/null @@ -1,16 +0,0 @@ -package fr.insee.protools.backend.service.context.enums; - -public enum PartitionTypeEchantillon { - LOGEMENT("logement"), - INDIVIDU("individu"); - - final String val; - - PartitionTypeEchantillon(String val) { - this.val = val; - } - - public String getAsString() { - return val; - } -} diff --git a/src/main/java/fr/insee/protools/backend/service/context/exception/BadContexMissingBPMNError.java b/src/main/java/fr/insee/protools/backend/service/context/exception/BadContexMissingBPMNError.java new file mode 100644 index 00000000..51c8d225 --- /dev/null +++ b/src/main/java/fr/insee/protools/backend/service/context/exception/BadContexMissingBPMNError.java @@ -0,0 +1,10 @@ +package fr.insee.protools.backend.service.context.exception; + +import static fr.insee.protools.backend.service.BPMNErrorCode.BPMNERROR_CODE_DEFAULT; + +@SuppressWarnings("squid:S110") +public class BadContexMissingBPMNError extends BadContexteBPMNError { + public BadContexMissingBPMNError(String message) { + super(BPMNERROR_CODE_DEFAULT, message); + } +} diff --git a/src/main/java/fr/insee/protools/backend/service/context/exception/BadContextJSONValidationBPMNError.java b/src/main/java/fr/insee/protools/backend/service/context/exception/BadContextJSONValidationBPMNError.java new file mode 100644 index 00000000..df32c46d --- /dev/null +++ b/src/main/java/fr/insee/protools/backend/service/context/exception/BadContextJSONValidationBPMNError.java @@ -0,0 +1,15 @@ +package fr.insee.protools.backend.service.context.exception; + +import fr.insee.protools.backend.exception.ProtoolsBpmnError; + +import static fr.insee.protools.backend.service.BPMNErrorCode.BPMNERROR_CODE_DEFAULT; + +/** + * Runtime exception indicating the context json is not correct according to the json-schema + */ +public class BadContextJSONValidationBPMNError extends ProtoolsBpmnError { + + public BadContextJSONValidationBPMNError(String message) { + super(BPMNERROR_CODE_DEFAULT, message); + } +} diff --git a/src/main/java/fr/insee/protools/backend/service/context/resolvers/PartitionCtxResolver.java b/src/main/java/fr/insee/protools/backend/service/context/resolvers/PartitionCtxResolver.java index 5f3431af..e4815214 100644 --- a/src/main/java/fr/insee/protools/backend/service/context/resolvers/PartitionCtxResolver.java +++ b/src/main/java/fr/insee/protools/backend/service/context/resolvers/PartitionCtxResolver.java @@ -1,16 +1,26 @@ package fr.insee.protools.backend.service.context.resolvers; -import org.flowable.common.engine.api.FlowableException; +import fr.insee.protools.backend.dto.Communication; +import fr.insee.protools.backend.dto.Lot; +import fr.insee.protools.backend.service.context.IContextService; +import fr.insee.protools.backend.service.exception.IncoherentBPMNContextError; +import fr.insee.protools.backend.service.utils.FlowableVariableUtils; +import fr.insee.protools.backend.service.utils.log.TimeLogUtils; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.flowable.engine.impl.persistence.entity.ExecutionEntity; import org.springframework.stereotype.Component; -import java.io.Serializable; +import java.time.Duration; import java.time.Instant; -import java.util.HashMap; +import java.time.LocalDate; +import java.time.ZoneId; +import java.time.temporal.TemporalAmount; +import java.util.HashSet; +import java.util.Optional; +import java.util.Set; -import static fr.insee.protools.backend.service.FlowableVariableNameConstants.VARNAME_CONTEXT_PARTITION_VARIABLES_BY_ID; -import static fr.insee.protools.backend.service.context.ContextConstants.CTX_PARTITION_DATE_DEBUT_COLLECTE; -import static fr.insee.protools.backend.service.context.ContextConstants.CTX_PARTITION_DATE_FIN_COLLECTE; +import static fr.insee.protools.backend.service.FlowableVariableNameConstants.*; /** * Used to make protools context variables available in BPMN expressions @@ -26,25 +36,119 @@ * Flowable doc : https://documentation.flowable.com/latest/develop/be/be-expressions#customization */ @Component +@RequiredArgsConstructor +@Slf4j public class PartitionCtxResolver { + private final IContextService protoolsContext; - private Serializable getVariableOfPartition(ExecutionEntity execution, Long partitionId, String key) { - HashMap> variablesByPartition = execution.getVariable(VARNAME_CONTEXT_PARTITION_VARIABLES_BY_ID, HashMap.class); - HashMap partitionVariables = variablesByPartition.get(partitionId); - if(partitionVariables==null) { - throw new FlowableException("Could not get variable "+VARNAME_CONTEXT_PARTITION_VARIABLES_BY_ID+ " of partitionId="+partitionId); - } - return partitionVariables.get(key); + //TODO: à faire valider par le métier + private final TemporalAmount maxSendCommunicationWindowHours = Duration.ofHours(24);; + + //Date in a far away future + private static final Instant farAwayInstant = LocalDate.parse("9999-12-31").atStartOfDay(ZoneId.of("Europe/Paris")).toInstant(); + + + private Optional getPartition(ExecutionEntity execution, String partitionId){ + var context = protoolsContext.getContextDtoByProcessInstance(execution.getProcessInstanceId()); + return context.getLots().stream() + .filter(x -> String.valueOf(x.getId()).equalsIgnoreCase(partitionId)) + .findAny(); } - public Instant getCollectionStartDate(ExecutionEntity execution, Long partitionId) { - return (Instant) getVariableOfPartition(execution,partitionId,CTX_PARTITION_DATE_DEBUT_COLLECTE); + public Instant getCollectionStartDate(ExecutionEntity execution, String partitionId) { + return getPartition(execution,partitionId) + .orElseThrow(() -> new IncoherentBPMNContextError("Tried to get Collection Start date on undefined partition")) + .getDateDebutCollecte(); } - public Instant getCollectionEndtDate(ExecutionEntity execution, Long partitionId) { - return (Instant) getVariableOfPartition(execution,partitionId,CTX_PARTITION_DATE_FIN_COLLECTE); + public Instant getCollectionEndDate(ExecutionEntity execution, String partitionId) { + return getPartition(execution,partitionId) + .orElseThrow(() -> new IncoherentBPMNContextError("Tried to get Collection Start date on undefined partition")) + .getDateDebutCollecte(); + } + + @SuppressWarnings("unused") //used in BPMNS + public String getCommunicationType(ExecutionEntity execution, String partitionId, String communicationId) { + return getPartition(execution,partitionId) + .orElseThrow(() -> new IncoherentBPMNContextError("Tried to get communication type on an unknown partition : "+partitionId)) + .getCommunications().stream() + .filter(x -> String.valueOf(x.getId()).equalsIgnoreCase(communicationId)) + .findAny() + .orElseThrow(() -> new IncoherentBPMNContextError("Tried to get communication type on an unknown communication : "+communicationId)) + .getTypeCommunication().toString(); + } + + + //TODO: documenter l'histoire des 24H + @SuppressWarnings("unused") //Used in BPMN + public Instant scheduleNextCommunication(ExecutionEntity execution, String partitionId) { + + Instant now = Instant.now(); + + //Context + Lot partition = getPartition(execution,partitionId) + .orElseThrow(() -> new IncoherentBPMNContextError("Tried to get schedule next communication on an unknown partition : "+partitionId)); + + Set sentCommunicationIds = FlowableVariableUtils.getVariableOrNull(execution, VARNAME_ALREADY_SCHEDULED_COMMUNICATION_ID_SET, Set.class); + Set errorCommunicationIds = FlowableVariableUtils.getVariableOrNull(execution, VARNAME_COMMUNICATION_ERROR_ID_SET, Set.class); + + + if(sentCommunicationIds==null){ + sentCommunicationIds=new HashSet<>(); + } + if(errorCommunicationIds==null){ + errorCommunicationIds=new HashSet<>(); + } + + //Collection End if after current time + if(partition.getDateFinCollecte().isBefore(now)){ + log.error("ProcessInstanceId={} - partitionId={} - dateFinCollecte={} is in the past ==> Timer is set to a far away Instant ", + execution.getProcessInstanceId(), partitionId, TimeLogUtils.format(partition.getDateFinCollecte())); + return farAwayInstant; + } + + Instant nextCommEcheance = null; + String nextCommId=null; + + for (Communication communication: partition.getCommunications()){ + + //null is an error in config so we ignore it; + // and we also discard communications that have already been sent or that have been marked as in error + if(communication==null || communication.getEcheance()==null || sentCommunicationIds.contains(String.valueOf(communication.getId())) || errorCommunicationIds.contains(communication.getId().toString())){ + continue; + } + + //verify that echeance of communication to be sent is not too old + if(communication.getEcheance().plus(maxSendCommunicationWindowHours).isBefore(now)){ + log.warn("Partition id={} : Communication id={} has not been sent. Its echeance [ {} ] is too far past so it will not be sent", + partitionId,communication.getId(),TimeLogUtils.format(communication.getEcheance())); + + errorCommunicationIds.add(String.valueOf(communication.getId())); + execution.getRootProcessInstance().setVariableLocal(VARNAME_COMMUNICATION_ERROR_ID_SET,errorCommunicationIds); + } + //Among the not treated communications we compute the one with the first echeance + else if(nextCommEcheance == null || nextCommEcheance.isAfter(communication.getEcheance())){ + nextCommEcheance=communication.getEcheance(); + nextCommId=String.valueOf(communication.getId()); + } + } + + //If no communication left (all have already been treated) ==> far away future + if(nextCommId==null){ + nextCommEcheance = farAwayInstant; + } + else{ + sentCommunicationIds.add(nextCommId); + + execution.getParent().setVariableLocal(VARNAME_CURRENT_COMMUNICATION_ID,nextCommId); + execution.getRootProcessInstance().setVariableLocal(VARNAME_ALREADY_SCHEDULED_COMMUNICATION_ID_SET,sentCommunicationIds); + } + + log.info("part="+partitionId+" - nextCom="+TimeLogUtils.format(nextCommEcheance)); + return nextCommEcheance; } + } \ No newline at end of file diff --git a/src/main/java/fr/insee/protools/backend/service/delegate/sample/LogVariablesTask.java b/src/main/java/fr/insee/protools/backend/service/delegate/logging/LogVariablesTask.java similarity index 96% rename from src/main/java/fr/insee/protools/backend/service/delegate/sample/LogVariablesTask.java rename to src/main/java/fr/insee/protools/backend/service/delegate/logging/LogVariablesTask.java index 1105bbbc..4656cca0 100644 --- a/src/main/java/fr/insee/protools/backend/service/delegate/sample/LogVariablesTask.java +++ b/src/main/java/fr/insee/protools/backend/service/delegate/logging/LogVariablesTask.java @@ -1,4 +1,4 @@ -package fr.insee.protools.backend.service.delegate.sample; +package fr.insee.protools.backend.service.delegate.logging; import lombok.extern.slf4j.Slf4j; import org.flowable.engine.delegate.DelegateExecution; diff --git a/src/main/java/fr/insee/protools/backend/service/delegate/sample/SampleServiceTask.java b/src/main/java/fr/insee/protools/backend/service/delegate/sample/SampleServiceTask.java deleted file mode 100644 index b31efce0..00000000 --- a/src/main/java/fr/insee/protools/backend/service/delegate/sample/SampleServiceTask.java +++ /dev/null @@ -1,24 +0,0 @@ -package fr.insee.protools.backend.service.delegate.sample; - -import fr.insee.protools.backend.service.context.ContextService; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.flowable.engine.delegate.DelegateExecution; -import org.flowable.engine.delegate.JavaDelegate; -import org.springframework.stereotype.Component; - -@Component -@Slf4j -@RequiredArgsConstructor -public class SampleServiceTask implements JavaDelegate { - - private final ContextService contextService; - - @Override - public void execute(DelegateExecution delegateExecution) { - String messageLog = ""; - log.info("Variables : {}", delegateExecution.getVariables()); - log.info("\t Sample service getCurrentActivityId={} - getCurrentFlowElement={} {}" - ,delegateExecution.getCurrentActivityId(), delegateExecution.getCurrentFlowElement().getName(),messageLog); - } -} diff --git a/src/main/java/fr/insee/protools/backend/service/era/EraGetSUForPeriodAndGenderTask.java b/src/main/java/fr/insee/protools/backend/service/era/EraGetSUForPeriodAndGenderTask.java deleted file mode 100644 index ac375078..00000000 --- a/src/main/java/fr/insee/protools/backend/service/era/EraGetSUForPeriodAndGenderTask.java +++ /dev/null @@ -1,91 +0,0 @@ -package fr.insee.protools.backend.service.era; - -import com.fasterxml.jackson.databind.JsonNode; -import fr.insee.protools.backend.dto.era.CensusJsonDto; -import fr.insee.protools.backend.dto.era.GenderType; -import fr.insee.protools.backend.service.DelegateContextVerifier; -import fr.insee.protools.backend.service.context.ContextService; -import fr.insee.protools.backend.service.utils.FlowableVariableUtils; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.flowable.engine.delegate.DelegateExecution; -import org.flowable.engine.delegate.JavaDelegate; -import org.springframework.stereotype.Component; - -import java.time.LocalDate; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import static fr.insee.protools.backend.service.FlowableVariableNameConstants.*; -import static fr.insee.protools.backend.service.context.ContextConstants.CTX_PARTITIONS; -import static fr.insee.protools.backend.service.context.ContextConstants.CTX_PARTITION_ERA_SEXE; -import static fr.insee.protools.backend.service.utils.ContextUtils.getCurrentPartitionNode; - -@Component -@Slf4j -@RequiredArgsConstructor -public class EraGetSUForPeriodAndGenderTask implements JavaDelegate, DelegateContextVerifier { - - private final ContextService protoolsContext; - private final EraService eraService; - private final ContextService contextService; - - @Override - public void execute(DelegateExecution execution) { - JsonNode contextRootNode = protoolsContext.getContextByProcessInstance(execution.getProcessInstanceId()); - checkContextOrThrow(log, execution.getProcessInstanceId(), contextRootNode); - - LocalDate startDate = FlowableVariableUtils.getVariableOrThrow(execution, VARNAME_ERA_QUERY_START_DATE, LocalDate.class); - LocalDate endDate = FlowableVariableUtils.getVariableOrThrow(execution, VARNAME_ERA_QUERY_END_DATE, LocalDate.class); - Long currentPartitionId = FlowableVariableUtils.getVariableOrThrow(execution, VARNAME_CURRENT_PARTITION_ID, Long.class); - - //Get current partition from contexte to get it's defined sexe - JsonNode currentPartitionNode = getCurrentPartitionNode(contextRootNode, currentPartitionId); - GenderType sexe = GenderType.fromLabel(currentPartitionNode.path(CTX_PARTITION_ERA_SEXE).asText()); - log.info("ProcessInstanceId={} - currentPartitionId={} - startDate={} - endDate={} - sexe={} begin" - ,execution.getProcessInstanceId(), currentPartitionId,startDate,endDate,sexe); - - List response = eraService.getSUForPeriodAndSex(startDate, endDate, sexe); - execution.setVariableLocal(VARNAME_ERA_RESPONSE, response); - - log.info("ProcessInstanceId={} response.size={} end" - ,execution.getProcessInstanceId(), response.size()); - } - - @Override - public Set getContextErrors(JsonNode contextRootNode) { - if (contextRootNode == null) { - return Set.of("Context is missing"); - } - Set results = new HashSet<>(); - Set requiredNodes = - Set.of( - //Global & Campaign - CTX_PARTITIONS - ); - Set requiredPartition = - Set.of(CTX_PARTITION_ERA_SEXE); - results.addAll(DelegateContextVerifier.computeMissingChildrenMessages(requiredNodes, contextRootNode, getClass())); - var partitionIterator = contextRootNode.path(CTX_PARTITIONS).elements(); - - //Partitions - while (partitionIterator.hasNext()) { - var partitionNode = partitionIterator.next(); - var missingChildren = DelegateContextVerifier.computeMissingChildrenMessages(requiredPartition, partitionNode, getClass()); - if (!missingChildren.isEmpty()) { - results.addAll(missingChildren); - continue; - } - - //We will use the custom label - String genderType = partitionNode.path(CTX_PARTITION_ERA_SEXE).asText(); - try { - GenderType.fromLabel(genderType); - } catch (IllegalStateException i) { - results.add(DelegateContextVerifier.computeIncorrectEnumMessage(CTX_PARTITION_ERA_SEXE, genderType, GenderType.getAllValidLabels(), getClass())); - } - } - return results; - } -} \ No newline at end of file diff --git a/src/main/java/fr/insee/protools/backend/service/era/EraService.java b/src/main/java/fr/insee/protools/backend/service/era/EraService.java deleted file mode 100644 index c6b1720d..00000000 --- a/src/main/java/fr/insee/protools/backend/service/era/EraService.java +++ /dev/null @@ -1,44 +0,0 @@ -package fr.insee.protools.backend.service.era; - -import fr.insee.protools.backend.dto.era.CensusJsonDto; -import fr.insee.protools.backend.dto.era.GenderType; -import fr.insee.protools.backend.webclient.WebClientHelper; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.core.ParameterizedTypeReference; -import org.springframework.stereotype.Service; - -import java.time.LocalDate; -import java.time.format.DateTimeFormatter; -import java.util.List; - -import static fr.insee.protools.backend.webclient.configuration.ApiConfigProperties.KNOWN_API.KNOWN_API_ERA; - -@Service -@Slf4j -@RequiredArgsConstructor -public class EraService { - private static final DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); - private final WebClientHelper webClientHelper; - - public List getSUForPeriodAndSex(LocalDate startDate, LocalDate endDate, GenderType gender) { - log.info("getSUForPeriodAndSex - gender={} from {} to {}", gender, startDate, endDate); - ParameterizedTypeReference> typeReference = new ParameterizedTypeReference>() { - }; - - List response = webClientHelper.getWebClient(KNOWN_API_ERA) - .get() - .uri(uriBuilder -> uriBuilder - .path("/census-extraction/census-respondents-by-period-and-gender") - .queryParam("startDate", startDate.format(dateFormatter)) - .queryParam("endDate", endDate.format(dateFormatter)) - .queryParam("gender", gender) - .build()) - .retrieve() - .bodyToMono(typeReference) - .block(); - log.trace("getSUForPeriodAndSex - response={} ", response); - log.info("getSUForPeriodAndSex: end"); - return response; - } -} diff --git a/src/main/java/fr/insee/protools/backend/webclient/exception/runtime/WebClient5xxBPMNError.java b/src/main/java/fr/insee/protools/backend/service/exception/IncoherentBPMNContextError.java similarity index 53% rename from src/main/java/fr/insee/protools/backend/webclient/exception/runtime/WebClient5xxBPMNError.java rename to src/main/java/fr/insee/protools/backend/service/exception/IncoherentBPMNContextError.java index 2ad46b17..4ff6f8ff 100644 --- a/src/main/java/fr/insee/protools/backend/webclient/exception/runtime/WebClient5xxBPMNError.java +++ b/src/main/java/fr/insee/protools/backend/service/exception/IncoherentBPMNContextError.java @@ -1,11 +1,11 @@ -package fr.insee.protools.backend.webclient.exception.runtime; +package fr.insee.protools.backend.service.exception; import fr.insee.protools.backend.exception.ProtoolsBpmnError; import static fr.insee.protools.backend.service.BPMNErrorCode.BPMNERROR_CODE_DEFAULT; -public class WebClient5xxBPMNError extends ProtoolsBpmnError { - public WebClient5xxBPMNError(String message) { +public class IncoherentBPMNContextError extends ProtoolsBpmnError { + public IncoherentBPMNContextError(String message) { super(BPMNERROR_CODE_DEFAULT, message); } } diff --git a/src/main/java/fr/insee/protools/backend/service/exception/PageableAPIBPMNError.java b/src/main/java/fr/insee/protools/backend/service/exception/PageableAPIBPMNError.java new file mode 100644 index 00000000..b7f1e897 --- /dev/null +++ b/src/main/java/fr/insee/protools/backend/service/exception/PageableAPIBPMNError.java @@ -0,0 +1,13 @@ +package fr.insee.protools.backend.service.exception; + +import fr.insee.protools.backend.exception.ProtoolsBpmnError; + +import static fr.insee.protools.backend.service.BPMNErrorCode.BPMNERROR_CODE_DEFAULT; + +public class PageableAPIBPMNError extends ProtoolsBpmnError { + + + public PageableAPIBPMNError(String message) { + super(BPMNERROR_CODE_DEFAULT,message); + } +} \ No newline at end of file diff --git a/src/main/java/fr/insee/protools/backend/service/exception/SugoiServiceCallBPMNError.java b/src/main/java/fr/insee/protools/backend/service/exception/SugoiServiceCallBPMNError.java new file mode 100644 index 00000000..f58d72f8 --- /dev/null +++ b/src/main/java/fr/insee/protools/backend/service/exception/SugoiServiceCallBPMNError.java @@ -0,0 +1,12 @@ +package fr.insee.protools.backend.service.exception; + +import fr.insee.protools.backend.exception.ProtoolsBpmnError; + +import static fr.insee.protools.backend.service.BPMNErrorCode.BPMNERROR_CODE_DEFAULT; + +public class SugoiServiceCallBPMNError extends ProtoolsBpmnError { + + public SugoiServiceCallBPMNError(String message) { + super(BPMNERROR_CODE_DEFAULT,message); + } +} diff --git a/src/main/java/fr/insee/protools/backend/service/meshuggah/IMeshuggahService.java b/src/main/java/fr/insee/protools/backend/service/meshuggah/IMeshuggahService.java new file mode 100644 index 00000000..69e82980 --- /dev/null +++ b/src/main/java/fr/insee/protools/backend/service/meshuggah/IMeshuggahService.java @@ -0,0 +1,12 @@ +package fr.insee.protools.backend.service.meshuggah; + +import com.fasterxml.jackson.databind.JsonNode; + +import java.util.List; + +public interface IMeshuggahService { + + void postContext(String campaignId, JsonNode contextRootNode); + + void postCommunicationRequest(String campaignId, String communicationId, List list); +} diff --git a/src/main/java/fr/insee/protools/backend/service/meshuggah/MeshuggahCreateCommunicationsContextTask.java b/src/main/java/fr/insee/protools/backend/service/meshuggah/MeshuggahCreateCommunicationsContextTask.java deleted file mode 100644 index 9c0e6a59..00000000 --- a/src/main/java/fr/insee/protools/backend/service/meshuggah/MeshuggahCreateCommunicationsContextTask.java +++ /dev/null @@ -1,173 +0,0 @@ -package fr.insee.protools.backend.service.meshuggah; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ObjectNode; -import fr.insee.protools.backend.dto.meshuggah.MeshuggahComDetails; -import fr.insee.protools.backend.service.DelegateContextVerifier; -import fr.insee.protools.backend.service.context.ContextService; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.EnumUtils; -import org.flowable.engine.delegate.DelegateExecution; -import org.flowable.engine.delegate.JavaDelegate; -import org.springframework.stereotype.Component; - -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import static fr.insee.protools.backend.service.context.ContextConstants.*; - -@Component -@Slf4j -@RequiredArgsConstructor -public class MeshuggahCreateCommunicationsContextTask implements JavaDelegate, DelegateContextVerifier { - - private final ContextService protoolsContext; - private final MeshuggahService meshuggahService; - - private static final ObjectMapper objectMapper = new ObjectMapper(); - - @Override - public void execute(DelegateExecution execution) { - //Contexte - JsonNode contextRootNode = protoolsContext.getContextByProcessInstance(execution.getProcessInstanceId()); - checkContextOrThrow(log,execution.getProcessInstanceId(), contextRootNode); - String campainId = contextRootNode.path(CTX_CAMPAGNE_ID).asText(); - - log.info("ProcessInstanceId={} - campainId={} begin",execution.getProcessInstanceId(), campainId); - treatPartitions(campainId,contextRootNode); - log.info("ProcessInstanceId={} - campainId={} end",execution.getProcessInstanceId(), campainId); - } - - - private void treatPartitions(String campainId, JsonNode contextRootNode){ - //Partitions - var partitionIterator =contextRootNode.path(CTX_PARTITIONS).elements(); - while (partitionIterator.hasNext()) { - var partitionNode = partitionIterator.next(); - Long partitionId = partitionNode.path(CTX_PARTITION_ID).asLong(); - treatPartition(campainId,partitionId,contextRootNode,partitionNode); - } - } - - private void treatPartition(String campainId, Long partitionId,JsonNode contextRootNode,JsonNode partitionNode){ - log.trace("treatPartition partitionId={}",partitionId); - //Treat every communication of this partition - var communicationsIterator =partitionNode.path(CTX_PARTITION_COMMUNICATIONS).elements(); - while (communicationsIterator.hasNext()) { - var communicationNode = communicationsIterator.next(); - JsonNode body = initBody(contextRootNode,communicationNode); - MeshuggahComDetails meshuggahComDetails = MeshuggahUtils.computeMeshuggahComDetails(campainId,partitionId,communicationNode); - meshuggahService.postCreateCommunication(meshuggahComDetails, body); - } - } - - - - private static JsonNode initBody(JsonNode contextRootNode, JsonNode communicationNode){ - - //Meta données - String logoPrestataire = contextRootNode.path(CTX_METADONNEES).path(CTX_META_LOGO_PRESTATAIRE).asText(); - String mailRespOperationnel = contextRootNode.path(CTX_METADONNEES).path(CTX_META_MAIL_RESP_OPERATIONNEL).asText(); - boolean isPrestataire = contextRootNode.path(CTX_METADONNEES).path(CTX_META_PRESTATAIRE).asBoolean(); - String responsableOperationnel = contextRootNode.path(CTX_METADONNEES).path(CTX_META_RESPONSABLE_OPERATIONNEL).asText(); - String responsableTraitement = contextRootNode.path(CTX_METADONNEES).path(CTX_META_RESPONSABLE_TRAITEMENT).asText(); - String srvcCollSignFunc = contextRootNode.path(CTX_METADONNEES).path(CTX_META_SRVC_COL_SIGN_FONCTION).asText(); - String srvcCollSignNom = contextRootNode.path(CTX_METADONNEES).path(CTX_META_SRVC_COL_SIGN_NOM).asText(); - String themeMieuxConnaitreMail = contextRootNode.path(CTX_METADONNEES).path(CTX_META_THEME_MIEUX_CONNAITRE_MAIL).asText(); - String urlEnq = contextRootNode.path(CTX_METADONNEES).path(CTX_META_URL_ENQUETE).asText(); - String boiteMailRetour = contextRootNode.path(CTX_METADONNEES).path(CTX_META_MAIL_BOITE_RETOUR).asText(); - - ObjectNode body = objectMapper.createObjectNode(); - body.put("Enq_ComplementConnexion",communicationNode.path(CTX_PARTITION_COMMUNICATION_COMPLEMENT_CONNEXION).asText()); - body.put("Enq_LogoPrestataire",logoPrestataire); - body.put("Enq_MailRespOperationnel",mailRespOperationnel); - body.put("Enq_Prestataire",isPrestataire?"oui":"non"); - body.put("Enq_RelanceLibreMailParagraphe1",communicationNode.path(CTX_PARTITION_COMMUNICATION_RELANCE_LIBRE_PARAGRAPHE1).asText()); - body.put("Enq_RelanceLibreMailParagraphe2",communicationNode.path(CTX_PARTITION_COMMUNICATION_RELANCE_LIBRE_PARAGRAPHE2).asText()); - body.put("Enq_RelanceLibreMailParagraphe3",communicationNode.path(CTX_PARTITION_COMMUNICATION_RELANCE_LIBRE_PARAGRAPHE3).asText()); - body.put("Enq_RelanceLibreMailParagraphe4",communicationNode.path(CTX_PARTITION_COMMUNICATION_RELANCE_LIBRE_PARAGRAPHE4).asText()); - body.put("Enq_RespOperationnel",responsableOperationnel); - body.put("Enq_RespTraitement",responsableTraitement); - body.put("Enq_ServiceCollecteurSignataireFonction",srvcCollSignFunc); - body.put("Enq_ServiceCollecteurSignataireNom",srvcCollSignNom); - body.put("Enq_ThemeMieuxConnaitreMail",themeMieuxConnaitreMail); - body.put("Enq_UrlEnquete",urlEnq); - body.put("Mail_BoiteRetour",boiteMailRetour); - body.put("Mail_Objet",communicationNode.path(CTX_PARTITION_COMMUNICATION_OBJET_MAIL).asText()); - - return body; - } - - - - @Override - public Set getContextErrors(JsonNode contextRootNode) { - if (contextRootNode == null) { - return Set.of("Context is missing"); - } - Set results = new HashSet<>(); - Set requiredNodes = - Set.of( - //Global & Campaign - CTX_CAMPAGNE_ID,CTX_METADONNEES,CTX_PARTITIONS - ); - Set requiredPartition = - Set.of(CTX_PARTITION_ID,CTX_PARTITION_COMMUNICATIONS); - - Set requiredMetadonnees = - Set.of(CTX_META_LOGO_PRESTATAIRE,CTX_META_MAIL_RESP_OPERATIONNEL,CTX_META_PRESTATAIRE,CTX_META_RESPONSABLE_OPERATIONNEL,CTX_META_RESPONSABLE_TRAITEMENT, - CTX_META_SRVC_COL_SIGN_FONCTION,CTX_META_SRVC_COL_SIGN_NOM,CTX_META_THEME_MIEUX_CONNAITRE_MAIL,CTX_META_URL_ENQUETE,CTX_META_MAIL_BOITE_RETOUR - ); - Set requiredCommunication = - Stream.of(CTX_PARTITION_COMMUNICATION_COMPLEMENT_CONNEXION, - CTX_PARTITION_COMMUNICATION_RELANCE_LIBRE_PARAGRAPHE1, - CTX_PARTITION_COMMUNICATION_RELANCE_LIBRE_PARAGRAPHE2, - CTX_PARTITION_COMMUNICATION_RELANCE_LIBRE_PARAGRAPHE3, - CTX_PARTITION_COMMUNICATION_RELANCE_LIBRE_PARAGRAPHE4, - CTX_PARTITION_COMMUNICATION_OBJET_MAIL - ).collect(Collectors.toSet()); - requiredCommunication.addAll(MeshuggahUtils.getCommunicationRequiredFields()); - - results.addAll(DelegateContextVerifier.computeMissingChildrenMessages(requiredNodes, contextRootNode, getClass())); - results.addAll(DelegateContextVerifier.computeMissingChildrenMessages(requiredMetadonnees,contextRootNode.path(CTX_METADONNEES),getClass())); - - //Partitions - var partitionIterator = contextRootNode.path(CTX_PARTITIONS).elements(); - while (partitionIterator.hasNext()) { - var partitionNode = partitionIterator.next(); - var missingChildren = DelegateContextVerifier.computeMissingChildrenMessages(requiredPartition, partitionNode, getClass()); - if (!missingChildren.isEmpty()) { - results.addAll(missingChildren); - continue; - } - - //Communications of the partition - var communicationIterator = partitionNode.path(CTX_PARTITION_COMMUNICATIONS).elements(); - while (communicationIterator.hasNext()) { - var communicationNode = communicationIterator.next(); - var missingChildrenCom = DelegateContextVerifier.computeMissingChildrenMessages(requiredCommunication, communicationNode, getClass()); - if (!missingChildrenCom.isEmpty()) { - results.addAll(missingChildrenCom); - } - //Verify medium enum - String medium = communicationNode.path(CTX_PARTITION_COMMUNICATION_MOYEN).asText(); - if(! EnumUtils.isValidEnumIgnoreCase(MeshuggahUtils.MediumEnum.class, medium)){ - results.add(DelegateContextVerifier.computeIncorrectEnumMessage(CTX_PARTITION_COMMUNICATION_MOYEN,medium, Arrays.toString(MeshuggahUtils.MediumEnum.values()),getClass())); - } - - //Verify medium enum - String phase = communicationNode.path(CTX_PARTITION_COMMUNICATION_PHASE).asText(); - if(! EnumUtils.isValidEnumIgnoreCase(MeshuggahUtils.PhaseEnum.class, phase)){ - results.add(DelegateContextVerifier.computeIncorrectEnumMessage(CTX_PARTITION_COMMUNICATION_PHASE,medium, Arrays.toString(MeshuggahUtils.PhaseEnum.values()),getClass())); - } - } - } - return results; - } - -} \ No newline at end of file diff --git a/src/main/java/fr/insee/protools/backend/service/meshuggah/MeshuggahSendCommunicationsForSUTask.java b/src/main/java/fr/insee/protools/backend/service/meshuggah/MeshuggahSendCommunicationsForSUTask.java deleted file mode 100644 index fcb74603..00000000 --- a/src/main/java/fr/insee/protools/backend/service/meshuggah/MeshuggahSendCommunicationsForSUTask.java +++ /dev/null @@ -1,150 +0,0 @@ -package fr.insee.protools.backend.service.meshuggah; - -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -@Component -@Slf4j -public class MeshuggahSendCommunicationsForSUTask -// implements JavaDelegate, DelegateContextVerifier -{ -// -// @Autowired ContextService protoolsContext; -// @Autowired MeshuggahService meshuggahService; -// -// private static final ObjectMapper objectMapper = new ObjectMapper(); -// -// static final Pattern echenancePattern = Pattern.compile("^\s*(?:J|j)\\+([0-9]+)\s*$"); -// -// -// @Override -// public void execute(DelegateExecution execution) { -// //Contexte -// JsonNode contextRootNode = protoolsContext.getContextByProcessInstance(execution.getProcessInstanceId()); -// checkContextOrThrow(log,execution.getProcessInstanceId(), contextRootNode); -// String campainId = contextRootNode.path(CTX_CAMPAGNE_ID).asText(); -// -// //Variables -// JsonNode contactNode = FlowableVariableUtils.getVariableOrThrow(execution,VARNAME_PLATINE_CONTACT, JsonNode.class); -// -// //each row is Tuple -// Triple suItem = FlowableVariableUtils.getVariableOrThrow(execution, VARNAME_SU_CREATION_ITEM, Triple.class); -// Instant creationInstant = suItem.getLeft(); -// Long partitionId = suItem.getMiddle(); -// Long remSUId = suItem.getRight(); -// -// log.info("ProcessInstanceId={} - campainId={} begin",execution.getProcessInstanceId(), campainId); -// -// -// //Get partition from contexte -// JsonNode partitionNode = getCurrentPartitionNode(contextRootNode, partitionId); -// -// treatCommunications(partitionNode,creationInstant,remSUId); -// -// -// -// -// PlatineContactDto platineContactDto; -// try { -// platineContactDto=objectMapper.treeToValue(contactNode,PlatineContactDto.class); -// } catch (JsonProcessingException e) { -// throw new IncorrectPlatineContactError("Error while parsing the json retrieved for platine contact : " + contactNode,contactNode, e); -// } -// -// -// //TODO : Currently only send OPENING -// JsonNode communicationNode = MeshuggahUtils.getCommunication(partitionNode,"mail","ouverture"); -// //TODO : hack avec le mail de marc -// platineContactDto.setEmail("marc.berger@insee.fr"); -// JsonNode body = initBody(platineContactDto); -// MeshuggahComDetails meshuggahComDetails = MeshuggahUtils.computeMeshuggahComDetails(campainId,currentPartitionId,communicationNode); -// meshuggahService.postSendCommunication(meshuggahComDetails, body); -// -// log.info("ProcessInstanceId={} - campainId={} end",execution.getProcessInstanceId(), campainId); -// } -// -// private void treatCommunications(JsonNode partitionNode, Instant creationInstant, Long remSUId) { -// -// LocalDate createDate = LocalDate.ofInstant(creationInstant, ZoneId.systemDefault()); -// LocalDate currentDay = LocalDate.now(); -// -// //Partitions -// //Treat every communication of this partition -// var communicationsIterator =partitionNode.path(CTX_PARTITION_COMMUNICATIONS).elements(); -// while (communicationsIterator.hasNext()) { -// var communicationNode = communicationsIterator.next(); -// var echeancesIterator = communicationNode.path(CTX_PARTITION_COMMUNICATION_ECHEANCES).elements(); -// while (communicationsIterator.hasNext()) { -// String echeanceStr = echeancesIterator.next().asText(); -// // create matcher for pattern p and given string -// Matcher matcher = echenancePattern.matcher(echeanceStr); -// // if an occurrence if a pattern was found in a given string... -// if (matcher.find()) { -// Integer nbOfDays = Integer.parseInt(matcher.group(1)); -// //Compute echeance by adding days to creation date -// LocalDate echeanceDate = createDate.plusDays(nbOfDays); -// -// //If echeanceDate is before or equals to today -// if(echeanceDate.compareTo(currentDay)<=0) { -// JsonNode body = initBody(contextRootNode,communicationNode); -// MeshuggahComDetails meshuggahComDetails = MeshuggahUtils.computeMeshuggahComDetails(campainId,partitionId,communicationNode); -// meshuggahService.postCreateCommunication(meshuggahComDetails, body); -// } -// } -// -// -// } -// -// } -// -// private static JsonNode initBody(PlatineContactDto platine_contact){ -// ObjectNode body = objectMapper.createObjectNode(); -// body.put("email",platine_contact.getEmail()); -// body.put("Ue_CalcIdentifiant",platine_contact.getIdentifier()); -// return body; -// } -// -// -// -// -// @Override -// public Set getContextErrors(JsonNode contextRootNode) { -// if (contextRootNode == null) { -// return Set.of("Context is missing"); -// } -// Set results = new HashSet<>(); -// Set requiredNodes = -// Set.of( -// //Global & Campaign -// CTX_CAMPAGNE_ID,CTX_PARTITIONS -// ); -// Set requiredPartition = -// Set.of(CTX_PARTITION_ID,CTX_PARTITION_COMMUNICATIONS); -// -// Set requiredCommunication = MeshuggahUtils.getCommunicationRequiredFields(); -// results.addAll(DelegateContextVerifier.computeMissingChildrenMessages(requiredNodes, contextRootNode, getClass())); -// -// //Partitions -// var partitionIterator = contextRootNode.path(CTX_PARTITIONS).elements(); -// while (partitionIterator.hasNext()) { -// var partitionNode = partitionIterator.next(); -// var missingChildren = DelegateContextVerifier.computeMissingChildrenMessages(requiredPartition, partitionNode, getClass()); -// if (!missingChildren.isEmpty()) { -// results.addAll(missingChildren); -// continue; -// } -// -// //Communications of the partition -// var communicationIterator = partitionNode.path(CTX_PARTITION_COMMUNICATIONS).elements(); -// while (communicationIterator.hasNext()) { -// var communicationNode = partitionIterator.next(); -// var missingChildrenCom = DelegateContextVerifier.computeMissingChildrenMessages(requiredCommunication, communicationNode, getClass()); -// if (!missingChildrenCom.isEmpty()) { -// results.addAll(missingChildrenCom); -// } -// } -// } -// return results; -// } -} - diff --git a/src/main/java/fr/insee/protools/backend/service/meshuggah/MeshuggahSendOpeningMailCommunicationForSUTask.java b/src/main/java/fr/insee/protools/backend/service/meshuggah/MeshuggahSendOpeningMailCommunicationForSUTask.java deleted file mode 100644 index 7cff6a37..00000000 --- a/src/main/java/fr/insee/protools/backend/service/meshuggah/MeshuggahSendOpeningMailCommunicationForSUTask.java +++ /dev/null @@ -1,118 +0,0 @@ -package fr.insee.protools.backend.service.meshuggah; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ObjectNode; -import fr.insee.protools.backend.dto.meshuggah.MeshuggahComDetails; -import fr.insee.protools.backend.dto.platine.pilotage.contact.PlatineContactDto; -import fr.insee.protools.backend.service.DelegateContextVerifier; -import fr.insee.protools.backend.service.context.ContextService; -import fr.insee.protools.backend.service.exception.IncorrectPlatineContactError; -import fr.insee.protools.backend.service.utils.FlowableVariableUtils; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.flowable.engine.delegate.DelegateExecution; -import org.flowable.engine.delegate.JavaDelegate; -import org.springframework.stereotype.Component; - -import java.util.HashSet; -import java.util.Set; - -import static fr.insee.protools.backend.service.FlowableVariableNameConstants.VARNAME_CURRENT_PARTITION_ID; -import static fr.insee.protools.backend.service.FlowableVariableNameConstants.VARNAME_PLATINE_CONTACT; -import static fr.insee.protools.backend.service.context.ContextConstants.*; -import static fr.insee.protools.backend.service.utils.ContextUtils.getCurrentPartitionNode; - -@Component -@Slf4j -@RequiredArgsConstructor -public class MeshuggahSendOpeningMailCommunicationForSUTask implements JavaDelegate, DelegateContextVerifier { - - private static final ObjectMapper objectMapper = new ObjectMapper(); - private final ContextService protoolsContext; - private final MeshuggahService meshuggahService; - - private static JsonNode initBody(PlatineContactDto platineContact) { - ObjectNode body = objectMapper.createObjectNode(); - body.put("email", platineContact.getEmail()); - body.put("Ue_CalcIdentifiant", platineContact.getIdentifier()); - return body; - } - - @Override - public void execute(DelegateExecution execution) { - //Contexte - JsonNode contextRootNode = protoolsContext.getContextByProcessInstance(execution.getProcessInstanceId()); - checkContextOrThrow(log, execution.getProcessInstanceId(), contextRootNode); - String campainId = contextRootNode.path(CTX_CAMPAGNE_ID).asText(); - - //Variables - Long currentPartitionId = FlowableVariableUtils.getVariableOrThrow(execution, VARNAME_CURRENT_PARTITION_ID, Long.class); - JsonNode contactNode = FlowableVariableUtils.getVariableOrThrow(execution, VARNAME_PLATINE_CONTACT, JsonNode.class); - - MeshuggahUtils.MediumEnum medium = MeshuggahUtils.MediumEnum.MAIL; - MeshuggahUtils.PhaseEnum phase = MeshuggahUtils.PhaseEnum.OUVERTURE; - - PlatineContactDto platineContactDto; - try { - platineContactDto = objectMapper.treeToValue(contactNode, PlatineContactDto.class); - } catch (JsonProcessingException e) { - throw new IncorrectPlatineContactError("Error while parsing the json retrieved for platine contact : " + contactNode, contactNode, e); - } - - //Get current partition from contexte - JsonNode currentPartitionNode = getCurrentPartitionNode(contextRootNode, currentPartitionId); - log.info("ProcessInstanceId={} - campainId={} - currentPartitionId={} - platineContactDto={} begin", - execution.getProcessInstanceId(), campainId, currentPartitionId,platineContactDto); - - JsonNode communicationNode = MeshuggahUtils.getCommunication(currentPartitionNode, medium, phase); - JsonNode body = initBody(platineContactDto); - - MeshuggahComDetails meshuggahComDetails = MeshuggahUtils.computeMeshuggahComDetails(campainId, currentPartitionId, communicationNode); - meshuggahService.postSendCommunication(meshuggahComDetails, body); - - log.debug("ProcessInstanceId={} - campainId={} - currentPartitionId={} - platineContactDto={} end", - execution.getProcessInstanceId(), campainId, currentPartitionId,platineContactDto); - } - - @Override - public Set getContextErrors(JsonNode contextRootNode) { - if (contextRootNode == null) { - return Set.of("Context is missing"); - } - Set results = new HashSet<>(); - Set requiredNodes = Set.of( - //Global & Campaign - CTX_CAMPAGNE_ID, CTX_PARTITIONS); - Set requiredPartition = Set.of(CTX_PARTITION_ID, CTX_PARTITION_COMMUNICATIONS); - - Set requiredCommunication = MeshuggahUtils.getCommunicationRequiredFields(); - results.addAll(DelegateContextVerifier.computeMissingChildrenMessages(requiredNodes, contextRootNode, getClass())); - - //Partitions - var partitionIterator = contextRootNode.path(CTX_PARTITIONS).elements(); - while (partitionIterator.hasNext()) { - var partitionNode = partitionIterator.next(); - var missingChildren = DelegateContextVerifier.computeMissingChildrenMessages(requiredPartition, partitionNode, getClass()); - if (!missingChildren.isEmpty()) { - results.addAll(missingChildren); - continue; - } - - //Communications of the partition - var communicationIterator = partitionNode.path(CTX_PARTITION_COMMUNICATIONS).elements(); - while (communicationIterator.hasNext()) { - var communicationNode = communicationIterator.next(); - var missingChildrenCom = DelegateContextVerifier.computeMissingChildrenMessages(requiredCommunication, communicationNode, getClass()); - if (!missingChildrenCom.isEmpty()) { - results.addAll(missingChildrenCom); - } - } - } - return results; - } - - -} - diff --git a/src/main/java/fr/insee/protools/backend/service/meshuggah/MeshuggahService.java b/src/main/java/fr/insee/protools/backend/service/meshuggah/MeshuggahService.java deleted file mode 100644 index a216b6c5..00000000 --- a/src/main/java/fr/insee/protools/backend/service/meshuggah/MeshuggahService.java +++ /dev/null @@ -1,66 +0,0 @@ -package fr.insee.protools.backend.service.meshuggah; - -import com.fasterxml.jackson.databind.JsonNode; -import fr.insee.protools.backend.dto.meshuggah.MeshuggahComDetails; -import fr.insee.protools.backend.webclient.WebClientHelper; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - -import static fr.insee.protools.backend.webclient.configuration.ApiConfigProperties.KNOWN_API.KNOWN_API_MESHUGGAH; - -@Service -@Slf4j -@RequiredArgsConstructor -public class MeshuggahService { - - private final WebClientHelper webClientHelper; - - - public void postCreateCommunication(MeshuggahComDetails meshuggahComDetails, JsonNode body) { - log.debug("postCreateCommunication: meshuggahComDetails={}",meshuggahComDetails); - String response = webClientHelper.getWebClient(KNOWN_API_MESHUGGAH) - .post() - .uri(uriBuilder -> uriBuilder - .path("/api/communication/medium/{medium}/campagne/{campaignId}/partition/{partitioningId}/phase/{phase}/operation/{operation}/mode/{mode}/protocol/{protocol}") - .queryParam("avecQuestionnaire",meshuggahComDetails.isAvecQuestionnaire()) - .build( - meshuggahComDetails.getMedium(), - meshuggahComDetails.getCampaignId(), - meshuggahComDetails.getPartitioningId(), - meshuggahComDetails.getPhase(), - meshuggahComDetails.getOperation(), - meshuggahComDetails.getMode(), - meshuggahComDetails.getProtocol())) - .bodyValue(body) - .retrieve() - .bodyToMono(String.class) - .block(); - log.debug("postCreateCommunication: meshuggahComDetails={} - response={}",meshuggahComDetails,response); - - } - - public void postSendCommunication(MeshuggahComDetails meshuggahComDetails, JsonNode body) { - log.debug("postSendCommunication: meshuggahComDetails={}",meshuggahComDetails); - String response = webClientHelper.getWebClient(KNOWN_API_MESHUGGAH) - .post() - .uri(uriBuilder -> uriBuilder - .path("/api/communication-request/medium/{medium}/campagne/{campaignId}/partition/{partitioningId}/phase/{phase}/operation/{operation}/mode/{mode}/protocol/{protocol}") - .queryParam("avecQuestionnaire",meshuggahComDetails.isAvecQuestionnaire()) - .build( - meshuggahComDetails.getMedium(), - meshuggahComDetails.getCampaignId(), - meshuggahComDetails.getPartitioningId(), - meshuggahComDetails.getPhase(), - meshuggahComDetails.getOperation(), - meshuggahComDetails.getMode(), - meshuggahComDetails.getProtocol())) - .bodyValue(body) - .retrieve() - .bodyToMono(String.class) - .block(); - log.debug("postSendCommunication: meshuggahComDetails={} - response={}",meshuggahComDetails,response); - - } - - } diff --git a/src/main/java/fr/insee/protools/backend/service/meshuggah/MeshuggahServiceImpl.java b/src/main/java/fr/insee/protools/backend/service/meshuggah/MeshuggahServiceImpl.java new file mode 100644 index 00000000..76c3b4bc --- /dev/null +++ b/src/main/java/fr/insee/protools/backend/service/meshuggah/MeshuggahServiceImpl.java @@ -0,0 +1,44 @@ +package fr.insee.protools.backend.service.meshuggah; + + +import com.fasterxml.jackson.databind.JsonNode; +import fr.insee.protools.backend.restclient.RestClientHelper; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.List; + +import static fr.insee.protools.backend.restclient.configuration.ApiConfigProperties.KNOWN_API.KNOWN_API_MESHUGGAH; + +@Service +@Slf4j +@RequiredArgsConstructor +public class MeshuggahServiceImpl implements IMeshuggahService{ + + private final RestClientHelper restClientHelper; + + @Override + public void postContext(String campaignId, JsonNode contextRootNode) { + log.trace("postContext: campaignId={}",campaignId); + var response = restClientHelper.getRestClient(KNOWN_API_MESHUGGAH) + .post() + .uri("/context") + .body(contextRootNode) + .retrieve() + .body(String.class); + log.trace("postContext: campaignId={} - response={} ",campaignId,response); + } + + @Override + public void postCommunicationRequest(String campaignId, String communicationId, List list) { + log.trace("postCommunicationRequest: campaignId={} - communicationId={}",campaignId,communicationId); + var response = restClientHelper.getRestClient(KNOWN_API_MESHUGGAH) + .post() + .uri("/context") + .body(list) + .retrieve() + .body(String.class); + log.trace("postCommunicationRequest: campaignId={} - communicationId={} - response={} ",campaignId,communicationId,response); + } +} diff --git a/src/main/java/fr/insee/protools/backend/service/meshuggah/MeshuggahUtils.java b/src/main/java/fr/insee/protools/backend/service/meshuggah/MeshuggahUtils.java deleted file mode 100644 index ae5e4d7c..00000000 --- a/src/main/java/fr/insee/protools/backend/service/meshuggah/MeshuggahUtils.java +++ /dev/null @@ -1,154 +0,0 @@ -package fr.insee.protools.backend.service.meshuggah; - -import com.fasterxml.jackson.databind.JsonNode; -import fr.insee.protools.backend.service.context.exception.BadContextIncorrectBPMNError; -import fr.insee.protools.backend.dto.meshuggah.MeshuggahComDetails; - -import java.util.Set; - -import static fr.insee.protools.backend.service.context.ContextConstants.*; - -public class MeshuggahUtils { - - static MeshuggahComDetails computeMeshuggahComDetails(String campagneId, Long partitionId, JsonNode communicationNode) { - String ctxMoyenCommunication = communicationNode.path(CTX_PARTITION_COMMUNICATION_MOYEN).asText(); - String ctxPhase = communicationNode.path(CTX_PARTITION_COMMUNICATION_PHASE).asText(); - String ctxTypeModele = communicationNode.path(CTX_PARTITION_COMMUNICATION_TYPE_MODELE).asText(); - String ctxMode = communicationNode.path(CTX_PARTITION_COMMUNICATION_MODE).asText(); - String ctxProtocol = communicationNode.path(CTX_PARTITION_COMMUNICATION_PROTOCOLE).asText(); - boolean meshAvecQuestionnaire = communicationNode.path(CTX_PARTITION_COMMUNICATION_AVEC_QUESTIONNAIRE_PAPIER).asBoolean(); - return MeshuggahComDetails.builder().campaignId(campagneId).partitioningId(String.valueOf(partitionId)).medium(MeshuggahUtils.MediumEnum.fromCtxValue(ctxMoyenCommunication).meshuggahValue).phase(MeshuggahUtils.PhaseEnum.fromCtxValue(ctxPhase).meshuggahValue).operation(MeshuggahUtils.TypeModeleEnum.fromCtxValue(ctxTypeModele).meshuggahValue).mode(MeshuggahUtils.ModeEnum.fromCtxValue(ctxMode).meshuggahValue).protocol(MeshuggahUtils.ProtocolEnum.fromCtxValue(ctxProtocol).meshuggahValue).avecQuestionnaire(meshAvecQuestionnaire).build(); - } - - - public static Set getCommunicationRequiredFields() { - return Set.of(CTX_PARTITION_COMMUNICATION_MOYEN, CTX_PARTITION_COMMUNICATION_PHASE, CTX_PARTITION_COMMUNICATION_TYPE_MODELE, CTX_PARTITION_COMMUNICATION_MODE, CTX_PARTITION_COMMUNICATION_PROTOCOLE, CTX_PARTITION_COMMUNICATION_AVEC_QUESTIONNAIRE_PAPIER); - } - - //Search for a communication in the contexte. - public static JsonNode getCommunication(JsonNode partitionNode, MeshuggahUtils.MediumEnum medium, MeshuggahUtils.PhaseEnum phase) { - JsonNode communicationNode = null; - for (JsonNode subNode : partitionNode.path(CTX_PARTITION_COMMUNICATIONS)) { - if (subNode.has(CTX_PARTITION_COMMUNICATION_MOYEN) && subNode.has(CTX_PARTITION_COMMUNICATION_PHASE) && subNode.get(CTX_PARTITION_COMMUNICATION_MOYEN).asText().equalsIgnoreCase(medium.ctxValue) && subNode.get(CTX_PARTITION_COMMUNICATION_PHASE).asText().equalsIgnoreCase(phase.ctxValue)) { - communicationNode = subNode; - break; - } - } - if (communicationNode == null) { - throw new BadContextIncorrectBPMNError(String.format("Communication medium=[%s] - phase=[%s] not found ", medium, phase)); - } - return communicationNode; - } - - enum MediumEnum { - - COURRIER("courrier", "COURRIER"), MAIL("mail", "EMAIL"); - - final String meshuggahValue; - final String ctxValue; - - MediumEnum(String ctxValue, String meshuggahValue) { - this.meshuggahValue = meshuggahValue; - this.ctxValue = ctxValue; - } - - public static MediumEnum fromCtxValue(String ctxValue) { - for (var c : values()) { - if (c.ctxValue.equalsIgnoreCase(ctxValue)) { - return c; - } - } - throw new IllegalArgumentException(ctxValue); - } - } - - enum PhaseEnum { - - OUVERTURE("ouverture", "OUVERTURE"), RELANCE("relance", "RELANCE"), PONCTUEL("ponctuel", "PONCTUEL"); - - final String meshuggahValue; - final String ctxValue; - - PhaseEnum(String ctxValue, String meshuggahValue) { - this.meshuggahValue = meshuggahValue; - this.ctxValue = ctxValue; - } - - public static PhaseEnum fromCtxValue(String ctxValue) { - for (var c : values()) { - if (c.ctxValue.equals(ctxValue)) { - return c; - } - } - throw new IllegalArgumentException(ctxValue); - } - } - - enum TypeModeleEnum { - - OUVERTURE("ouverture", "OUVERTURE"), RELANCE("relance", "RELANCE"), RELANCE_LIBRE("relance_libre", "RELANCE_LIBRE"); - - final String meshuggahValue; - final String ctxValue; - - TypeModeleEnum(String ctxValue, String meshuggahValue) { - this.meshuggahValue = meshuggahValue; - this.ctxValue = ctxValue; - } - - public static TypeModeleEnum fromCtxValue(String ctxValue) { - for (var c : values()) { - if (c.ctxValue.equals(ctxValue)) { - return c; - } - } - throw new IllegalArgumentException(ctxValue); - } - } - - enum ModeEnum { - - FAF("faf", "FAF"), TEL("tel", "TEL"), WEB("web", "WEB"); - - final String meshuggahValue; - final String ctxValue; - - ModeEnum(String ctxValue, String meshuggahValue) { - this.meshuggahValue = meshuggahValue; - this.ctxValue = ctxValue; - } - - public static ModeEnum fromCtxValue(String ctxValue) { - for (var c : values()) { - if (c.ctxValue.equals(ctxValue)) { - return c; - } - } - throw new IllegalArgumentException(ctxValue); - } - } - - enum ProtocolEnum { - - SEQ_WT("sequentiel web tel faf", "SEQ_WT"), SEQ_TW("sequentiel tel web", "SEQ_TW"), PANEL("panel", "PANEL"), DEFAULT("null", "DEFAULT"); - - final String meshuggahValue; - final String ctxValue; - - ProtocolEnum(String ctxValue, String meshuggahValue) { - this.meshuggahValue = meshuggahValue; - this.ctxValue = ctxValue; - } - - public static ProtocolEnum fromCtxValue(String ctxValue) { - for (var c : values()) { - if (c.ctxValue.equals(ctxValue)) { - return c; - } - } - return DEFAULT; - } - } - - -} diff --git a/src/main/java/fr/insee/protools/backend/service/meshuggah/delegate/MeshuggahCreateContextTaskREST.java b/src/main/java/fr/insee/protools/backend/service/meshuggah/delegate/MeshuggahCreateContextTaskREST.java new file mode 100644 index 00000000..1a84040a --- /dev/null +++ b/src/main/java/fr/insee/protools/backend/service/meshuggah/delegate/MeshuggahCreateContextTaskREST.java @@ -0,0 +1,34 @@ +package fr.insee.protools.backend.service.meshuggah.delegate; + +import com.fasterxml.jackson.databind.JsonNode; +import fr.insee.protools.backend.dto.ContexteProcessus; +import fr.insee.protools.backend.service.DelegateContextVerifier; +import fr.insee.protools.backend.service.context.IContextService; +import fr.insee.protools.backend.service.meshuggah.IMeshuggahService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.flowable.engine.delegate.DelegateExecution; +import org.flowable.engine.delegate.JavaDelegate; +import org.springframework.stereotype.Component; + +@Slf4j +@RequiredArgsConstructor +@Component +public class MeshuggahCreateContextTaskREST implements JavaDelegate, DelegateContextVerifier { + private final IContextService protoolsContext; + private final IMeshuggahService service; + + @Override + public void execute(DelegateExecution execution) { + log.info("ProcessInstanceId={} begin",execution.getProcessInstanceId()); + JsonNode contextRootNode = protoolsContext.getContextJsonNodeByProcessInstance(execution.getProcessInstanceId()); + ContexteProcessus contexteProcessus = protoolsContext.getContextDtoByProcessInstance(execution.getProcessInstanceId()); + + checkContextOrThrow(log,execution.getProcessInstanceId(), contexteProcessus); + String campainId = contexteProcessus.getId().toString(); + + service.postContext(campainId,contextRootNode); + + log.info("ProcessInstanceId={} end",execution.getProcessInstanceId()); + } +} diff --git a/src/main/java/fr/insee/protools/backend/service/meshuggah/delegate/MeshuggahSendCommunicationForInterrogationListTaskREST.java b/src/main/java/fr/insee/protools/backend/service/meshuggah/delegate/MeshuggahSendCommunicationForInterrogationListTaskREST.java new file mode 100644 index 00000000..7b64072f --- /dev/null +++ b/src/main/java/fr/insee/protools/backend/service/meshuggah/delegate/MeshuggahSendCommunicationForInterrogationListTaskREST.java @@ -0,0 +1,42 @@ +package fr.insee.protools.backend.service.meshuggah.delegate; + +import com.fasterxml.jackson.databind.JsonNode; +import fr.insee.protools.backend.dto.ContexteProcessus; +import fr.insee.protools.backend.service.context.IContextService; +import fr.insee.protools.backend.service.meshuggah.IMeshuggahService; +import fr.insee.protools.backend.service.utils.FlowableVariableUtils; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.flowable.engine.delegate.DelegateExecution; +import org.flowable.engine.delegate.JavaDelegate; +import org.springframework.stereotype.Component; + +import java.util.List; + +import static fr.insee.protools.backend.service.FlowableVariableNameConstants.VARNAME_CURRENT_COMMUNICATION_ID; +import static fr.insee.protools.backend.service.FlowableVariableNameConstants.VARNAME_REM_INTERRO_LIST; + +@Component +@RequiredArgsConstructor +@Slf4j +public class MeshuggahSendCommunicationForInterrogationListTaskREST implements JavaDelegate { + + private final IMeshuggahService meshuggahService; + private final IContextService protoolsContext; + + @Override + public void execute(DelegateExecution execution) { + ContexteProcessus context = protoolsContext.getContextDtoByProcessInstance(execution.getProcessInstanceId()); + List interroList = FlowableVariableUtils.getVariableOrThrow(execution, VARNAME_REM_INTERRO_LIST, List.class); + String currentCommunicationId = FlowableVariableUtils.getVariableOrThrow(execution, VARNAME_CURRENT_COMMUNICATION_ID, String.class); + + log.info("ProcessInstanceId={} - currentCommunicationId={} - begin", + execution.getProcessInstanceId(), currentCommunicationId); + + meshuggahService.postCommunicationRequest(String.valueOf(context.getId()), currentCommunicationId, interroList); + + log.info("ProcessInstanceId={} - currentCommunicationId={} - end", + execution.getProcessInstanceId(), currentCommunicationId); + } +} + diff --git a/src/main/java/fr/insee/protools/backend/service/nomenclature/NomenclatureFromStaticWebsiteServiceImpl.java b/src/main/java/fr/insee/protools/backend/service/nomenclature/NomenclatureFromStaticWebsiteServiceImpl.java deleted file mode 100644 index 4a1e1319..00000000 --- a/src/main/java/fr/insee/protools/backend/service/nomenclature/NomenclatureFromStaticWebsiteServiceImpl.java +++ /dev/null @@ -1,46 +0,0 @@ -package fr.insee.protools.backend.service.nomenclature; - -import fr.insee.protools.backend.service.context.exception.BadContextIncorrectBPMNError; -import fr.insee.protools.backend.webclient.WebClientHelper; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Service; - -import java.net.URI; -import java.net.URISyntaxException; - -/** - * This service retrieves the nomenclatures from a static website based on a property uri - */ -@Service -@Slf4j -@RequiredArgsConstructor -public class NomenclatureFromStaticWebsiteServiceImpl implements NomenclatureService{ - - //TODO : expose mandatory configuration? - @Value("${fr.insee.protools.nomenclature.uri}") - private String nomenclatureUri; - - private final WebClientHelper webClientHelper; - - @Override - public String getNomenclatureContent(String nomenclatureId, String folderPath) { - log.debug("Get Naming Model Value for nomenclatureId={}", nomenclatureId); - String uri; - String fullPath=nomenclatureUri+ "/" +folderPath+ "/"+nomenclatureId + ".json"; - try { - uri = new URI(fullPath).normalize().toString(); - } catch (URISyntaxException e) { - throw new BadContextIncorrectBPMNError(String.format("nomenclatureId=[%s] - folderPath=[%s] : fullPath=[%s] cannot be parsed: Error=[%s]" - ,nomenclatureId,folderPath,fullPath, e.getMessage())); - } - return - webClientHelper.getWebClientForFile() - .get() - .uri(uri) - .retrieve() - .bodyToMono(String.class) - .block(); - } -} diff --git a/src/main/java/fr/insee/protools/backend/service/nomenclature/NomenclatureService.java b/src/main/java/fr/insee/protools/backend/service/nomenclature/NomenclatureService.java deleted file mode 100644 index c3230836..00000000 --- a/src/main/java/fr/insee/protools/backend/service/nomenclature/NomenclatureService.java +++ /dev/null @@ -1,13 +0,0 @@ -package fr.insee.protools.backend.service.nomenclature; - -public interface NomenclatureService { - - /** - * Returns the nomenclature associated with stored at - * @param nomenclatureId - * @param folderPath - * @return the nomenclature content retrieved from external source - */ - String getNomenclatureContent(String nomenclatureId,String folderPath); - -} diff --git a/src/main/java/fr/insee/protools/backend/service/platine/delegate/PlatinePilotageCreateContextTask.java b/src/main/java/fr/insee/protools/backend/service/platine/delegate/PlatinePilotageCreateContextTask.java deleted file mode 100644 index dc1837dd..00000000 --- a/src/main/java/fr/insee/protools/backend/service/platine/delegate/PlatinePilotageCreateContextTask.java +++ /dev/null @@ -1,223 +0,0 @@ -package fr.insee.protools.backend.service.platine.delegate; - -import com.fasterxml.jackson.databind.JsonNode; -import fr.insee.protools.backend.service.DelegateContextVerifier; -import fr.insee.protools.backend.service.context.ContextService; -import fr.insee.protools.backend.service.platine.pilotage.PlatinePilotageService; -import fr.insee.protools.backend.service.platine.pilotage.metadata.*; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.EnumUtils; -import org.flowable.engine.delegate.DelegateExecution; -import org.flowable.engine.delegate.JavaDelegate; -import org.springframework.stereotype.Component; - -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; - -import static fr.insee.protools.backend.service.context.ContextConstants.*; -import static fr.insee.protools.backend.service.platine.utils.PlatineHelper.computePilotagePartitionID; - -@Slf4j -@Component -@RequiredArgsConstructor -public class PlatinePilotageCreateContextTask implements JavaDelegate, DelegateContextVerifier { - - private final ContextService protoolsContext; - private final PlatinePilotageService platinePilotageService; - @Override - public void execute(DelegateExecution execution) { - log.info("ProcessInstanceId={} begin",execution.getProcessInstanceId()); - JsonNode contextRootNode = protoolsContext.getContextByProcessInstance(execution.getProcessInstanceId()); - checkContextOrThrow(log,execution.getProcessInstanceId(), contextRootNode); - var dtos = computeMetadataDtoForEachPartition(contextRootNode); - - for (MetadataDto dto: dtos) { - platinePilotageService.putMetadata(dto.getPartitioningDto().getId(),dto); - } - - log.info("ProcessInstanceId={} end",execution.getProcessInstanceId()); - - } - @Override - public Set getContextErrors(JsonNode contextRootNode) { - if(contextRootNode==null){ - return Set.of("Context is missing"); - } - Set results=new HashSet<>(); - Set requiredNodes = - Set.of( - //Global & Campaign - CTX_METADONNEES, CTX_CAMPAGNE_ID, CTX_CAMPAGNE_LABEL, CTX_PARTITIONS - ); - Set requiredMetadonnees = - //For source/Serie - Set.of(//Campaign - CTX_META_OPERATION_ID, CTX_META_SERIE_ID,CTX_META_ANNEE,CTX_META_PERIODE,CTX_META_PERIODICITE, - CTX_META_SERIE_LABEL_LONG, CTX_META_SERIE_LABEL_COURT, CTX_META_PORTAIL_MES_ENQUETE_OPERATION, - //For support - CTX_META_ASSISTANCE_NIVO2_ID, CTX_META_ASSISTANCE_NIVO2_LABEL, CTX_META_ASSISTANCE_NIVO2_TEL, CTX_META_ASSISTANCE_NIVO2_MAIL, CTX_META_ASSISTANCE_NIVO2_PAYS, - CTX_META_ASSISTANCE_NIVO2_NUMERO_VOIE, CTX_META_ASSISTANCE_NIVO2_NOM_VOIE, CTX_META_ASSISTANCE_NIVO2_COMMUNE, CTX_META_ASSISTANCE_NIVO2_CODE_POSTAL, - //For Owner - CTX_META_PROPRIETAIRE_ID, CTX_META_PROPRIETAIRE_LABEL, CTX_META_MINISTERE_TUTELLE, CTX_META_PROPRIETAIRE_LOGO, - //For Source/serie - //For Survey - CTX_META_LABEL_LONG_OPERATION, CTX_META_LABEL_COURT_OPERATION, CTX_META_OBJECTIFS_LONGS, CTX_META_OBJECTIFS_COURTS, - CTX_META_NUMERO_VISA, CTX_META_CNIS_URL, CTX_META_DIFFUSION_URL, CTX_META_NOTICE_URL, CTX_META_SPECIMENT_URL - ); - Set requiredPartition = - Set.of(CTX_PARTITION_ID,CTX_PARTITION_LABEL, CTX_PARTITION_DATE_DEBUT_COLLECTE, CTX_PARTITION_DATE_FIN_COLLECTE, CTX_PARTITION_DATE_RETOUR); - results.addAll(DelegateContextVerifier.computeMissingChildrenMessages(requiredNodes,contextRootNode,getClass())); - results.addAll(DelegateContextVerifier.computeMissingChildrenMessages(requiredMetadonnees,contextRootNode.path(CTX_METADONNEES),getClass())); - - var partitionIterator =contextRootNode.path(CTX_PARTITIONS).elements(); - //Partitions - while (partitionIterator.hasNext()) { - var partitionNode = partitionIterator.next(); - results.addAll(DelegateContextVerifier.computeMissingChildrenMessages(requiredPartition,partitionNode,getClass())); - } - - - //Check value of PERIODE Enum - String periode = contextRootNode.path(CTX_METADONNEES).path(CTX_META_PERIODE).asText(); - if(! EnumUtils.isValidEnumIgnoreCase(PeriodEnum.class, periode)){ - results.add(DelegateContextVerifier.computeIncorrectEnumMessage(CTX_META_PERIODE,periode,Arrays.toString(PeriodEnum.values()),getClass())); - } - //Check value of PERIODICITE Enum - String periodicite = contextRootNode.path(CTX_METADONNEES).path(CTX_META_PERIODICITE).asText(); - if(! EnumUtils.isValidEnumIgnoreCase(PeriodicityEnum.class, periodicite)){ - results.add(DelegateContextVerifier.computeIncorrectEnumMessage(CTX_META_PERIODICITE,periodicite,Arrays.toString(PeriodicityEnum.values()),getClass())); - } - return results; - } - - private static Set computeMetadataDtoForEachPartition(JsonNode contextRootNode) { - - Set result = new HashSet<>(); - String campainId = contextRootNode.path(CTX_CAMPAGNE_ID).asText(); - //Get the list of partitions - var partitionIterator =contextRootNode.path(CTX_PARTITIONS).elements(); - - //These parts are always the same - CampaignDto campaignDto = computeCampaignDto(contextRootNode); - SurveyDto surveyDto = computeSurveyDto(contextRootNode); - SourceDto sourceDto = computeSourceDto(contextRootNode); - OwnerDto ownerDto = computeOwnerDto(contextRootNode); - SupportDto supportDto = computeSupportDto(contextRootNode); - - - //Partition part - while (partitionIterator.hasNext()) { - var partitionNode = partitionIterator.next(); - PartitioningDto partitioningDto = computePartitioningDto(partitionNode, campainId); - MetadataDto metadataDto = new MetadataDto(partitioningDto, campaignDto, surveyDto, sourceDto, ownerDto, supportDto); - result.add(metadataDto); - } - return result; - } - - private static SupportDto computeSupportDto(JsonNode contextRootNode) { - JsonNode medatadata = contextRootNode.path(CTX_METADONNEES); - - return SupportDto.builder() - .id(medatadata.path(CTX_META_ASSISTANCE_NIVO2_ID).asText()) - .label(medatadata.path(CTX_META_ASSISTANCE_NIVO2_LABEL).asText()) - .phoneNumber(medatadata.path(CTX_META_ASSISTANCE_NIVO2_TEL).asText()) - .mail(medatadata.path(CTX_META_ASSISTANCE_NIVO2_MAIL).asText()) - .countryName(medatadata.path(CTX_META_ASSISTANCE_NIVO2_PAYS).asText()) - .streetNumber(medatadata.path(CTX_META_ASSISTANCE_NIVO2_NUMERO_VOIE).asText()) - .streetName(medatadata.path(CTX_META_ASSISTANCE_NIVO2_NOM_VOIE).asText()) - .city(medatadata.path(CTX_META_ASSISTANCE_NIVO2_COMMUNE).asText()) - .zipCode(medatadata.path(CTX_META_ASSISTANCE_NIVO2_CODE_POSTAL).asText()) - .build(); - } - - private static OwnerDto computeOwnerDto(JsonNode contextRootNode) { - String idProprietaire = contextRootNode.path(CTX_METADONNEES).path(CTX_META_PROPRIETAIRE_ID).asText(); - String labelProprietaire = contextRootNode.path(CTX_METADONNEES).path(CTX_META_PROPRIETAIRE_LABEL).asText(); - String ministereTutelle = contextRootNode.path(CTX_METADONNEES).path(CTX_META_MINISTERE_TUTELLE).asText(); - String logoProprietaire = contextRootNode.path(CTX_METADONNEES).path(CTX_META_PROPRIETAIRE_LOGO).asText(); - return OwnerDto.builder() - .id(idProprietaire) - .label(labelProprietaire) - .ministry(ministereTutelle) - .logo(logoProprietaire) - .build(); - } - - private static SourceDto computeSourceDto(JsonNode contextRootNode) { - String serieId = contextRootNode.path(CTX_METADONNEES).path(CTX_META_SERIE_ID).asText(); - String labelLongSerie = contextRootNode.path(CTX_METADONNEES).path(CTX_META_SERIE_LABEL_LONG).asText(); - String labelCourtSerie = contextRootNode.path(CTX_METADONNEES).path(CTX_META_SERIE_LABEL_COURT).asText(); - PeriodicityEnum periodicite = PeriodicityEnum.valueOf(contextRootNode.path(CTX_METADONNEES).path(CTX_META_PERIODICITE).asText()); - boolean mandatoryMySurveys = contextRootNode.path(CTX_METADONNEES).path(CTX_META_PORTAIL_MES_ENQUETE_OPERATION).asBoolean(); - - return SourceDto.builder() - .id(serieId) - .longWording(labelLongSerie) - .shortWording(labelCourtSerie) - .periodicity(periodicite) - .mandatoryMySurveys(mandatoryMySurveys) - .build(); - } - - private static SurveyDto computeSurveyDto(JsonNode contextRootNode) { - JsonNode medatadata = contextRootNode.path(CTX_METADONNEES); - String id = medatadata.path(CTX_META_OPERATION_ID).asText(); - String serieId = medatadata.path(CTX_META_SERIE_ID).asText(); - int year = medatadata.path(CTX_META_ANNEE).asInt(); - String labelLongOperation = medatadata.path(CTX_META_LABEL_LONG_OPERATION).asText(); - String labelCourtOperation = medatadata.path(CTX_META_LABEL_COURT_OPERATION).asText(); - String labelLongObjectifs = medatadata.path(CTX_META_OBJECTIFS_LONGS).asText(); - String labelCourtObjectifs = medatadata.path(CTX_META_OBJECTIFS_COURTS).asText(); - String numeroVisa = medatadata.path(CTX_META_NUMERO_VISA).asText(); - String cnisUrl = medatadata.path(CTX_META_CNIS_URL).asText(); - String diffusionUrl = medatadata.path(CTX_META_DIFFUSION_URL).asText(); - String noticeUrl = medatadata.path(CTX_META_NOTICE_URL).asText(); - String specimenUrl = medatadata.path(CTX_META_SPECIMENT_URL).asText(); - return SurveyDto.builder() - .id(id) - .sourceId(serieId) - .year(year) - .sampleSize(0) - .longWording(labelLongOperation) - .shortWording(labelCourtOperation) - .shortObjectives(labelCourtObjectifs) - .longObjectives(labelLongObjectifs) - .visaNumber(numeroVisa) - .cnisUrl(cnisUrl) - .diffusionUrl(diffusionUrl) - .noticeUrl(noticeUrl) - .specimenUrl(specimenUrl) - .communication("") - .build(); - } - - - private static PartitioningDto computePartitioningDto(JsonNode partitionNode, String campaignId) { - return PartitioningDto.builder() - .id(computePilotagePartitionID(campaignId,partitionNode.path(CTX_PARTITION_ID).asLong())) - .campaignId(campaignId) - .label(partitionNode.path(CTX_PARTITION_LABEL).asText()) - .openingDate(partitionNode.path(CTX_PARTITION_DATE_DEBUT_COLLECTE).asText()) - .closingDate(partitionNode.path(CTX_PARTITION_DATE_FIN_COLLECTE).asText()) - .returnDate(partitionNode.path(CTX_PARTITION_DATE_RETOUR).asText()) - .build(); - } - - private static CampaignDto computeCampaignDto(JsonNode contextRootNode) { - String campaignId = contextRootNode.path(CTX_CAMPAGNE_ID).asText(); - String serieId = contextRootNode.path(CTX_METADONNEES).path(CTX_META_SERIE_ID).asText(); - int year = contextRootNode.path(CTX_METADONNEES).path(CTX_META_ANNEE).asInt(); - String campaignLabel = contextRootNode.path(CTX_CAMPAGNE_LABEL).asText(); - PeriodEnum period = PeriodEnum.valueOf(contextRootNode.path(CTX_METADONNEES).path(CTX_META_PERIODE).asText()); - return CampaignDto.builder() - .id(campaignId) - .surveyId(serieId) - .year(year) - .campaignWording(campaignLabel) - .period(period) - .build(); - } -} \ No newline at end of file diff --git a/src/main/java/fr/insee/protools/backend/service/platine/delegate/PlatinePilotageCreateSurveyUnitTask.java b/src/main/java/fr/insee/protools/backend/service/platine/delegate/PlatinePilotageCreateSurveyUnitTask.java deleted file mode 100644 index 7ba7ff32..00000000 --- a/src/main/java/fr/insee/protools/backend/service/platine/delegate/PlatinePilotageCreateSurveyUnitTask.java +++ /dev/null @@ -1,194 +0,0 @@ -package fr.insee.protools.backend.service.platine.delegate; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import fr.insee.protools.backend.dto.platine.pilotage.PlatineAddressDto; -import fr.insee.protools.backend.dto.platine.pilotage.PlatinePilotageGenderType; -import fr.insee.protools.backend.dto.platine.pilotage.query.ContactAccreditationDto; -import fr.insee.protools.backend.dto.platine.pilotage.query.QuestioningWebclientDto; -import fr.insee.protools.backend.dto.platine.pilotage.questioning.PlatineQuestioningSurveyUnitDto; -import fr.insee.protools.backend.dto.rem.*; -import fr.insee.protools.backend.service.DelegateContextVerifier; -import fr.insee.protools.backend.service.context.ContextService; -import fr.insee.protools.backend.service.context.enums.CampaignContextEnum; -import fr.insee.protools.backend.service.context.enums.PartitionTypeEchantillon; -import fr.insee.protools.backend.service.platine.pilotage.PlatinePilotageService; -import fr.insee.protools.backend.service.platine.utils.PlatineHelper; -import fr.insee.protools.backend.service.rem.RemDtoUtils; -import fr.insee.protools.backend.service.utils.FlowableVariableUtils; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.EnumUtils; -import org.flowable.engine.delegate.DelegateExecution; -import org.flowable.engine.delegate.JavaDelegate; -import org.springframework.beans.BeanUtils; -import org.springframework.stereotype.Component; - -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import static com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES; -import static fr.insee.protools.backend.service.FlowableVariableNameConstants.*; -import static fr.insee.protools.backend.service.context.ContextConstants.*; -import static fr.insee.protools.backend.service.utils.ContextUtils.getCurrentPartitionNode; - -@Slf4j -@Component -@RequiredArgsConstructor -public class PlatinePilotageCreateSurveyUnitTask implements JavaDelegate, DelegateContextVerifier { - - private static final ObjectMapper objectMapper = new ObjectMapper().configure(FAIL_ON_UNKNOWN_PROPERTIES,false); - - private final ContextService protoolsContext; - private final PlatinePilotageService platinePilotageService; - - @Override - public void execute(DelegateExecution execution) { - JsonNode contextRootNode = protoolsContext.getContextByProcessInstance(execution.getProcessInstanceId()); - checkContextOrThrow(log,execution.getProcessInstanceId(), contextRootNode); - String campainId = contextRootNode.path(CTX_CAMPAGNE_ID).asText(); - Long currentPartitionId = FlowableVariableUtils.getVariableOrThrow(execution,VARNAME_CURRENT_PARTITION_ID, Long.class); - JsonNode remSUNode = FlowableVariableUtils.getVariableOrThrow(execution,VARNAME_REM_SURVEY_UNIT, JsonNode.class); - String idInternaute = FlowableVariableUtils.getVariableOrThrow(execution, VARNAME_DIRECTORYACCESS_ID_CONTACT, String.class); - JsonNode currentPartitionNode = getCurrentPartitionNode(contextRootNode, currentPartitionId); - - //Create the platine DTO object - QuestioningWebclientDto dto = computeQuestioningWebclientDto(remSUNode,currentPartitionNode,idInternaute,campainId); - - log.info("ProcessInstanceId={} campainId={} - currentPartitionId={} - remSUNode.id={} ", - execution.getProcessInstanceId(), campainId,currentPartitionId,dto.getSurveyUnit().getIdSu()); - //Call service - platinePilotageService.putQuestionings(dto); - } - - private static QuestioningWebclientDto computeQuestioningWebclientDto(JsonNode remSUNode, JsonNode currentPartitionNode,String idInternaute, String idCampagne) { - REMSurveyUnitDto remSurveyUnitDto=PlatineHelper.parseRemSUNode(objectMapper,VARNAME_REM_SURVEY_UNIT,remSUNode); - boolean isLogement = currentPartitionNode.path(CTX_PARTITION_TYPE_ECHANTILLON).textValue().equalsIgnoreCase(PartitionTypeEchantillon.LOGEMENT.getAsString()); - PersonDto contact = RemDtoUtils.findContact(remSUNode, remSurveyUnitDto, isLogement); - - PlatineAddressDto platineAdress = computePlatineAdress(remSurveyUnitDto.getAddress()); - ContactAccreditationDto platineContact = convertREMPersonToPlatineContact(idInternaute, platineAdress, contact); - - return - QuestioningWebclientDto.builder() - .idPartitioning(PlatineHelper.computePilotagePartitionID(idCampagne,currentPartitionNode.path(CTX_PARTITION_ID).asLong())) - .modelName(currentPartitionNode.path(CTX_PARTITION_QUESTIONNAIRE_MODEL).asText()) - .surveyUnit(computeSurveyUnitDto(remSurveyUnitDto)) - .contacts(List.of(platineContact)) - .build(); - } - - - - private static PlatineQuestioningSurveyUnitDto computeSurveyUnitDto(REMSurveyUnitDto remSurveyUnitDto) { - - return PlatineQuestioningSurveyUnitDto.builder() - .idSu(remSurveyUnitDto.getRepositoryId().toString()) - .identificationCode("") - .identificationName("") - .address(computePlatineAdress(remSurveyUnitDto.getAddress())) - .build(); - } - - @Override - public Set getContextErrors(JsonNode contextRootNode) { - if(contextRootNode==null){ - return Set.of("Context is missing"); - } - Set results=new HashSet<>(); - Set requiredNodes = - Set.of( - //Global & Campaign - CTX_CAMPAGNE_ID,CTX_CAMPAGNE_CONTEXTE, CTX_PARTITIONS - ); - Set requiredPartition = - Set.of(CTX_PARTITION_ID,CTX_PARTITION_QUESTIONNAIRE_MODEL, CTX_PARTITION_TYPE_ECHANTILLON); - - - results.addAll(DelegateContextVerifier.computeMissingChildrenMessages(requiredNodes,contextRootNode,getClass())); - if (!contextRootNode.path(CTX_CAMPAGNE_CONTEXTE).asText().equalsIgnoreCase(CampaignContextEnum.HOUSEHOLD.getAsString())) { - results.add(DelegateContextVerifier.computeIncorrectMessage(CTX_CAMPAGNE_CONTEXTE,"contexte for platine can only be "+CampaignContextEnum.HOUSEHOLD,getClass())); - } - - //Maybe one day we will have partitions for platine and partitions for sabiane and we will only validate the platine ones - //Partitions - var partitionIterator =contextRootNode.path(CTX_PARTITIONS).elements(); - while (partitionIterator.hasNext()) { - var partitionNode = partitionIterator.next(); - results.addAll(DelegateContextVerifier.computeMissingChildrenMessages(requiredPartition,partitionNode,getClass())); - - //Check value of Enum - String enumVal = partitionNode.path(CTX_PARTITION_TYPE_ECHANTILLON).asText(); - if(! EnumUtils.isValidEnumIgnoreCase(PartitionTypeEchantillon.class, enumVal)){ - results.add(DelegateContextVerifier.computeIncorrectEnumMessage(CTX_PARTITION_TYPE_ECHANTILLON,enumVal,Arrays.toString(PartitionTypeEchantillon.values()),getClass())); - } - } - return results; - } - - /** - * Compute the lastname to send to platine. - * @param lastname from rem - * @param birthname from rem - * @return the computed platine last name - */ - protected static String getPlatineLastname(String lastname, String birthname){ - if(lastname!=null) - return lastname; - else if(birthname!=null) - return birthname; - return ""; - } - - private static ContactAccreditationDto convertREMPersonToPlatineContact(String idInternaute, PlatineAddressDto platineAdress, PersonDto remPersonDto) { - //If lastname is null then we use birthname - String platineName = getPlatineLastname(remPersonDto.getLastName(),remPersonDto.getBirthName()); - return ContactAccreditationDto.builder() - .identifier(idInternaute) - .externalId(remPersonDto.getExternalId()) - .function("") - .lastName(platineName) - .firstName(remPersonDto.getFirstName()) - .isMain(true) - .civility(convertREMGenderToPlatineCivility(remPersonDto.getGender()).getLabel()) - //Get favorite phone/mail ; if no favorite get the first of the list ; else empty - .email(remPersonDto.getEmails().stream() - .filter(EmailDto::getFavorite) - .findFirst() - .orElse(remPersonDto.getEmails().stream().findFirst().orElse(new EmailDto())) - .getMailAddress()) - - .phone( - remPersonDto.getPhoneNumbers().stream() - .filter(PhoneNumberDto::getFavorite) - .findFirst() - .orElse(remPersonDto.getPhoneNumbers().stream().findFirst().orElse(new PhoneNumberDto())) - .getNumber()) - .address(platineAdress) - .build(); - } - - static PlatinePilotageGenderType convertREMGenderToPlatineCivility(String remGender) { - if(remGender==null) - return PlatinePilotageGenderType.Undefined; - return switch (remGender) { - case "2": - yield PlatinePilotageGenderType.Female; - case "1" : - yield PlatinePilotageGenderType.Male; - default: - yield PlatinePilotageGenderType.Undefined; - }; - } - - private static PlatineAddressDto computePlatineAdress(REMAddressDto remAddressDto) { - //The REM REMAddressDto and Platine PlatineQuestioningSurveyUnitDto are identical - //I'll use the copyProperty to recopy identical members - var platineAdresse = BeanUtils.instantiateClass(PlatineAddressDto.class); - BeanUtils.copyProperties(remAddressDto, platineAdresse); - return platineAdresse; - } - -} diff --git a/src/main/java/fr/insee/protools/backend/service/platine/delegate/PlatinePilotageGetSUContactTask.java b/src/main/java/fr/insee/protools/backend/service/platine/delegate/PlatinePilotageGetSUContactTask.java deleted file mode 100644 index 1983ed85..00000000 --- a/src/main/java/fr/insee/protools/backend/service/platine/delegate/PlatinePilotageGetSUContactTask.java +++ /dev/null @@ -1,59 +0,0 @@ -package fr.insee.protools.backend.service.platine.delegate; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import fr.insee.protools.backend.dto.platine.pilotage.contact.PlatineContactDto; -import fr.insee.protools.backend.service.DelegateContextVerifier; -import fr.insee.protools.backend.service.context.ContextService; -import fr.insee.protools.backend.service.platine.pilotage.PlatinePilotageService; -import fr.insee.protools.backend.service.utils.FlowableVariableUtils; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.flowable.engine.delegate.DelegateExecution; -import org.flowable.engine.delegate.JavaDelegate; -import org.springframework.stereotype.Component; - -import java.util.Set; - -import static com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES; -import static fr.insee.protools.backend.service.FlowableVariableNameConstants.*; -import static fr.insee.protools.backend.service.context.ContextConstants.CTX_CAMPAGNE_ID; -import static fr.insee.protools.backend.service.platine.utils.PlatineHelper.computePilotagePartitionID; - -@Slf4j -@Component -@RequiredArgsConstructor -public class PlatinePilotageGetSUContactTask implements JavaDelegate, DelegateContextVerifier { - - private static final ObjectMapper objectMapper = new ObjectMapper().configure(FAIL_ON_UNKNOWN_PROPERTIES,false); - private final ContextService protoolsContext; - private final PlatinePilotageService platinePilotageService; - - @Override - public void execute(DelegateExecution execution) { - //Contexte - JsonNode contextRootNode = protoolsContext.getContextByProcessInstance(execution.getProcessInstanceId()); - checkContextOrThrow(log,execution.getProcessInstanceId(), contextRootNode); - String campainId = contextRootNode.path(CTX_CAMPAGNE_ID).asText(); - //Process variables - Long suId = FlowableVariableUtils.getVariableOrThrow(execution, VARNAME_REM_SURVEY_UNIT_IDENTIFIER, Long.class); - Long currentPartitionId = FlowableVariableUtils.getVariableOrThrow(execution, VARNAME_CURRENT_PARTITION_ID, Long.class); - log.info("ProcessInstanceId={} - currentPartitionId={} suId={} ",execution.getProcessInstanceId(), currentPartitionId,suId); - - //Get the Contact details from platine pilotage - String platinePartitionId = computePilotagePartitionID(campainId,currentPartitionId); - PlatineContactDto platineContactDto = platinePilotageService.getSUMainContact(suId, platinePartitionId); - - //STORE this info - execution.getParent().setVariableLocal(VARNAME_PLATINE_CONTACT, objectMapper.valueToTree(platineContactDto)); - log.info("Got contact info : platineContactDto.Identifier={}", platineContactDto.getIdentifier()); - } - - @Override - public Set getContextErrors(JsonNode contextRootNode) { - if(contextRootNode==null){ - return Set.of("Context is missing"); - } - return DelegateContextVerifier.computeMissingChildrenMessages(Set.of(CTX_CAMPAGNE_ID),contextRootNode,getClass()); - } -} \ No newline at end of file diff --git a/src/main/java/fr/insee/protools/backend/service/platine/delegate/PlatinePilotageGetSUIsToFollowUpTask.java b/src/main/java/fr/insee/protools/backend/service/platine/delegate/PlatinePilotageGetSUIsToFollowUpTask.java deleted file mode 100644 index 8af4e9a9..00000000 --- a/src/main/java/fr/insee/protools/backend/service/platine/delegate/PlatinePilotageGetSUIsToFollowUpTask.java +++ /dev/null @@ -1,57 +0,0 @@ -package fr.insee.protools.backend.service.platine.delegate; - -import com.fasterxml.jackson.databind.JsonNode; -import fr.insee.protools.backend.service.DelegateContextVerifier; -import fr.insee.protools.backend.service.context.ContextService; -import fr.insee.protools.backend.service.platine.pilotage.PlatinePilotageService; -import fr.insee.protools.backend.service.utils.FlowableVariableUtils; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.flowable.engine.delegate.DelegateExecution; -import org.flowable.engine.delegate.JavaDelegate; -import org.springframework.stereotype.Component; - -import java.util.Set; - -import static fr.insee.protools.backend.service.FlowableVariableNameConstants.*; -import static fr.insee.protools.backend.service.context.ContextConstants.CTX_CAMPAGNE_ID; -import static fr.insee.protools.backend.service.platine.utils.PlatineHelper.computePilotagePartitionID; - -@Slf4j -@Component -@RequiredArgsConstructor -public class PlatinePilotageGetSUIsToFollowUpTask implements JavaDelegate, DelegateContextVerifier { - - private final ContextService protoolsContext; - private final PlatinePilotageService platinePilotageService; - - - @Override - public void execute(DelegateExecution execution) { - //Contexte - JsonNode contextRootNode = protoolsContext.getContextByProcessInstance(execution.getProcessInstanceId()); - checkContextOrThrow(log,execution.getProcessInstanceId(), contextRootNode); - String campainId = contextRootNode.path(CTX_CAMPAGNE_ID).asText(); - //Process variables - Long suId = FlowableVariableUtils.getVariableOrThrow(execution, VARNAME_REM_SURVEY_UNIT_IDENTIFIER, Long.class); - Long currentPartitionId = FlowableVariableUtils.getVariableOrThrow(execution, VARNAME_CURRENT_PARTITION_ID, Long.class); - log.info("ProcessInstanceId={} - currentPartitionId={} suId={} begin",execution.getProcessInstanceId(), currentPartitionId,suId); - - //Check if this survey unit isToFollowUp - String platinePartitionId = computePilotagePartitionID(campainId,currentPartitionId); - Boolean suIsToFollowUp = platinePilotageService.isToFollowUp(suId, platinePartitionId); - - //STORE this info - execution.getParent().setVariableLocal(VARNAME_SU_IS_TO_FOLLOWUP, suIsToFollowUp); - log.info("ProcessInstanceId={} - currentPartitionId={} - suId={} - suIsToFollowUp={} end" - ,execution.getProcessInstanceId(), currentPartitionId,suId,suIsToFollowUp); - } - - @Override - public Set getContextErrors(JsonNode contextRootNode) { - if(contextRootNode==null){ - return Set.of("Context is missing"); - } - return DelegateContextVerifier.computeMissingChildrenMessages(Set.of(CTX_CAMPAGNE_ID),contextRootNode,getClass()); - } -} \ No newline at end of file diff --git a/src/main/java/fr/insee/protools/backend/service/platine/delegate/PlatineQuestionnaireCreateContextTask.java b/src/main/java/fr/insee/protools/backend/service/platine/delegate/PlatineQuestionnaireCreateContextTask.java deleted file mode 100644 index 7b361066..00000000 --- a/src/main/java/fr/insee/protools/backend/service/platine/delegate/PlatineQuestionnaireCreateContextTask.java +++ /dev/null @@ -1,109 +0,0 @@ -package fr.insee.protools.backend.service.platine.delegate; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import fr.insee.protools.backend.dto.platine_sabiane_questionnaire.MetadataConstants; -import fr.insee.protools.backend.dto.platine_sabiane_questionnaire.campaign.MetadataValue; -import fr.insee.protools.backend.dto.platine_sabiane_questionnaire.campaign.MetadataValueItem; -import fr.insee.protools.backend.dto.platine_sabiane_questionnaire.campaign.MetadataVariables; -import fr.insee.protools.backend.service.DelegateContextVerifier; -import fr.insee.protools.backend.service.common.platine_sabiane.QuestionnaireHelper; -import fr.insee.protools.backend.service.context.ContextService; -import fr.insee.protools.backend.service.nomenclature.NomenclatureService; -import fr.insee.protools.backend.service.platine.questionnaire.PlatineQuestionnaireService; -import fr.insee.protools.backend.service.questionnaire_model.QuestionnaireModelService; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.flowable.engine.delegate.DelegateExecution; -import org.flowable.engine.delegate.JavaDelegate; -import org.springframework.stereotype.Component; - -import java.util.List; -import java.util.Set; - -import static fr.insee.protools.backend.service.context.ContextConstants.*; - -@Component -@Slf4j -@RequiredArgsConstructor -public class PlatineQuestionnaireCreateContextTask implements JavaDelegate, DelegateContextVerifier { - - private final ContextService protoolsContext; - private final ObjectMapper objectMapper; - private final NomenclatureService nomenclatureService; - private final QuestionnaireModelService questionnaireModelService; - private final PlatineQuestionnaireService platineQuestionnaireService; - - @Override - public void execute(DelegateExecution execution) { - JsonNode contextRootNode = protoolsContext.getContextByProcessInstance(execution.getProcessInstanceId()); - //check context - checkContextOrThrow(log,execution.getProcessInstanceId(), contextRootNode); - - MetadataValue metadataDto = createMetadataDto(contextRootNode); - log.info("ProcessInstanceId={} - campagne={}" - ,execution.getProcessInstanceId(),contextRootNode.path(CTX_CAMPAGNE_CONTEXTE).asText()); - - QuestionnaireHelper.createQuestionnaire(contextRootNode,platineQuestionnaireService,nomenclatureService, - questionnaireModelService,execution.getProcessInstanceId(),metadataDto); - - log.debug("ProcessInstanceId={} end",execution.getProcessInstanceId()); - } - - @Override - public Set getContextErrors(JsonNode contextRootNode) { - if(contextRootNode==null){ - return Set.of(String.format("Class=%s : Context is missing ", this.getClass().getSimpleName())); - } - - //Standard verifications (common between platine and sabiane) - Set missingNodes = - QuestionnaireHelper.getCreateCtxContextErrors(contextRootNode); - - //Metadata used by platine - Set requiredMetadonnes = - Set.of(CTX_META_LABEL_LONG_OPERATION, CTX_META_OBJECTIFS_COURTS, CTX_META_CARACTERE_OBLIGATOIRE, - CTX_META_NUMERO_VISA, CTX_META_MINISTERE_TUTELLE, CTX_META_PARUTION_JO, CTX_META_DATE_PARUTION_JO, - CTX_META_RESPONSABLE_OPERATIONNEL, CTX_META_RESPONSABLE_TRAITEMENT, CTX_META_ANNEE_VISA, - CTX_META_QUALITE_STATISTIQUE, CTX_META_TEST_NON_LABELLISE, - //Legal - CTX_META_URL_LOI_RGPD,CTX_META_URL_LOI_INFORMATIQUE,CTX_META_URL_LOI_STATISTIQUE - ); - - if (contextRootNode.get(CTX_METADONNEES) != null) { - missingNodes.addAll(DelegateContextVerifier.computeMissingChildrenMessages(requiredMetadonnes,contextRootNode.path(CTX_METADONNEES),getClass())); - } - - return missingNodes; - } - - - - MetadataValue createMetadataDto(JsonNode contextRootNode){ - JsonNode metadataNode = contextRootNode.path(CTX_METADONNEES); - return MetadataValue.builder() - .value(MetadataVariables.builder() - .variables( - List.of( - new MetadataValueItem(MetadataConstants.Enq_LibelleEnquete,metadataNode.path(CTX_META_LABEL_LONG_OPERATION).asText()), - new MetadataValueItem(MetadataConstants.Enq_ObjectifsCourts,metadataNode.path(CTX_META_OBJECTIFS_COURTS).asText()), - new MetadataValueItem(MetadataConstants.Enq_CaractereObligatoire,metadataNode.path(CTX_META_CARACTERE_OBLIGATOIRE).asBoolean()), - new MetadataValueItem(MetadataConstants.Enq_NumeroVisa,metadataNode.path(CTX_META_NUMERO_VISA).asText()), - new MetadataValueItem(MetadataConstants.Enq_MinistereTutelle,metadataNode.path(CTX_META_MINISTERE_TUTELLE).asText()), - new MetadataValueItem(MetadataConstants.Enq_ParutionJo,metadataNode.path(CTX_META_PARUTION_JO).asBoolean()), - new MetadataValueItem(MetadataConstants.Enq_DateParutionJo,metadataNode.path(CTX_META_DATE_PARUTION_JO).asText()), - new MetadataValueItem(MetadataConstants.Enq_RespOperationnel,metadataNode.path(CTX_META_RESPONSABLE_OPERATIONNEL).asText()), - new MetadataValueItem(MetadataConstants.Enq_RespTraitement,metadataNode.path(CTX_META_RESPONSABLE_TRAITEMENT).asText()), - new MetadataValueItem(MetadataConstants.Enq_AnneeVisa,metadataNode.path(CTX_META_ANNEE_VISA).asInt()), - new MetadataValueItem(MetadataConstants.Enq_QualiteStatistique,metadataNode.path(CTX_META_QUALITE_STATISTIQUE).asBoolean()), - new MetadataValueItem(MetadataConstants.Enq_TestNonLabellise,metadataNode.path(CTX_META_TEST_NON_LABELLISE).asBoolean()), - new MetadataValueItem(MetadataConstants.Loi_statistique,metadataNode.path(CTX_META_URL_LOI_STATISTIQUE).asText()), - new MetadataValueItem(MetadataConstants.Loi_rgpd,metadataNode.path(CTX_META_URL_LOI_RGPD).asText()), - new MetadataValueItem(MetadataConstants.Loi_informatique,metadataNode.path(CTX_META_URL_LOI_INFORMATIQUE).asText()) - ) - ) - .inseeContext(contextRootNode.path(CTX_CAMPAGNE_CONTEXTE).asText()) - .build()) - .build(); - } -} diff --git a/src/main/java/fr/insee/protools/backend/service/platine/delegate/PlatineQuestionnaireCreateSurveyUnitTask.java b/src/main/java/fr/insee/protools/backend/service/platine/delegate/PlatineQuestionnaireCreateSurveyUnitTask.java deleted file mode 100644 index 864abf91..00000000 --- a/src/main/java/fr/insee/protools/backend/service/platine/delegate/PlatineQuestionnaireCreateSurveyUnitTask.java +++ /dev/null @@ -1,36 +0,0 @@ -package fr.insee.protools.backend.service.platine.delegate; - -import com.fasterxml.jackson.databind.JsonNode; -import fr.insee.protools.backend.service.DelegateContextVerifier; -import fr.insee.protools.backend.service.common.platine_sabiane.QuestionnaireHelper; -import fr.insee.protools.backend.service.context.ContextService; -import fr.insee.protools.backend.service.platine.questionnaire.PlatineQuestionnaireService; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.flowable.engine.delegate.DelegateExecution; -import org.flowable.engine.delegate.JavaDelegate; -import org.springframework.stereotype.Component; - -import java.util.Set; - -@Slf4j -@Component -@RequiredArgsConstructor -public class PlatineQuestionnaireCreateSurveyUnitTask implements JavaDelegate, DelegateContextVerifier { - - private final ContextService protoolsContext; - private final PlatineQuestionnaireService platineQuestionnaireService; - - @Override - public void execute(DelegateExecution execution) { - JsonNode contextRootNode = protoolsContext.getContextByProcessInstance(execution.getProcessInstanceId()); - checkContextOrThrow(log,execution.getProcessInstanceId(), contextRootNode); - QuestionnaireHelper.createSUTaskPlatine(execution,protoolsContext,platineQuestionnaireService); - } - - @Override - public Set getContextErrors(JsonNode contextRootNode) { - return QuestionnaireHelper.getCreateSUContextErrorsPlatine(contextRootNode); - } - -} diff --git a/src/main/java/fr/insee/protools/backend/service/platine/delegate/PlatineQuestionnaireCreateSurveyUnitTaskAsync.java b/src/main/java/fr/insee/protools/backend/service/platine/delegate/PlatineQuestionnaireCreateSurveyUnitTaskAsync.java new file mode 100644 index 00000000..632283f3 --- /dev/null +++ b/src/main/java/fr/insee/protools/backend/service/platine/delegate/PlatineQuestionnaireCreateSurveyUnitTaskAsync.java @@ -0,0 +1,71 @@ +package fr.insee.protools.backend.service.platine.delegate; + +import com.fasterxml.jackson.databind.JsonNode; +import fr.insee.protools.backend.dto.ContexteProcessus; +import fr.insee.protools.backend.repository.IUniteEnquetee; +import fr.insee.protools.backend.service.DelegateContextVerifier; +import fr.insee.protools.backend.service.context.IContextService; +import fr.insee.protools.backend.service.platine.service.IPlatineQuestionnaireService; +import fr.insee.protools.backend.service.scheduled.TaskService; +import fr.insee.protools.backend.service.utils.FlowableVariableUtils; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.flowable.engine.delegate.DelegateExecution; +import org.flowable.engine.delegate.JavaDelegate; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Set; + +import static fr.insee.protools.backend.service.FlowableVariableNameConstants.VARNAME_REM_INTERRO_LIST; + +@Slf4j +@Component +@RequiredArgsConstructor +public class PlatineQuestionnaireCreateSurveyUnitTaskAsync implements JavaDelegate, DelegateContextVerifier { + + private final IContextService protoolsContext; + private final IPlatineQuestionnaireService platineQuestionnaireService; + private final IUniteEnquetee iUniteEnquetee; + @Autowired + TaskService taskService; + + @Override + public void execute(DelegateExecution execution) { + Boolean start = Boolean.FALSE; + ContexteProcessus context = protoolsContext.getContextDtoByProcessInstance(execution.getProcessInstanceId()); + //TODO: delete this log if necessary + log.debug("ProcessInstanceId={} - campagne={} - begin" + ,execution.getProcessInstanceId(),context.getId()); + + checkContextOrThrow(log,execution.getProcessInstanceId(), context); + +// QuestionnaireHelper.createSUTaskPlatineAsync(execution,protoolsContext,iUniteEnquetee,platineQuestionnaireService); + + List listeUe = FlowableVariableUtils.getVariableOrThrow(execution, VARNAME_REM_INTERRO_LIST, List.class); + String processInstanceId = execution.getProcessInstanceId(); + String currentActivityId = execution.getCurrentActivityId(); + iUniteEnquetee.addManyUniteEnquetee(listeUe, processInstanceId, currentActivityId); + +// iUniteEnquetee.addManyUniteEnqueteeDeleteColonneClass(listeUe); + +// TODO gestion des timeouts + while (!start) { + log.info("start : "+ start); + try { + long nbInterogation = iUniteEnquetee.getCommandesByProcessInstanceIdAndCurrentActivityId(execution.getProcessInstanceId(), execution.getCurrentActivityId()); + start = taskService.isTerminated(execution.getProcessInstanceId(), execution.getCurrentActivityId(), nbInterogation); + log.info("Tâche planifiée en cours pour le processInstanceId : " + execution.getProcessInstanceId() + ", le currentActivityId " + execution.getCurrentActivityId() + ",et le nbInterogation totale " + nbInterogation); + Thread.sleep(5000); + if (start) { + break; + } + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + log.debug("ProcessInstanceId={} - campagne={} - end", + execution.getProcessInstanceId(),context.getId()); + } +} diff --git a/src/main/java/fr/insee/protools/backend/service/platine/delegate/pilotatage/PlatinePilotageCreateCommunicationEventTaskREST.java b/src/main/java/fr/insee/protools/backend/service/platine/delegate/pilotatage/PlatinePilotageCreateCommunicationEventTaskREST.java new file mode 100644 index 00000000..cedb4883 --- /dev/null +++ b/src/main/java/fr/insee/protools/backend/service/platine/delegate/pilotatage/PlatinePilotageCreateCommunicationEventTaskREST.java @@ -0,0 +1,60 @@ +package fr.insee.protools.backend.service.platine.delegate.pilotatage; + +import fr.insee.protools.backend.dto.platine.pilotage.PlatinePilotageCommunicationEventDto; +import fr.insee.protools.backend.exception.ProtoolsProcessFlowBPMNError; +import fr.insee.protools.backend.service.platine.service.IPlatinePilotageService; +import fr.insee.protools.backend.service.utils.FlowableVariableUtils; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.flowable.engine.delegate.DelegateExecution; +import org.flowable.engine.delegate.JavaDelegate; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Map; + +import static fr.insee.protools.backend.dto.platine.pilotage.PlatinePilotageCommunicationEventType.COMMUNICATION_STATE_SENT; +import static fr.insee.protools.backend.service.FlowableVariableNameConstants.*; + +@Slf4j +@RequiredArgsConstructor +@Component +public class PlatinePilotageCreateCommunicationEventTaskREST implements JavaDelegate { + + private final IPlatinePilotageService platinePilotageService; + + @Override + public void execute(DelegateExecution execution) { + String currentCommunicationId = FlowableVariableUtils.getVariableOrThrow(execution, VARNAME_CURRENT_COMMUNICATION_ID, String.class); + String currentPartitionId = FlowableVariableUtils.getVariableOrThrow(execution, VARNAME_CURRENT_PARTITION_ID, String.class); + + log.info("ProcessInstanceId={} currentPartitionId={} - currentCommunicationId{} - begin", + execution.getProcessInstanceId(), currentPartitionId, currentCommunicationId); + Map communicationRequestIdByInterroIdMap = FlowableVariableUtils.getVariableOrThrow(execution, VARNAME_COMMUNICATION_REQUEST_ID_FOR_INTERRO_ID_MAP, Map.class); + + if (currentCommunicationId.isBlank()) { + log.error("ProcessInstanceId={} currentPartitionId={} - currentCommunicationId{} : currentCommunicationId cannot be blank", + execution.getProcessInstanceId(), currentPartitionId, currentCommunicationId); + throw new ProtoolsProcessFlowBPMNError("PlatinePilotageCreateCommunicationEventTaskREST: communicationId cannot be empty"); + } + + //If nothing to do ==> Directly return + if (communicationRequestIdByInterroIdMap.isEmpty()) { + log.info("ProcessInstanceId={} currentPartitionId={} - currentCommunicationId{} - end : Nothing to do", + execution.getProcessInstanceId(), currentPartitionId, currentCommunicationId); + return; + } + + List platinePilotageCommunicationEventList = communicationRequestIdByInterroIdMap.entrySet() + .stream() + .map(entry -> + new PlatinePilotageCommunicationEventDto(entry.getKey(), currentCommunicationId, entry.getValue(), COMMUNICATION_STATE_SENT)) + .toList(); + + //Check ctx? + platinePilotageService.postCommunicationEvents(platinePilotageCommunicationEventList); + + log.info("ProcessInstanceId={} end", execution.getProcessInstanceId()); + + } +} \ No newline at end of file diff --git a/src/main/java/fr/insee/protools/backend/service/platine/delegate/pilotatage/PlatinePilotageCreateContextTaskREST.java b/src/main/java/fr/insee/protools/backend/service/platine/delegate/pilotatage/PlatinePilotageCreateContextTaskREST.java new file mode 100644 index 00000000..5854ce3e --- /dev/null +++ b/src/main/java/fr/insee/protools/backend/service/platine/delegate/pilotatage/PlatinePilotageCreateContextTaskREST.java @@ -0,0 +1,33 @@ +package fr.insee.protools.backend.service.platine.delegate.pilotatage; + +import com.fasterxml.jackson.databind.JsonNode; +import fr.insee.protools.backend.dto.ContexteProcessus; +import fr.insee.protools.backend.service.context.IContextService; +import fr.insee.protools.backend.service.platine.service.IPlatinePilotageService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.flowable.engine.delegate.DelegateExecution; +import org.flowable.engine.delegate.JavaDelegate; +import org.springframework.stereotype.Component; + +@Slf4j +@RequiredArgsConstructor +@Component +public class PlatinePilotageCreateContextTaskREST implements JavaDelegate { + + private final IContextService protoolsContext; + private final IPlatinePilotageService platinePilotageService; + + @Override + public void execute(DelegateExecution execution) { + log.info("ProcessInstanceId={} begin",execution.getProcessInstanceId()); + JsonNode contextRootNode = protoolsContext.getContextJsonNodeByProcessInstance(execution.getProcessInstanceId()); + ContexteProcessus contexteProcessus = protoolsContext.getContextDtoByProcessInstance(execution.getProcessInstanceId()); + + //No context used (only passed as json) + platinePilotageService.postContext(contexteProcessus.getId().toString(),contextRootNode); + + log.info("ProcessInstanceId={} end",execution.getProcessInstanceId()); + + } +} \ No newline at end of file diff --git a/src/main/java/fr/insee/protools/backend/service/platine/delegate/pilotatage/PlatinePilotageCreateInterrogationListTaskREST.java b/src/main/java/fr/insee/protools/backend/service/platine/delegate/pilotatage/PlatinePilotageCreateInterrogationListTaskREST.java new file mode 100644 index 00000000..7dba1557 --- /dev/null +++ b/src/main/java/fr/insee/protools/backend/service/platine/delegate/pilotatage/PlatinePilotageCreateInterrogationListTaskREST.java @@ -0,0 +1,37 @@ +package fr.insee.protools.backend.service.platine.delegate.pilotatage; + +import com.fasterxml.jackson.databind.JsonNode; +import fr.insee.protools.backend.dto.ContexteProcessus; +import fr.insee.protools.backend.service.context.IContextService; +import fr.insee.protools.backend.service.platine.service.IPlatinePilotageService; +import fr.insee.protools.backend.service.utils.FlowableVariableUtils; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.flowable.engine.delegate.DelegateExecution; +import org.flowable.engine.delegate.JavaDelegate; +import org.springframework.stereotype.Component; + +import java.util.List; + +import static fr.insee.protools.backend.service.FlowableVariableNameConstants.VARNAME_CURRENT_PARTITION_ID; +import static fr.insee.protools.backend.service.FlowableVariableNameConstants.VARNAME_REM_INTERRO_LIST; + +@Component +@RequiredArgsConstructor +@Slf4j +public class PlatinePilotageCreateInterrogationListTaskREST implements JavaDelegate { + + private final IPlatinePilotageService platinePilotageService; + private final IContextService protoolsContext; + + @Override + public void execute(DelegateExecution execution) { + ContexteProcessus context = protoolsContext.getContextDtoByProcessInstance(execution.getProcessInstanceId()); + String currentPartitionId = FlowableVariableUtils.getVariableOrThrow(execution, VARNAME_CURRENT_PARTITION_ID, String.class); + List interroList = FlowableVariableUtils.getVariableOrThrow(execution, VARNAME_REM_INTERRO_LIST, List.class); + + log.info("ProcessInstanceId={} - currentPartitionId={} - begin",execution.getProcessInstanceId(),currentPartitionId); + platinePilotageService.postInterrogations(String.valueOf(context.getId()),interroList); + log.info("ProcessInstanceId={} - currentPartitionId={} - end",execution.getProcessInstanceId(),currentPartitionId); + } +} diff --git a/src/main/java/fr/insee/protools/backend/service/platine/delegate/pilotatage/PlatinePilotageGetListOfInterroToFollowUpPaginatedTaskREST.java b/src/main/java/fr/insee/protools/backend/service/platine/delegate/pilotatage/PlatinePilotageGetListOfInterroToFollowUpPaginatedTaskREST.java new file mode 100644 index 00000000..1ce886cf --- /dev/null +++ b/src/main/java/fr/insee/protools/backend/service/platine/delegate/pilotatage/PlatinePilotageGetListOfInterroToFollowUpPaginatedTaskREST.java @@ -0,0 +1,53 @@ +package fr.insee.protools.backend.service.platine.delegate.pilotatage; + +import com.fasterxml.jackson.databind.JsonNode; +import fr.insee.protools.backend.restclient.pagination.PageResponse; +import fr.insee.protools.backend.service.DelegateContextVerifier; +import fr.insee.protools.backend.service.platine.service.IPlatinePilotageService; +import fr.insee.protools.backend.service.utils.FlowableVariableUtils; +import fr.insee.protools.backend.service.utils.delegate.PaginationHelper; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.flowable.engine.delegate.DelegateExecution; +import org.flowable.engine.delegate.JavaDelegate; +import org.slf4j.Logger; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import static fr.insee.protools.backend.service.FlowableVariableNameConstants.*; + + +@Slf4j +@Component +@RequiredArgsConstructor +public class PlatinePilotageGetListOfInterroToFollowUpPaginatedTaskREST implements JavaDelegate, DelegateContextVerifier, PaginationHelper { + + private final IPlatinePilotageService pilotageService; + + protected PageResponse readFunction(Integer pageToRead, Object... objects) { + String partitionId = (String) objects[0]; + return pilotageService.getInterrogationToFollowUpPaginated(partitionId, pageToRead, Optional.of(Boolean.TRUE)); + } + + @Override + public void execute(DelegateExecution execution) { + String currentPartitionId = FlowableVariableUtils.getVariableOrThrow(execution, VARNAME_CURRENT_PARTITION_ID, String.class); + getAndTreat(execution, VARNAME_INTERRO_LIST_PAGEABLE_CURRENT_PAGE, VARNAME_INTERRO_LIST_PAGEABLE_IS_LAST_PAGE, this::readFunction, currentPartitionId); + } + + @Override + public Logger getLogger() { + return log; + } + + @Override + public Map treatPage(DelegateExecution execution, List contentList) { + Map variables = new HashMap<>(); + variables.put(VARNAME_REM_INTERRO_LIST, contentList); + return variables; + } +} \ No newline at end of file diff --git a/src/main/java/fr/insee/protools/backend/service/platine/delegate/questionnaire/PlatineQuestionnaireCreateContextTaskREST.java b/src/main/java/fr/insee/protools/backend/service/platine/delegate/questionnaire/PlatineQuestionnaireCreateContextTaskREST.java new file mode 100644 index 00000000..9cbe6f1c --- /dev/null +++ b/src/main/java/fr/insee/protools/backend/service/platine/delegate/questionnaire/PlatineQuestionnaireCreateContextTaskREST.java @@ -0,0 +1,33 @@ +package fr.insee.protools.backend.service.platine.delegate.questionnaire; + +import com.fasterxml.jackson.databind.JsonNode; +import fr.insee.protools.backend.dto.ContexteProcessus; +import fr.insee.protools.backend.service.context.IContextService; +import fr.insee.protools.backend.service.platine.service.IPlatineQuestionnaireService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.flowable.engine.delegate.DelegateExecution; +import org.flowable.engine.delegate.JavaDelegate; +import org.springframework.stereotype.Component; + +@Slf4j +@RequiredArgsConstructor +@Component +public class PlatineQuestionnaireCreateContextTaskREST implements JavaDelegate { + + private final IContextService protoolsContext; + private final IPlatineQuestionnaireService platineQuestionnaireService; + + @Override + public void execute(DelegateExecution execution) { + log.info("ProcessInstanceId={} begin",execution.getProcessInstanceId()); + JsonNode contextRootNode = protoolsContext.getContextJsonNodeByProcessInstance(execution.getProcessInstanceId()); + ContexteProcessus contexteProcessus = protoolsContext.getContextDtoByProcessInstance(execution.getProcessInstanceId()); + + //No context used (only passed as json) + platineQuestionnaireService.postContext(contexteProcessus.getId().toString(),contextRootNode); + + log.info("ProcessInstanceId={} end",execution.getProcessInstanceId()); + + } +} \ No newline at end of file diff --git a/src/main/java/fr/insee/protools/backend/service/platine/delegate/questionnaire/PlatineQuestionnaireCreateInterrogationListTaskREST.java b/src/main/java/fr/insee/protools/backend/service/platine/delegate/questionnaire/PlatineQuestionnaireCreateInterrogationListTaskREST.java new file mode 100644 index 00000000..b5c7d6ba --- /dev/null +++ b/src/main/java/fr/insee/protools/backend/service/platine/delegate/questionnaire/PlatineQuestionnaireCreateInterrogationListTaskREST.java @@ -0,0 +1,37 @@ +package fr.insee.protools.backend.service.platine.delegate.questionnaire; + +import com.fasterxml.jackson.databind.JsonNode; +import fr.insee.protools.backend.dto.ContexteProcessus; +import fr.insee.protools.backend.service.context.IContextService; +import fr.insee.protools.backend.service.platine.service.IPlatineQuestionnaireService; +import fr.insee.protools.backend.service.utils.FlowableVariableUtils; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.flowable.engine.delegate.DelegateExecution; +import org.flowable.engine.delegate.JavaDelegate; +import org.springframework.stereotype.Component; + +import java.util.List; + +import static fr.insee.protools.backend.service.FlowableVariableNameConstants.VARNAME_CURRENT_PARTITION_ID; +import static fr.insee.protools.backend.service.FlowableVariableNameConstants.VARNAME_REM_INTERRO_LIST; + +@Component +@RequiredArgsConstructor +@Slf4j +public class PlatineQuestionnaireCreateInterrogationListTaskREST implements JavaDelegate { + + private final IPlatineQuestionnaireService platineQuestionnaireService; + private final IContextService protoolsContext; + + @Override + public void execute(DelegateExecution execution) { + ContexteProcessus context = protoolsContext.getContextDtoByProcessInstance(execution.getProcessInstanceId()); + String currentPartitionId = FlowableVariableUtils.getVariableOrThrow(execution, VARNAME_CURRENT_PARTITION_ID, String.class); + List interroList = FlowableVariableUtils.getVariableOrThrow(execution, VARNAME_REM_INTERRO_LIST, List.class); + + log.info("ProcessInstanceId={} - currentPartitionId={} - begin",execution.getProcessInstanceId(),currentPartitionId); + platineQuestionnaireService.postInterrogations(String.valueOf(context.getId()),interroList); + log.info("ProcessInstanceId={} - currentPartitionId={} - end",execution.getProcessInstanceId(),currentPartitionId); + } +} diff --git a/src/main/java/fr/insee/protools/backend/service/platine/pilotage/PlatinePilotageService.java b/src/main/java/fr/insee/protools/backend/service/platine/pilotage/PlatinePilotageService.java deleted file mode 100644 index 996eeabd..00000000 --- a/src/main/java/fr/insee/protools/backend/service/platine/pilotage/PlatinePilotageService.java +++ /dev/null @@ -1,80 +0,0 @@ -package fr.insee.protools.backend.service.platine.pilotage; - -import fr.insee.protools.backend.dto.platine.pilotage.PlatinePilotageEligibleDto; -import fr.insee.protools.backend.dto.platine.pilotage.contact.PlatineContactDto; -import fr.insee.protools.backend.dto.platine.pilotage.query.QuestioningWebclientDto; -import fr.insee.protools.backend.service.platine.pilotage.metadata.MetadataDto; -import fr.insee.protools.backend.webclient.WebClientHelper; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.slf4j.event.Level; -import org.springframework.stereotype.Service; - -import static fr.insee.protools.backend.webclient.WebClientHelper.logJson; -import static fr.insee.protools.backend.webclient.configuration.ApiConfigProperties.KNOWN_API.KNOWN_API_PLATINE_PILOTAGE; - -@Service -@Slf4j -@RequiredArgsConstructor -public class PlatinePilotageService { - - private final WebClientHelper webClientHelper; - public void putMetadata(String partitionId , MetadataDto dto) { - log.debug("putMetadata : partitionId={} - dto.su.id={} ",partitionId,dto.getSurveyDto().getId()); - logJson(String.format("putMetadata - partitionId=%s : ",partitionId),dto, log,Level.DEBUG); - var response = webClientHelper.getWebClient(KNOWN_API_PLATINE_PILOTAGE) - .put() - .uri(uriBuilder -> uriBuilder - .path("/api/metadata/{id}") - .build(partitionId)) - .bodyValue(dto) - .retrieve() - .bodyToMono(String.class) - .block(); - log.trace("putMetadata : partitionId={} - response={} ",partitionId,response); - } - public void putQuestionings(QuestioningWebclientDto dto) { - log.debug("putQuestionings: idPartitioning={} - idSu={}",dto.getIdPartitioning(),dto.getSurveyUnit().getIdSu()); - logJson("putMetadata ",dto,log,Level.TRACE); - var response = webClientHelper.getWebClient(KNOWN_API_PLATINE_PILOTAGE) - .put() - .uri("/api/questionings") - .bodyValue(dto) - .retrieve() - .bodyToMono(String.class) - .block(); - log.trace("putQuestionings - response={} ",response); - } - - public PlatineContactDto getSUMainContact(Long idSU, String platinePartitionId){ - log.debug("getSUMainContact: platinePartitionId={} - idSu={}",platinePartitionId,idSU); - PlatineContactDto response = webClientHelper.getWebClient(KNOWN_API_PLATINE_PILOTAGE) - .get() - .uri(uriBuilder -> uriBuilder - .path("/api/main-contact") - .queryParam("partitioning", platinePartitionId) - .queryParam("survey-unit", idSU) - .build()) - .retrieve() - .bodyToMono(PlatineContactDto.class) - .block(); - logJson("getSUMainContact response : ",response,log,Level.TRACE); - return response; - } - - public Boolean isToFollowUp(Long idSU, String platinePartitionId){ - log.debug("isToFollowUp: platinePartitionId={} - idSu={}",platinePartitionId,idSU); - PlatinePilotageEligibleDto response = webClientHelper.getWebClient(KNOWN_API_PLATINE_PILOTAGE) - .get() - .uri(uriBuilder -> uriBuilder - .path("/api/partitionings/{idPartitioning}/survey-units/{idSu}/follow-up") - .build(platinePartitionId,idSU)) - .retrieve() - .bodyToMono(PlatinePilotageEligibleDto.class) - .block(); - Boolean result = Boolean.valueOf(response.getEligible()); - logJson("isToFollowUp: result="+result+" - response : ",response,log,Level.TRACE); - return result; - } - -} diff --git a/src/main/java/fr/insee/protools/backend/service/platine/pilotage/metadata/CampaignDto.java b/src/main/java/fr/insee/protools/backend/service/platine/pilotage/metadata/CampaignDto.java deleted file mode 100644 index d6b994f4..00000000 --- a/src/main/java/fr/insee/protools/backend/service/platine/pilotage/metadata/CampaignDto.java +++ /dev/null @@ -1,14 +0,0 @@ -package fr.insee.protools.backend.service.platine.pilotage.metadata; -import lombok.Builder; -import lombok.Data; - -@Data -@Builder -public class CampaignDto { - - private String id; - private String surveyId; - private int year; - private String campaignWording; - private PeriodEnum period; -} \ No newline at end of file diff --git a/src/main/java/fr/insee/protools/backend/service/platine/pilotage/metadata/MetadataDto.java b/src/main/java/fr/insee/protools/backend/service/platine/pilotage/metadata/MetadataDto.java deleted file mode 100644 index 65924ffc..00000000 --- a/src/main/java/fr/insee/protools/backend/service/platine/pilotage/metadata/MetadataDto.java +++ /dev/null @@ -1,26 +0,0 @@ -package fr.insee.protools.backend.service.platine.pilotage.metadata; - -import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -@Data -@AllArgsConstructor -@NoArgsConstructor -public class MetadataDto { - - @JsonProperty("partitioning") - private PartitioningDto partitioningDto; - @JsonProperty("campaign") - private CampaignDto campaignDto; - @JsonProperty("survey") - private SurveyDto surveyDto; - @JsonProperty("source") - private SourceDto sourceDto; - @JsonProperty("owner") - private OwnerDto ownerDto; - @JsonProperty("support") - private SupportDto supportDto; - -} \ No newline at end of file diff --git a/src/main/java/fr/insee/protools/backend/service/platine/pilotage/metadata/OwnerDto.java b/src/main/java/fr/insee/protools/backend/service/platine/pilotage/metadata/OwnerDto.java deleted file mode 100644 index 40789a19..00000000 --- a/src/main/java/fr/insee/protools/backend/service/platine/pilotage/metadata/OwnerDto.java +++ /dev/null @@ -1,15 +0,0 @@ -package fr.insee.protools.backend.service.platine.pilotage.metadata; - -import lombok.Builder; -import lombok.Data; - -@Data -@Builder -public class OwnerDto { - - private String id; - private String label; - private String ministry; - private String logo; - -} \ No newline at end of file diff --git a/src/main/java/fr/insee/protools/backend/service/platine/pilotage/metadata/PartitioningDto.java b/src/main/java/fr/insee/protools/backend/service/platine/pilotage/metadata/PartitioningDto.java deleted file mode 100644 index d378887a..00000000 --- a/src/main/java/fr/insee/protools/backend/service/platine/pilotage/metadata/PartitioningDto.java +++ /dev/null @@ -1,17 +0,0 @@ -package fr.insee.protools.backend.service.platine.pilotage.metadata; - -import lombok.Builder; -import lombok.Data; - -@Data -@Builder -public class PartitioningDto { - - private String id; - private String campaignId; - private String label; - //Defined as dates in platine but use String in protools so we dont have to parse them - private String openingDate; - private String closingDate; - private String returnDate; -} \ No newline at end of file diff --git a/src/main/java/fr/insee/protools/backend/service/platine/pilotage/metadata/PeriodEnum.java b/src/main/java/fr/insee/protools/backend/service/platine/pilotage/metadata/PeriodEnum.java deleted file mode 100644 index 6607150c..00000000 --- a/src/main/java/fr/insee/protools/backend/service/platine/pilotage/metadata/PeriodEnum.java +++ /dev/null @@ -1,145 +0,0 @@ -package fr.insee.protools.backend.service.platine.pilotage.metadata; - -import lombok.Getter; - -@Getter -public enum PeriodEnum { - - A00(PeriodicityEnum.A, "annual"), - X00(PeriodicityEnum.X, "pluriannual"), - X01(PeriodicityEnum.X, "pluriannual"), - X02(PeriodicityEnum.X, "pluriannual"), - X03(PeriodicityEnum.X, "pluriannual"), - X04(PeriodicityEnum.X, "pluriannual"), - X05(PeriodicityEnum.X, "pluriannual"), - X06(PeriodicityEnum.X, "pluriannual"), - X07(PeriodicityEnum.X, "pluriannual"), - X08(PeriodicityEnum.X, "pluriannual"), - X09(PeriodicityEnum.X, "pluriannual"), - X10(PeriodicityEnum.X, "pluriannual"), - X11(PeriodicityEnum.X, "pluriannual"), - X12(PeriodicityEnum.X, "pluriannual"), - X13(PeriodicityEnum.X, "pluriannual"), - X14(PeriodicityEnum.X, "pluriannual"), - X15(PeriodicityEnum.X, "pluriannual"), - X16(PeriodicityEnum.X, "pluriannual"), - X17(PeriodicityEnum.X, "pluriannual"), - X18(PeriodicityEnum.X, "pluriannual"), - X19(PeriodicityEnum.X, "pluriannual"), - X20(PeriodicityEnum.X, "pluriannual"), - X21(PeriodicityEnum.X, "pluriannual"), - X22(PeriodicityEnum.X, "pluriannual"), - X23(PeriodicityEnum.X, "pluriannual"), - X24(PeriodicityEnum.X, "pluriannual"), - X25(PeriodicityEnum.X, "pluriannual"), - X26(PeriodicityEnum.X, "pluriannual"), - X27(PeriodicityEnum.X, "pluriannual"), - X28(PeriodicityEnum.X, "pluriannual"), - X29(PeriodicityEnum.X, "pluriannual"), - X30(PeriodicityEnum.X, "pluriannual"), - X31(PeriodicityEnum.X, "pluriannual"), - X32(PeriodicityEnum.X, "pluriannual"), - X33(PeriodicityEnum.X, "pluriannual"), - X34(PeriodicityEnum.X, "pluriannual"), - X35(PeriodicityEnum.X, "pluriannual"), - X36(PeriodicityEnum.X, "pluriannual"), - X37(PeriodicityEnum.X, "pluriannual"), - X38(PeriodicityEnum.X, "pluriannual"), - X39(PeriodicityEnum.X, "pluriannual"), - X40(PeriodicityEnum.X, "pluriannual"), - X41(PeriodicityEnum.X, "pluriannual"), - X42(PeriodicityEnum.X, "pluriannual"), - X43(PeriodicityEnum.X, "pluriannual"), - X44(PeriodicityEnum.X, "pluriannual"), - X45(PeriodicityEnum.X, "pluriannual"), - X46(PeriodicityEnum.X, "pluriannual"), - X47(PeriodicityEnum.X, "pluriannual"), - X48(PeriodicityEnum.X, "pluriannual"), - X49(PeriodicityEnum.X, "pluriannual"), - X50(PeriodicityEnum.X, "pluriannual"), - X51(PeriodicityEnum.X, "pluriannual"), - X52(PeriodicityEnum.X, "pluriannual"), - X53(PeriodicityEnum.X, "pluriannual"), - X54(PeriodicityEnum.X, "pluriannual"), - X55(PeriodicityEnum.X, "pluriannual"), - X56(PeriodicityEnum.X, "pluriannual"), - X57(PeriodicityEnum.X, "pluriannual"), - X58(PeriodicityEnum.X, "pluriannual"), - X59(PeriodicityEnum.X, "pluriannual"), - X60(PeriodicityEnum.X, "pluriannual"), - X61(PeriodicityEnum.X, "pluriannual"), - X62(PeriodicityEnum.X, "pluriannual"), - X63(PeriodicityEnum.X, "pluriannual"), - X64(PeriodicityEnum.X, "pluriannual"), - X65(PeriodicityEnum.X, "pluriannual"), - X66(PeriodicityEnum.X, "pluriannual"), - X67(PeriodicityEnum.X, "pluriannual"), - X68(PeriodicityEnum.X, "pluriannual"), - X69(PeriodicityEnum.X, "pluriannual"), - X70(PeriodicityEnum.X, "pluriannual"), - X71(PeriodicityEnum.X, "pluriannual"), - X72(PeriodicityEnum.X, "pluriannual"), - X73(PeriodicityEnum.X, "pluriannual"), - X74(PeriodicityEnum.X, "pluriannual"), - X75(PeriodicityEnum.X, "pluriannual"), - X76(PeriodicityEnum.X, "pluriannual"), - X77(PeriodicityEnum.X, "pluriannual"), - X78(PeriodicityEnum.X, "pluriannual"), - X79(PeriodicityEnum.X, "pluriannual"), - X80(PeriodicityEnum.X, "pluriannual"), - X81(PeriodicityEnum.X, "pluriannual"), - X82(PeriodicityEnum.X, "pluriannual"), - X83(PeriodicityEnum.X, "pluriannual"), - X84(PeriodicityEnum.X, "pluriannual"), - X85(PeriodicityEnum.X, "pluriannual"), - X86(PeriodicityEnum.X, "pluriannual"), - X87(PeriodicityEnum.X, "pluriannual"), - X88(PeriodicityEnum.X, "pluriannual"), - X89(PeriodicityEnum.X, "pluriannual"), - X90(PeriodicityEnum.X, "pluriannual"), - X91(PeriodicityEnum.X, "pluriannual"), - X92(PeriodicityEnum.X, "pluriannual"), - X93(PeriodicityEnum.X, "pluriannual"), - X94(PeriodicityEnum.X, "pluriannual"), - X95(PeriodicityEnum.X, "pluriannual"), - X96(PeriodicityEnum.X, "pluriannual"), - X97(PeriodicityEnum.X, "pluriannual"), - X98(PeriodicityEnum.X, "pluriannual"), - X99(PeriodicityEnum.X, "pluriannual"), - S01(PeriodicityEnum.S, "1st semester"), - S02(PeriodicityEnum.S, "2nd semester"), - T01(PeriodicityEnum.T, "1st trimester"), - T02(PeriodicityEnum.T, "2nd trimester"), - T03(PeriodicityEnum.T, "3rd trimester"), - T04(PeriodicityEnum.T, "4th trimester"), - M01(PeriodicityEnum.M, "january"), - M02(PeriodicityEnum.M, "february"), - M03(PeriodicityEnum.M, "march"), - M04(PeriodicityEnum.M, "april"), - M05(PeriodicityEnum.M, "may"), - M06(PeriodicityEnum.M, "june"), - M07(PeriodicityEnum.M, "july"), - M08(PeriodicityEnum.M, "august"), - M09(PeriodicityEnum.M, "september"), - M10(PeriodicityEnum.M, "october"), - M11(PeriodicityEnum.M, "november"), - M12(PeriodicityEnum.M, "december"), - B01(PeriodicityEnum.B, "1st bimester"), - B02(PeriodicityEnum.B, "2nd bimester"), - B03(PeriodicityEnum.B, "3rd bimester"), - B04(PeriodicityEnum.B, "4th bimester"), - B05(PeriodicityEnum.B, "5th bimester"), - B06(PeriodicityEnum.B, "6th bimester"), - - ; - - PeriodEnum(PeriodicityEnum period, String value) { - this.value = value; - this.period = period; - } - - final PeriodicityEnum period; - - final String value; - -} \ No newline at end of file diff --git a/src/main/java/fr/insee/protools/backend/service/platine/pilotage/metadata/PeriodicityEnum.java b/src/main/java/fr/insee/protools/backend/service/platine/pilotage/metadata/PeriodicityEnum.java deleted file mode 100644 index bd66eddb..00000000 --- a/src/main/java/fr/insee/protools/backend/service/platine/pilotage/metadata/PeriodicityEnum.java +++ /dev/null @@ -1,26 +0,0 @@ -package fr.insee.protools.backend.service.platine.pilotage.metadata; - -import lombok.Getter; - -@Getter -public enum PeriodicityEnum { - - X("pluriannual"), A("annual"), S("semi-annual"), T("trimestrial"), B("bimonthly"), - M("monthly"); - - PeriodicityEnum(String value) { - this.value = value; - } - - final String value; - - public static PeriodicityEnum fromValue(String v) { - for (PeriodicityEnum c : PeriodicityEnum.values()) { - if (c.value.equals(v)) { - return c; - } - } - throw new IllegalArgumentException(v); - } - -} \ No newline at end of file diff --git a/src/main/java/fr/insee/protools/backend/service/platine/pilotage/metadata/SourceDto.java b/src/main/java/fr/insee/protools/backend/service/platine/pilotage/metadata/SourceDto.java deleted file mode 100644 index 74dde6e4..00000000 --- a/src/main/java/fr/insee/protools/backend/service/platine/pilotage/metadata/SourceDto.java +++ /dev/null @@ -1,15 +0,0 @@ -package fr.insee.protools.backend.service.platine.pilotage.metadata; -import lombok.Builder; -import lombok.Data; - -@Data -@Builder -public class SourceDto { - - private String id; - private String longWording; - private String shortWording; - private PeriodicityEnum periodicity; - private boolean mandatoryMySurveys; - -} \ No newline at end of file diff --git a/src/main/java/fr/insee/protools/backend/service/platine/pilotage/metadata/SupportDto.java b/src/main/java/fr/insee/protools/backend/service/platine/pilotage/metadata/SupportDto.java deleted file mode 100644 index 4c577b7d..00000000 --- a/src/main/java/fr/insee/protools/backend/service/platine/pilotage/metadata/SupportDto.java +++ /dev/null @@ -1,20 +0,0 @@ -package fr.insee.protools.backend.service.platine.pilotage.metadata; - -import lombok.Builder; -import lombok.Data; - -@Data -@Builder -public class SupportDto { - - private String id; - private String label; - private String phoneNumber; - private String mail; - private String countryName; - private String streetNumber; - private String streetName; - private String city; - private String zipCode; - -} \ No newline at end of file diff --git a/src/main/java/fr/insee/protools/backend/service/platine/pilotage/metadata/SurveyDto.java b/src/main/java/fr/insee/protools/backend/service/platine/pilotage/metadata/SurveyDto.java deleted file mode 100644 index 04392d17..00000000 --- a/src/main/java/fr/insee/protools/backend/service/platine/pilotage/metadata/SurveyDto.java +++ /dev/null @@ -1,26 +0,0 @@ -package fr.insee.protools.backend.service.platine.pilotage.metadata; - -import lombok.Builder; -import lombok.Data; -import lombok.NonNull; - -@Data -@Builder -public class SurveyDto { - - private String id; - @NonNull - private String sourceId; - private Integer year; - private Integer sampleSize; - private String longWording; - private String shortWording; - private String shortObjectives; - private String longObjectives; - private String visaNumber; - private String cnisUrl; - private String diffusionUrl; - private String noticeUrl; - private String specimenUrl; - private String communication; -} \ No newline at end of file diff --git a/src/main/java/fr/insee/protools/backend/service/platine/questionnaire/PlatineQuestionnaireService.java b/src/main/java/fr/insee/protools/backend/service/platine/questionnaire/PlatineQuestionnaireService.java deleted file mode 100644 index b8bae3a3..00000000 --- a/src/main/java/fr/insee/protools/backend/service/platine/questionnaire/PlatineQuestionnaireService.java +++ /dev/null @@ -1,29 +0,0 @@ -package fr.insee.protools.backend.service.platine.questionnaire; - -import fr.insee.protools.backend.service.common.platine_sabiane.QuestionnairePlatineSabianeService; -import fr.insee.protools.backend.webclient.WebClientHelper; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.slf4j.Logger; -import org.springframework.stereotype.Service; -import org.springframework.web.reactive.function.client.WebClient; - -import static fr.insee.protools.backend.webclient.configuration.ApiConfigProperties.KNOWN_API.KNOWN_API_PLATINE_QUESTIONNAIRE; - -@Service -@Slf4j -@RequiredArgsConstructor -public class PlatineQuestionnaireService implements QuestionnairePlatineSabianeService { - - private final WebClientHelper webClientHelper; - - @Override - public WebClient webClient() { - return webClientHelper.getWebClient(KNOWN_API_PLATINE_QUESTIONNAIRE); - } - - @Override - public Logger getLogger() { - return log; - } -} diff --git a/src/main/java/fr/insee/protools/backend/service/platine/service/IPlatinePilotageService.java b/src/main/java/fr/insee/protools/backend/service/platine/service/IPlatinePilotageService.java new file mode 100644 index 00000000..419b4b2d --- /dev/null +++ b/src/main/java/fr/insee/protools/backend/service/platine/service/IPlatinePilotageService.java @@ -0,0 +1,19 @@ +package fr.insee.protools.backend.service.platine.service; + +import com.fasterxml.jackson.databind.JsonNode; +import fr.insee.protools.backend.dto.platine.pilotage.PlatinePilotageCommunicationEventDto; +import fr.insee.protools.backend.restclient.pagination.PageResponse; + +import java.util.List; +import java.util.Optional; + +public interface IPlatinePilotageService { + + void postCommunicationEvents(List platinePilotageCommunicationEventList); + + void postContext(String campaignId, JsonNode contextRootNode); + + void postInterrogations(String campaignId, List interrogations); + + PageResponse getInterrogationToFollowUpPaginated(String partitionId, long page, Optional isToFollowUp); +} diff --git a/src/main/java/fr/insee/protools/backend/service/platine/service/IPlatineQuestionnaireService.java b/src/main/java/fr/insee/protools/backend/service/platine/service/IPlatineQuestionnaireService.java new file mode 100644 index 00000000..bfae6ac0 --- /dev/null +++ b/src/main/java/fr/insee/protools/backend/service/platine/service/IPlatineQuestionnaireService.java @@ -0,0 +1,12 @@ +package fr.insee.protools.backend.service.platine.service; + +import com.fasterxml.jackson.databind.JsonNode; + +import java.util.List; + +public interface IPlatineQuestionnaireService { + + void postContext(String campaignId, JsonNode contextRootNode); + + void postInterrogations(String campaignId, List interrogations); +} diff --git a/src/main/java/fr/insee/protools/backend/service/platine/service/PlatinePilotageServiceImpl.java b/src/main/java/fr/insee/protools/backend/service/platine/service/PlatinePilotageServiceImpl.java new file mode 100644 index 00000000..06b8f8b8 --- /dev/null +++ b/src/main/java/fr/insee/protools/backend/service/platine/service/PlatinePilotageServiceImpl.java @@ -0,0 +1,107 @@ +package fr.insee.protools.backend.service.platine.service; + +import com.fasterxml.jackson.databind.JsonNode; +import fr.insee.protools.backend.dto.platine.pilotage.PlatinePilotageCommunicationEventDto; +import fr.insee.protools.backend.restclient.RestClientHelper; +import fr.insee.protools.backend.restclient.configuration.ApiConfigProperties; +import fr.insee.protools.backend.restclient.exception.runtime.HttpClient4xxBPMNError; +import fr.insee.protools.backend.restclient.pagination.PageResponse; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.slf4j.event.Level; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Optional; + +import static fr.insee.protools.backend.logging.LoggingHelper.logJson; +import static fr.insee.protools.backend.restclient.configuration.ApiConfigProperties.KNOWN_API.KNOWN_API_PLATINE_PILOTAGE; + +@Service +@Slf4j +@RequiredArgsConstructor +public class PlatinePilotageServiceImpl implements IPlatinePilotageService{ + + private final RestClientHelper restClientHelper; + private static final ApiConfigProperties.KNOWN_API API= KNOWN_API_PLATINE_PILOTAGE; + + @Value("${fr.insee.protools.api.platine-pilotage.interrogation.page.size:5000}") + private int pageSizeGetInterro; + + @Override + public void postCommunicationEvents(List platinePilotageCommunicationEventList) { + log.trace("postCommunicationEvents: "); + logJson("postCommunicationEvents ",platinePilotageCommunicationEventList,log, Level.TRACE); + + var response = restClientHelper.getRestClient(API) + .post() + .uri("/interrogations/communication-events") + .body(platinePilotageCommunicationEventList) + .retrieve() + .body(String.class); + log.trace("postCommunicationEvents: response={} ",response); + } + + @Override + public void postContext(String campaignId, JsonNode contextRootNode) { + log.trace("postContext: campaignId={}",campaignId); + var response = restClientHelper.getRestClient(KNOWN_API_PLATINE_PILOTAGE) + .post() + .uri("/context") + .body(contextRootNode) + .retrieve() + .body(String.class); + log.trace("postContext: campaignId={} - response={} ",campaignId,response); + } + + @Override + public void postInterrogations(String campaignId, List interrogations) { + log.trace("postInterrogations: campaignId={}",campaignId); + logJson("postInterrogations ",interrogations,log,Level.TRACE); + var response = restClientHelper.getRestClient(API) + .post() + .uri("/interrogations") + .body(interrogations) + .retrieve() + .body(String.class); + log.trace("postInterrogations: campaignId={} - response={} ",campaignId,response); + } + + @Override + public PageResponse getInterrogationToFollowUpPaginated(String partitionId, long page, Optional isToFollowUp) { + log.debug("partitionId={} - page={} - pageSizeGetInterro={} - isToFollowUp={}",partitionId,page,pageSizeGetInterro,isToFollowUp); + ParameterizedTypeReference> typeReference = new ParameterizedTypeReference<>() { }; + try { + PageResponse response = restClientHelper.getRestClient(API) + .get() + .uri(uriBuilder -> uriBuilder + .path("/interrogations") + .queryParam("page", page) + .queryParam("size", pageSizeGetInterro) + .queryParam("partition_id", partitionId) + .queryParamIfPresent("follow-up", isToFollowUp) + .build()) + .retrieve() + .body(typeReference); + if(response==null){ + response=new PageResponse<>(); + } + log.trace("partitionId={} - page={} - pageSizeGetInterro={} - response={} ", partitionId,page,pageSizeGetInterro, response.getContent().size()); + return response; + } + catch (HttpClient4xxBPMNError e){ + if(e.getHttpStatusCodeError().equals(HttpStatus.NOT_FOUND)){ + String msg= + "Error 404/NOT_FOUND during Platine Pilotage getInterrogationToFollowUpPaginated with partitionId="+partitionId + + " - msg="+e.getMessage(); + log.error(msg); + throw new HttpClient4xxBPMNError(msg,e.getHttpStatusCodeError()); + } + //Currently no remediation so just rethrow + throw e; + } + } +} diff --git a/src/main/java/fr/insee/protools/backend/service/platine/service/PlatineQuestionnaireServiceImpl.java b/src/main/java/fr/insee/protools/backend/service/platine/service/PlatineQuestionnaireServiceImpl.java new file mode 100644 index 00000000..65da9e03 --- /dev/null +++ b/src/main/java/fr/insee/protools/backend/service/platine/service/PlatineQuestionnaireServiceImpl.java @@ -0,0 +1,49 @@ +package fr.insee.protools.backend.service.platine.service; + +import com.fasterxml.jackson.databind.JsonNode; +import fr.insee.protools.backend.restclient.RestClientHelper; +import fr.insee.protools.backend.restclient.configuration.ApiConfigProperties; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.slf4j.event.Level; +import org.springframework.stereotype.Service; + +import java.util.List; + +import static fr.insee.protools.backend.logging.LoggingHelper.logJson; +import static fr.insee.protools.backend.restclient.configuration.ApiConfigProperties.KNOWN_API.KNOWN_API_PLATINE_QUESTIONNAIRE; + +@Service +@Slf4j +@RequiredArgsConstructor +public class PlatineQuestionnaireServiceImpl implements IPlatineQuestionnaireService{ + + private final RestClientHelper restClientHelper; + private static final ApiConfigProperties.KNOWN_API API= KNOWN_API_PLATINE_QUESTIONNAIRE; + + @Override + public void postContext(String campaignId, JsonNode contextRootNode) { + log.trace("postContext: campaignId={}",campaignId); + var response = restClientHelper.getRestClient(API) + .post() + .uri("/context") + .body(contextRootNode) + .retrieve() + .body(String.class); + log.trace("postContext: campaignId={} - response={} ",campaignId,response); + } + + @Override + public void postInterrogations(String campaignId, List interrogations) { + log.trace("postInterrogations: campaignId={}",campaignId); + logJson("putQuestionings ",interrogations,log,Level.TRACE); + var response = restClientHelper.getRestClient(API) + .post() + .uri("/interrogations") + .body(interrogations) + .retrieve() + .body(String.class); + log.trace("postInterrogations: campaignId={} - response={} ",campaignId,response); + } + +} diff --git a/src/main/java/fr/insee/protools/backend/service/platine/utils/PlatineHelper.java b/src/main/java/fr/insee/protools/backend/service/platine/utils/PlatineHelper.java deleted file mode 100644 index 15fd4eee..00000000 --- a/src/main/java/fr/insee/protools/backend/service/platine/utils/PlatineHelper.java +++ /dev/null @@ -1,33 +0,0 @@ -package fr.insee.protools.backend.service.platine.utils; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import fr.insee.protools.backend.service.exception.IncorrectSUBPMNError; -import fr.insee.protools.backend.dto.rem.REMSurveyUnitDto; - -public class PlatineHelper { - - //In platine pilotage, partition ID must start by the campaignId. We decide to follow it with the configured REM partitionID - public static String computePilotagePartitionID(String campaignId, Long partitionId){ - if(campaignId==null||partitionId==null){ - return null; - } - return campaignId+partitionId; - } - - public static REMSurveyUnitDto parseRemSUNode(ObjectMapper objectMapper, String key , JsonNode remSUNode){ - REMSurveyUnitDto remSurveyUnitDto; - try { - remSurveyUnitDto = objectMapper.treeToValue(remSUNode, REMSurveyUnitDto.class); - } catch (JsonProcessingException e) { - throw new IncorrectSUBPMNError("Error while parsing the json retrieved from REM : " + key,remSUNode, e); - } - - if(remSurveyUnitDto.getRepositoryId()==null){ - throw new IncorrectSUBPMNError("Error json retrieved from REM has no repositoryId : " + key,remSUNode); - } - return remSurveyUnitDto; - } - private PlatineHelper(){} -} diff --git a/src/main/java/fr/insee/protools/backend/service/questionnaire_model/QuestionnaireModelFromStaticWebsiteServiceImpl.java b/src/main/java/fr/insee/protools/backend/service/questionnaire_model/QuestionnaireModelFromStaticWebsiteServiceImpl.java deleted file mode 100644 index c1c40fbd..00000000 --- a/src/main/java/fr/insee/protools/backend/service/questionnaire_model/QuestionnaireModelFromStaticWebsiteServiceImpl.java +++ /dev/null @@ -1,47 +0,0 @@ -package fr.insee.protools.backend.service.questionnaire_model; - -import fr.insee.protools.backend.service.context.exception.BadContextIncorrectBPMNError; -import fr.insee.protools.backend.webclient.WebClientHelper; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Service; - -import java.net.URI; -import java.net.URISyntaxException; - -/** - * This service retrieves the nomenclatures from a static website based on a property uri - */ -@Service -@Slf4j -@RequiredArgsConstructor -public class QuestionnaireModelFromStaticWebsiteServiceImpl implements QuestionnaireModelService { - - //TODO : expose mandatory configuration? - private final WebClientHelper webClientHelper; - - @Value("${fr.insee.protools.questionnaire.model.uri}") - private String questionnaireModelUri; - - - @Override - public String getQuestionnaireModel(String questionnaireModelId, String folderPath){ - log.info("Get Questionnaire Model Value for questionnaireModelId={}", questionnaireModelId); - String uri; - String fullPath=questionnaireModelUri+"/" +folderPath+ "/"+questionnaireModelId + ".json"; - try { - uri = new URI(fullPath).normalize().toString(); - } catch (URISyntaxException e) { - throw new BadContextIncorrectBPMNError(String.format("questionnaireModelId=[%s] - folderPath=[%s] : fullPath=[%s] cannot be parsed: Error=[%s]" - ,questionnaireModelId,folderPath,fullPath, e.getMessage())); - } - return - webClientHelper.getWebClientForFile() - .get() - .uri(uri) - .retrieve() - .bodyToMono(String.class) - .block(); - } -} diff --git a/src/main/java/fr/insee/protools/backend/service/questionnaire_model/QuestionnaireModelService.java b/src/main/java/fr/insee/protools/backend/service/questionnaire_model/QuestionnaireModelService.java deleted file mode 100644 index 88d402e5..00000000 --- a/src/main/java/fr/insee/protools/backend/service/questionnaire_model/QuestionnaireModelService.java +++ /dev/null @@ -1,14 +0,0 @@ -package fr.insee.protools.backend.service.questionnaire_model; - -public interface QuestionnaireModelService { - - /** - * Returns the questionnaire model associated with stored at - * @param questionnaireModelId - * @param folderPath - * @return the questionnaire model content retrieved from external source - */ - String getQuestionnaireModel(String questionnaireModelId, String folderPath); - - -} diff --git a/src/main/java/fr/insee/protools/backend/service/rem/IRemService.java b/src/main/java/fr/insee/protools/backend/service/rem/IRemService.java new file mode 100644 index 00000000..6a8dbe9c --- /dev/null +++ b/src/main/java/fr/insee/protools/backend/service/rem/IRemService.java @@ -0,0 +1,20 @@ +package fr.insee.protools.backend.service.rem; + +import com.fasterxml.jackson.databind.JsonNode; +import fr.insee.protools.backend.restclient.pagination.PageResponse; + +import java.util.List; +import java.util.Map; + +public interface IRemService { + + PageResponse getPartitionAllInterroPaginated(String partitionId, long page); + + List getInterrogationIdsWithoutAccountForPartition(String partitionId); + + void patchInterrogationsSetAccounts(Map userByInterroId); + + void putContactsPlatine(List contactPlatineList); + + void postRemiseEnCollecte(List interroRemiseEnCollecteList); +} \ No newline at end of file diff --git a/src/main/java/fr/insee/protools/backend/service/rem/RemDtoUtils.java b/src/main/java/fr/insee/protools/backend/service/rem/RemDtoUtils.java deleted file mode 100644 index db60c1c2..00000000 --- a/src/main/java/fr/insee/protools/backend/service/rem/RemDtoUtils.java +++ /dev/null @@ -1,113 +0,0 @@ -package fr.insee.protools.backend.service.rem; - -import com.fasterxml.jackson.databind.JsonNode; -import fr.insee.protools.backend.service.exception.IncorrectSUBPMNError; -import fr.insee.protools.backend.dto.rem.PersonDto; -import fr.insee.protools.backend.dto.rem.REMSurveyUnitDto; -import org.apache.commons.lang3.tuple.Pair; - -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; - -public class RemDtoUtils { - private RemDtoUtils(){} - - - private static final String REM_ADDITIONALINFOS = "additionalInformations"; - private static final String REM_ADDITIONALINFOS_KEY = "key"; - private static final String REM_ADDITIONALINFOS_VALUE = "value"; - - public static final String REM_ADDITIONALINFOS_POLE_GESTION_OPALE = "pole_gestion_opale"; - - /** - * Search for the right contact according to the SU Type : - * For Logement : Find the first person flagged as Main - * For Individu : Find the first person flagged as Surveyed - * @param remSUNode : Used only to add it to exception in case of error - * @param remSurveyUnitDto - * @param isLogement true if logement (false if individu) - * @return the contact to be used - */ - public static PersonDto findContact(JsonNode remSUNode, REMSurveyUnitDto remSurveyUnitDto, boolean isLogement) { - //Search for right contact - PersonDto contact; - //SU Logement - if (isLogement) { - //We use the "main" person (actually it is the Declarant) - contact = remSurveyUnitDto.getPersons().stream() - .filter(personDto -> (Boolean.TRUE.equals(personDto.getMain()))) - .findFirst().orElseThrow(() -> new IncorrectSUBPMNError("No main person found in SU [id=" + remSurveyUnitDto.getRepositoryId() + "]", remSUNode)); - } - //SU INDIVIDU - else { - contact = remSurveyUnitDto.getPersons().stream() - .filter(personDto -> (Boolean.TRUE.equals(personDto.getSurveyed()))) - .findFirst().orElseThrow(() -> new IncorrectSUBPMNError("No surveyed person found in SU [id="+ remSurveyUnitDto.getRepositoryId()+"]", remSUNode)); - } - return contact; - } - - - /** - * Search for the right Main contact according to the SU Type : - * For Logement : Find the first person flagged as Main + The Co-declarant - * For Individu : Find the first person flagged as Surveyed + either the declarant or the co-declarant - * - * @param remSUNode : Used only to add it to exception in case of error - * @param remSurveyUnitDto - * @param isLogement true if logement (false if individu) - * @return A pair with the contacts; Secondary one is optional - */ - public static Pair> findContactAndSecondary(JsonNode remSUNode, REMSurveyUnitDto remSurveyUnitDto, boolean isLogement) { - //Search for right contact - PersonDto mainContact = findContact(remSUNode, remSurveyUnitDto, isLogement); - PersonDto secondaryContact; - - List remainingPersons = new ArrayList<>(remSurveyUnitDto.getPersons()); - remainingPersons.remove(mainContact); - - if(remainingPersons.isEmpty()) - return Pair.of(mainContact,Optional.ofNullable(null)); - - - //SU Logement - if (isLogement) { - //Secondary is the co-declarant - secondaryContact = remSurveyUnitDto.getPersons().stream() - .filter(personDto -> (Boolean.TRUE.equals(personDto.getCoDeclarant()))) - .findFirst().orElse(null); - } - //SU INDIVIDU - else { - //If main contact is declarant ==> secondary is the co-declarant - if(Boolean.TRUE.equals(mainContact.getMain())){ - secondaryContact = remSurveyUnitDto.getPersons().stream() - .filter(personDto -> (Boolean.TRUE.equals(personDto.getCoDeclarant()))) - .findFirst().orElse(null); - } - //else ==> secondary is the declarant (main==true) - else{ - secondaryContact = remSurveyUnitDto.getPersons().stream() - .filter(personDto -> (Boolean.TRUE.equals(personDto.getMain()))) - .findFirst().orElse(null); - } - } - return Pair.of(mainContact,Optional.ofNullable(secondaryContact)); - } - - - public static Optional searchAdditionalInformation(String searchedKey,JsonNode remSUNode){ - JsonNode additionalInfoNode = remSUNode.path(REM_ADDITIONALINFOS); - if (additionalInfoNode!=null && additionalInfoNode.isArray()) { - for (JsonNode jsonNode : additionalInfoNode) { - String key = jsonNode.path(REM_ADDITIONALINFOS_KEY).asText(); - if(key.equalsIgnoreCase(searchedKey)){ - String value=jsonNode.path(REM_ADDITIONALINFOS_VALUE).asText(); - return Optional.of(value); - } - } - } - return Optional.empty(); - } -} diff --git a/src/main/java/fr/insee/protools/backend/service/rem/RemService.java b/src/main/java/fr/insee/protools/backend/service/rem/RemService.java deleted file mode 100644 index 7ce94ce9..00000000 --- a/src/main/java/fr/insee/protools/backend/service/rem/RemService.java +++ /dev/null @@ -1,114 +0,0 @@ -package fr.insee.protools.backend.service.rem; - -import fr.insee.protools.backend.dto.era.CensusJsonDto; -import fr.insee.protools.backend.dto.rem.REMSurveyUnitDto; -import fr.insee.protools.backend.dto.rem.SuIdMappingJson; -import fr.insee.protools.backend.webclient.WebClientHelper; -import fr.insee.protools.backend.webclient.exception.runtime.WebClient4xxBPMNError; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.http.HttpStatus; -import org.springframework.stereotype.Service; - -import java.util.List; - -import static fr.insee.protools.backend.webclient.configuration.ApiConfigProperties.KNOWN_API.KNOWN_API_REM; - -@Service -@Slf4j -@RequiredArgsConstructor -public class RemService { - - private final WebClientHelper webClientHelper; - - public Long[] getSampleSuIds(Long partitionId) { - log.debug("getSampleSuIds - partitionId={} ",partitionId); - try { - var response = webClientHelper.getWebClient(KNOWN_API_REM) - .get() - .uri(uriBuilder -> uriBuilder - .path("/survey-units/partitions/{partitionId}/ids") - .build(partitionId)) - .retrieve() - .bodyToMono(Long[].class) - .block(); - log.trace("partitionIds={} - response={} ", partitionId, response); - return response; - } - catch (WebClient4xxBPMNError e){ - if(e.getHttpStatusCodeError().equals(HttpStatus.NOT_FOUND)){ - String msg= - "Error 404/NOT_FOUND during get sample on REM with partitionId="+partitionId - + " - msg="+e.getMessage(); - log.error(msg); - throw new WebClient4xxBPMNError(msg,e.getHttpStatusCodeError()); - } - //Currently no remediation so just rethrow - throw e; - } - } - - public REMSurveyUnitDto getSurveyUnit(Long surveyUnitId ) { - log.debug("getSurveyUnit - surveyUnitId ={}",surveyUnitId ); - try { - var response = webClientHelper.getWebClient(KNOWN_API_REM) - .get() - .uri(uriBuilder -> uriBuilder - .path("/survey-units/{surveyUnitId}") - .queryParam("withExternals", true) - .build(surveyUnitId)) - .retrieve() - .bodyToMono(REMSurveyUnitDto.class) - .block(); - log.trace("surveyUnitId={} - response={} ", surveyUnitId, response); - return response; - } - catch (WebClient4xxBPMNError e){ - if(e.getHttpStatusCodeError().equals(HttpStatus.NOT_FOUND)){ - String msg= - "Error 404/NOT_FOUND during get SU on REM with surveyUnitId="+surveyUnitId - + " - msg="+e.getMessage(); - log.error(msg); - throw new WebClient4xxBPMNError(msg,e.getHttpStatusCodeError()); - } - //Currently no remediation so just rethrow - throw e; - } - } - - /** - * @param partitionId - * @param values - * @return return null if values is null ; else return the result of the api call - */ - public SuIdMappingJson writeERASUList(long partitionId, List values) { - log.debug("writeERASUList - partitionId={} - values.size={}", partitionId, values == null ? 0 : values.size()); - if (values == null) { - log.debug("writeERASUList - partitionId={} - values==null ==> Nothing to do"); - return null; - } - try { - var response = webClientHelper.getWebClient(KNOWN_API_REM) - .post() - .uri(uriBuilder -> uriBuilder - .path("/survey-units/households/partitions/{partitionId}/census-upload") - .build(partitionId)) - .bodyValue(values) - .retrieve() - .bodyToMono(SuIdMappingJson.class) - .block(); - log.trace("writeERASUList - partitionId={} - response={} ", partitionId, response); - return response; - } catch (WebClient4xxBPMNError e) { - if (e.getHttpStatusCodeError().equals(HttpStatus.NOT_FOUND)) { - String msg = - "Error 404/NOT_FOUND during REM post census-upload partitionId=" + partitionId - + " (check that the partition exists in REM) - msg=" + e.getMessage(); - log.error(msg); - throw new WebClient4xxBPMNError(msg, e.getHttpStatusCodeError()); - } - //Currently no remediation so just rethrow - throw e; - } - } -} diff --git a/src/main/java/fr/insee/protools/backend/service/rem/RemServiceImpl.java b/src/main/java/fr/insee/protools/backend/service/rem/RemServiceImpl.java new file mode 100644 index 00000000..c3407af5 --- /dev/null +++ b/src/main/java/fr/insee/protools/backend/service/rem/RemServiceImpl.java @@ -0,0 +1,153 @@ +package fr.insee.protools.backend.service.rem; + +import com.fasterxml.jackson.databind.JsonNode; +import fr.insee.protools.backend.dto.rem_tmp.InterrogationAccountDto; +import fr.insee.protools.backend.dto.rem_tmp.InterrogationIdentifiersDto; +import fr.insee.protools.backend.restclient.RestClientHelper; +import fr.insee.protools.backend.restclient.configuration.ApiConfigProperties; +import fr.insee.protools.backend.restclient.exception.runtime.HttpClient4xxBPMNError; +import fr.insee.protools.backend.restclient.pagination.PageResponse; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import static fr.insee.protools.backend.restclient.configuration.ApiConfigProperties.KNOWN_API.KNOWN_API_REM; + +@Service +@Slf4j +@RequiredArgsConstructor +public class RemServiceImpl implements IRemService{ + + private static final ApiConfigProperties.KNOWN_API API = KNOWN_API_REM; + private final RestClientHelper restClientHelper; + @Value("${fr.insee.protools.api.rem.interrogation.page.size:5000}") + private int pageSizeGetInterro; + + public PageResponse getPartitionAllInterroPaginated(String partitionId, long page) { + log.debug("partitionId={} - page={} - pageSizeGetInterro={} }", partitionId, page, pageSizeGetInterro); + ParameterizedTypeReference> typeReference = new ParameterizedTypeReference<>() { + }; + try { + PageResponse response = restClientHelper.getRestClient(API) + .get() + .uri(uriBuilder -> uriBuilder + .path("/interrogations") + .queryParam("page", page) + .queryParam("size", pageSizeGetInterro) + .queryParam("partition_id", partitionId) + .build()) + .retrieve() + .body(typeReference); + if(response==null){ + response=new PageResponse<>(); + } + log.trace("partitionId={} - page={} - pageSizeGetInterro={} - response={} ", partitionId, page, pageSizeGetInterro, response.getContent().size()); + return response; + } catch (HttpClient4xxBPMNError e) { + if (e.getHttpStatusCodeError().equals(HttpStatus.NOT_FOUND)) { + String msg = + "Error 404/NOT_FOUND during get sample on REM with partitionId=" + partitionId + + " - msg=" + e.getMessage(); + log.error(msg); + throw new HttpClient4xxBPMNError(msg, e.getHttpStatusCodeError()); + } + //Currently no remediation so just rethrow + throw e; + } + } + + public List getInterrogationIdsWithoutAccountForPartition(String partitionId) { + log.debug("getSampleSuIds - partitionId={} ", partitionId); + ParameterizedTypeReference> typeReference = new ParameterizedTypeReference>() { + }; + + try { + List response = restClientHelper.getRestClient(API) + .get() + .uri(uriBuilder -> uriBuilder + .path("/interrogations/ids") + .queryParam("partition_id", partitionId) + .queryParam("hasAccount", false) + .build()) + .retrieve() + .body(typeReference); + + List interrogationIdsWithoutAccount = + response.stream() + .map(InterrogationIdentifiersDto::getInterrogationId) + .map(UUID::toString).toList(); + + log.trace("partitionId={} - interrogationIdsWithoutAccount={} ", partitionId, interrogationIdsWithoutAccount); + return interrogationIdsWithoutAccount; + } catch (HttpClient4xxBPMNError e) { + if (e.getHttpStatusCodeError().equals(HttpStatus.NOT_FOUND)) { + String msg = + "Error 404/NOT_FOUND during get lot interrogations ids on REM with partitionId=" + partitionId + + " - msg=" + e.getMessage(); + log.error(msg); + throw new HttpClient4xxBPMNError(msg, e.getHttpStatusCodeError()); + } + //Currently no remediation so just rethrow + throw e; + } + } + + public void patchInterrogationsSetAccounts(Map userByInterroId) { + log.debug("patchInterrogationsSetAccounts - userByInterroId.size={}", userByInterroId.size()); + + List remDto = userByInterroId.entrySet() + .stream() + .map(entry -> InterrogationAccountDto.builder() + .interrogationId(UUID.fromString(entry.getKey())) + .account(entry.getValue()) + .build()) + .toList(); + + var response = restClientHelper.getRestClient(API) + .patch() + .uri("/interrogations/account") + .body(remDto) + .retrieve() + .body(String.class); + log.trace("patchInterrogationsSetAccounts - response={} ", response); + } + + public void putContactsPlatine(List contactPlatineList) { + if (contactPlatineList == null || contactPlatineList.isEmpty()) { + log.debug("putContactsPlatine ==> Nothing to do"); + return; + } + + log.debug("putContactsPlatine - contactPlatineList.size={}", contactPlatineList); + var response = restClientHelper.getRestClient(API) + .put() + .uri("/contacts-platine") + .body(contactPlatineList) + .retrieve() + .body(String.class); + log.trace("putContactsPlatine - response={} ", response); + } + + public void postRemiseEnCollecte(List interroRemiseEnCollecteList) { + if (interroRemiseEnCollecteList == null || interroRemiseEnCollecteList.isEmpty()) { + log.debug("postRemiseEnCollecte ==> Nothing to do"); + return; + } + + log.debug("postRemiseEnCollecte - interroRemiseEnCollecteList.size={}", interroRemiseEnCollecteList); + var response = restClientHelper.getRestClient(API) + .post() + .uri("/remise-en-collecte") + .body(interroRemiseEnCollecteList) + .retrieve() + .body(String.class); + log.trace("postRemiseEnCollecte - response={} ", response); + } +} diff --git a/src/main/java/fr/insee/protools/backend/service/rem/delegate/ExtractContactIdentifierFromREMSUTask.java b/src/main/java/fr/insee/protools/backend/service/rem/delegate/ExtractContactIdentifierFromREMSUTask.java deleted file mode 100644 index 29b7374a..00000000 --- a/src/main/java/fr/insee/protools/backend/service/rem/delegate/ExtractContactIdentifierFromREMSUTask.java +++ /dev/null @@ -1,47 +0,0 @@ -package fr.insee.protools.backend.service.rem.delegate; - -import com.fasterxml.jackson.databind.JsonNode; -import fr.insee.protools.backend.service.exception.IncorrectSUBPMNError; -import fr.insee.protools.backend.service.rem.RemDtoUtils; -import fr.insee.protools.backend.service.utils.FlowableVariableUtils; -import lombok.extern.slf4j.Slf4j; -import org.flowable.engine.delegate.DelegateExecution; -import org.flowable.engine.delegate.JavaDelegate; -import org.springframework.stereotype.Component; - -import java.util.Optional; - -import static fr.insee.protools.backend.service.FlowableVariableNameConstants.VARNAME_DIRECTORYACCESS_ID_CONTACT; -import static fr.insee.protools.backend.service.FlowableVariableNameConstants.VARNAME_REM_SURVEY_UNIT; - -/** - * This delegate will search for the identifiantCompte (internet identifier) in a REM SU - * additional information. - */ -@Component -@Slf4j -public class ExtractContactIdentifierFromREMSUTask implements JavaDelegate { - - private static final String REM_ADDITIONALINFOS_KEY_IDENTIFIANTCOMPTE = "identifiantCompte"; - private static final String REM_REPOSITORY_ID = "repositoryId"; - private static final String REM_EXTERNAL_ID = "externalId"; - - @Override - public void execute(DelegateExecution execution) { - //No need protools context ==> no checkContextOrThrow - log.debug("ProcessInstanceId={} - begin",execution.getProcessInstanceId()); - JsonNode remSUNode = FlowableVariableUtils.getVariableOrThrow(execution,VARNAME_REM_SURVEY_UNIT, JsonNode.class); - - Optional optionalIdentifiantCompte = RemDtoUtils.searchAdditionalInformation(REM_ADDITIONALINFOS_KEY_IDENTIFIANTCOMPTE,remSUNode); - String idInternaute = optionalIdentifiantCompte.orElseThrow(() -> { - String repositoryId = remSUNode.path(REM_REPOSITORY_ID).asText(); - String externalId = remSUNode.path(REM_EXTERNAL_ID).asText(); - String msg = String.format("No identifiantCompte found for REM repositoryId=%s - externalId=%s",repositoryId,externalId); - log.error(msg); - throw new IncorrectSUBPMNError(msg); - }); - execution.setVariableLocal(VARNAME_DIRECTORYACCESS_ID_CONTACT,idInternaute); - - log.debug("ProcessInstanceId={} - idInternaute="+idInternaute+" end", execution.getProcessInstanceId()); - } -} diff --git a/src/main/java/fr/insee/protools/backend/service/rem/delegate/RemGetPartitionListOfInterroPaginatedTask.java b/src/main/java/fr/insee/protools/backend/service/rem/delegate/RemGetPartitionListOfInterroPaginatedTask.java new file mode 100644 index 00000000..6c3834a7 --- /dev/null +++ b/src/main/java/fr/insee/protools/backend/service/rem/delegate/RemGetPartitionListOfInterroPaginatedTask.java @@ -0,0 +1,51 @@ +package fr.insee.protools.backend.service.rem.delegate; + +import com.fasterxml.jackson.databind.JsonNode; +import fr.insee.protools.backend.restclient.pagination.PageResponse; +import fr.insee.protools.backend.service.DelegateContextVerifier; +import fr.insee.protools.backend.service.rem.IRemService; +import fr.insee.protools.backend.service.utils.FlowableVariableUtils; +import fr.insee.protools.backend.service.utils.delegate.PaginationHelper; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import org.flowable.engine.delegate.DelegateExecution; +import org.flowable.engine.delegate.JavaDelegate; +import org.slf4j.Logger; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static fr.insee.protools.backend.service.FlowableVariableNameConstants.*; + +@Slf4j +@Component +@Data +public class RemGetPartitionListOfInterroPaginatedTask implements JavaDelegate, DelegateContextVerifier, PaginationHelper { + + IRemService remService; + + private PageResponse readFunction(Integer pageToRead, Object... objects) { + String partitionId = (String) objects[0]; + return remService.getPartitionAllInterroPaginated(partitionId, pageToRead); + } + + @Override + public void execute(DelegateExecution execution) { + String currentPartitionId = FlowableVariableUtils.getVariableOrThrow(execution, VARNAME_CURRENT_PARTITION_ID, String.class); + getAndTreat(execution, VARNAME_INTERRO_LIST_PAGEABLE_CURRENT_PAGE, VARNAME_INTERRO_LIST_PAGEABLE_IS_LAST_PAGE, this::readFunction, currentPartitionId); + } + + @Override + public Logger getLogger() { + return log; + } + + @Override + public Map treatPage(DelegateExecution execution, List contentList) { + Map variables = new HashMap<>(); + variables.put(VARNAME_REM_INTERRO_LIST, contentList); + return variables; + } +} \ No newline at end of file diff --git a/src/main/java/fr/insee/protools/backend/service/rem/delegate/RemGetPartitionListOfSuIdTask.java b/src/main/java/fr/insee/protools/backend/service/rem/delegate/RemGetPartitionListOfSuIdTask.java deleted file mode 100644 index 07475f1c..00000000 --- a/src/main/java/fr/insee/protools/backend/service/rem/delegate/RemGetPartitionListOfSuIdTask.java +++ /dev/null @@ -1,35 +0,0 @@ -package fr.insee.protools.backend.service.rem.delegate; - -import fr.insee.protools.backend.service.DelegateContextVerifier; -import fr.insee.protools.backend.service.rem.RemService; -import fr.insee.protools.backend.service.utils.FlowableVariableUtils; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.flowable.engine.delegate.DelegateExecution; -import org.flowable.engine.delegate.JavaDelegate; -import org.springframework.stereotype.Component; - -import java.util.List; - -import static fr.insee.protools.backend.service.FlowableVariableNameConstants.VARNAME_CURRENT_PARTITION_ID; -import static fr.insee.protools.backend.service.FlowableVariableNameConstants.VARNAME_REM_SU_ID_LIST; - -@Slf4j -@Component -@RequiredArgsConstructor -public class RemGetPartitionListOfSuIdTask implements JavaDelegate, DelegateContextVerifier { - - private final RemService remService; - - @Override - public void execute(DelegateExecution execution) { - Long currentPartitionId = FlowableVariableUtils.getVariableOrThrow(execution,VARNAME_CURRENT_PARTITION_ID, Long.class); - //No need protools context ==> no checkContextOrThrow - log.info("ProcessInstanceId={} - partition={} begin",execution.getProcessInstanceId(),currentPartitionId); - - Long[] partitionSUIds = remService.getSampleSuIds(currentPartitionId); - List remSuIdList = List.of(partitionSUIds); - execution.getParent().setVariableLocal(VARNAME_REM_SU_ID_LIST, remSuIdList); - log.debug("ProcessInstanceId={} - partition={} - remSuIdList={} end",execution.getProcessInstanceId(),currentPartitionId,remSuIdList); - } -} \ No newline at end of file diff --git a/src/main/java/fr/insee/protools/backend/service/rem/delegate/RemGetSUTask.java b/src/main/java/fr/insee/protools/backend/service/rem/delegate/RemGetSUTask.java deleted file mode 100644 index e064c61d..00000000 --- a/src/main/java/fr/insee/protools/backend/service/rem/delegate/RemGetSUTask.java +++ /dev/null @@ -1,38 +0,0 @@ -package fr.insee.protools.backend.service.rem.delegate; - -import com.fasterxml.jackson.databind.ObjectMapper; -import fr.insee.protools.backend.dto.rem.REMSurveyUnitDto; -import fr.insee.protools.backend.service.DelegateContextVerifier; -import fr.insee.protools.backend.service.rem.RemService; -import fr.insee.protools.backend.service.utils.FlowableVariableUtils; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.flowable.engine.delegate.DelegateExecution; -import org.flowable.engine.delegate.JavaDelegate; -import org.springframework.stereotype.Component; - -import static fr.insee.protools.backend.service.FlowableVariableNameConstants.VARNAME_REM_SURVEY_UNIT; -import static fr.insee.protools.backend.service.FlowableVariableNameConstants.VARNAME_REM_SURVEY_UNIT_IDENTIFIER; - -@Slf4j -@Component -@RequiredArgsConstructor -public class RemGetSUTask implements JavaDelegate, DelegateContextVerifier { - - private final RemService remService; - private final ObjectMapper objectMapper; - - @Override - public void execute(DelegateExecution execution) { - //No need context - - //Get the UE - Long suId = FlowableVariableUtils.getVariableOrThrow(execution,VARNAME_REM_SURVEY_UNIT_IDENTIFIER, Long.class); - log.info("ProcessInstanceId={} - suId={}",execution.getProcessInstanceId(), suId); - //TODO : ne pas créer le DTO ici : Ca ne sert à rien... - REMSurveyUnitDto remSurveyUnitDto = remService.getSurveyUnit(suId); - execution.setVariableLocal(VARNAME_REM_SURVEY_UNIT,objectMapper.valueToTree(remSurveyUnitDto)); - log.trace("suId={} - content={}", suId, remSurveyUnitDto); - log.debug("ProcessInstanceId={} - suId={} end",execution.getProcessInstanceId(), suId); - } -} \ No newline at end of file diff --git a/src/main/java/fr/insee/protools/backend/service/rem/delegate/RemPostResmiseEnCollecteTaskREST.java b/src/main/java/fr/insee/protools/backend/service/rem/delegate/RemPostResmiseEnCollecteTaskREST.java new file mode 100644 index 00000000..3703d712 --- /dev/null +++ b/src/main/java/fr/insee/protools/backend/service/rem/delegate/RemPostResmiseEnCollecteTaskREST.java @@ -0,0 +1,41 @@ +package fr.insee.protools.backend.service.rem.delegate; + +import com.fasterxml.jackson.databind.JsonNode; +import fr.insee.protools.backend.service.DelegateContextVerifier; +import fr.insee.protools.backend.service.rem.IRemService; +import fr.insee.protools.backend.service.utils.FlowableVariableUtils; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.flowable.engine.delegate.DelegateExecution; +import org.flowable.engine.delegate.JavaDelegate; +import org.springframework.stereotype.Component; + +import java.util.List; + +import static fr.insee.protools.backend.service.FlowableVariableNameConstants.VARNAME_INTERRO_REMISE_EN_COLLECTE_LIST; + +@Slf4j +@Component +@RequiredArgsConstructor +public class RemPostResmiseEnCollecteTaskREST implements JavaDelegate, DelegateContextVerifier { + + private final IRemService remService; + + @Override + public void execute(DelegateExecution execution) { + log.info("ProcessInstanceId={} begin", execution.getProcessInstanceId()); + + //Get the contacts + List interroRemiseEnCollecteList = FlowableVariableUtils.getVariableOrThrow(execution, VARNAME_INTERRO_REMISE_EN_COLLECTE_LIST, List.class); + //If nothing to do ==> Directly return + if(interroRemiseEnCollecteList.isEmpty()){ + log.info("ProcessInstanceId={} - end : Nothing to do", + execution.getProcessInstanceId()); + return; + } + + remService.postRemiseEnCollecte(interroRemiseEnCollecteList); + log.info("ProcessInstanceId={} end", execution.getProcessInstanceId()); + } + +} \ No newline at end of file diff --git a/src/main/java/fr/insee/protools/backend/service/rem/delegate/RemPutContactPlatineTaskREST.java b/src/main/java/fr/insee/protools/backend/service/rem/delegate/RemPutContactPlatineTaskREST.java new file mode 100644 index 00000000..b68e1356 --- /dev/null +++ b/src/main/java/fr/insee/protools/backend/service/rem/delegate/RemPutContactPlatineTaskREST.java @@ -0,0 +1,42 @@ +package fr.insee.protools.backend.service.rem.delegate; + +import com.fasterxml.jackson.databind.JsonNode; +import fr.insee.protools.backend.service.DelegateContextVerifier; +import fr.insee.protools.backend.service.rem.IRemService; +import fr.insee.protools.backend.service.utils.FlowableVariableUtils; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.flowable.engine.delegate.DelegateExecution; +import org.flowable.engine.delegate.JavaDelegate; +import org.springframework.stereotype.Component; + +import java.util.List; + +import static fr.insee.protools.backend.service.FlowableVariableNameConstants.VARNAME_PLATINE_CONTACT_LIST; + +@Slf4j +@Component +@RequiredArgsConstructor +public class RemPutContactPlatineTaskREST implements JavaDelegate, DelegateContextVerifier { + + private final IRemService remService; + + @Override + public void execute(DelegateExecution execution) { + log.info("ProcessInstanceId={} begin", execution.getProcessInstanceId()); + + //Get the contacts + List contactPlatineList = FlowableVariableUtils.getVariableOrThrow(execution, VARNAME_PLATINE_CONTACT_LIST, List.class); + //If nothing to do ==> Directly return + if(contactPlatineList.isEmpty()){ + log.info("ProcessInstanceId={} - end : Nothing to do", + execution.getProcessInstanceId()); + return; + } + + remService.putContactsPlatine(contactPlatineList); + + log.info("ProcessInstanceId={} end", execution.getProcessInstanceId()); + } + +} \ No newline at end of file diff --git a/src/main/java/fr/insee/protools/backend/service/rem/delegate/RemWriteEraSUListTask.java b/src/main/java/fr/insee/protools/backend/service/rem/delegate/RemWriteEraSUListTask.java deleted file mode 100644 index eb812ed4..00000000 --- a/src/main/java/fr/insee/protools/backend/service/rem/delegate/RemWriteEraSUListTask.java +++ /dev/null @@ -1,54 +0,0 @@ -package fr.insee.protools.backend.service.rem.delegate; - -import fr.insee.protools.backend.dto.era.CensusJsonDto; -import fr.insee.protools.backend.dto.rem.SuIdMappingJson; -import fr.insee.protools.backend.dto.rem.SuIdMappingRecord; -import fr.insee.protools.backend.service.DelegateContextVerifier; -import fr.insee.protools.backend.service.exception.ProtoolsTaskBPMNError; -import fr.insee.protools.backend.service.rem.RemService; -import fr.insee.protools.backend.service.utils.FlowableVariableUtils; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.flowable.engine.delegate.DelegateExecution; -import org.flowable.engine.delegate.JavaDelegate; -import org.springframework.stereotype.Component; - -import java.util.List; - -import static fr.insee.protools.backend.service.FlowableVariableNameConstants.*; - -@Component -@Slf4j -@RequiredArgsConstructor -public class RemWriteEraSUListTask implements JavaDelegate, DelegateContextVerifier { - - private final RemService remService; - - @Override - public void execute(DelegateExecution execution) { - - //Get the list of SU previouly retrieved from ERA - List eraSUList = FlowableVariableUtils.getVariableOrThrow(execution,VARNAME_ERA_RESPONSE, List.class); - //Get current REM partition - Long currentPartitionId = FlowableVariableUtils.getVariableOrThrow(execution,VARNAME_CURRENT_PARTITION_ID, Long.class); - if(eraSUList==null||eraSUList.isEmpty()){ - log.info("ProcessInstanceId={} - currentPartitionId={} - variable {} is empty",execution.getProcessInstanceId(), currentPartitionId,VARNAME_ERA_RESPONSE); - execution.getParent().setVariableLocal(VARNAME_REM_SU_ID_LIST, List.of()); - return; - } - - log.info("ProcessInstanceId={} - currentPartitionId={} - eraSUList.size={} begin",execution.getProcessInstanceId(), currentPartitionId,eraSUList.size()); - //Store SU in REM - SuIdMappingJson remMapping = remService.writeERASUList(currentPartitionId, eraSUList); - if(remMapping==null){ - log.error("ProcessInstanceId={} - currentPartitionId={} remMapping is empty/null end",execution.getProcessInstanceId(), currentPartitionId); - execution.getParent().setVariableLocal(VARNAME_REM_SU_ID_LIST, List.of()); - throw new ProtoolsTaskBPMNError("Error while writing list of Era SU to REM : REM returned a null result "); - } - - //STORE the list of REM identifier created - List remSuIdList = remMapping.getData().stream().map(SuIdMappingRecord::repositoryId).toList(); - execution.getParent().setVariableLocal(VARNAME_REM_SU_ID_LIST, remSuIdList); - log.info("ProcessInstanceId={} - currentPartitionId={} - remSuIdList={} end",execution.getProcessInstanceId(), currentPartitionId,remSuIdList); - } -} diff --git a/src/main/java/fr/insee/protools/backend/service/sabiane/SabianeIdHelper.java b/src/main/java/fr/insee/protools/backend/service/sabiane/SabianeIdHelper.java deleted file mode 100644 index b4b4671d..00000000 --- a/src/main/java/fr/insee/protools/backend/service/sabiane/SabianeIdHelper.java +++ /dev/null @@ -1,15 +0,0 @@ -package fr.insee.protools.backend.service.sabiane; - -import fr.insee.protools.backend.service.exception.IncorrectSUBPMNError; - -public class SabianeIdHelper { - - public static String computeSabianeID(String partitionId, String remRepositoryID){ - if(partitionId!=null && remRepositoryID!=null) - return partitionId + "P" + remRepositoryID; - else - throw new IncorrectSUBPMNError("partitionId and/or remRepositoryID cannot be null to compute sabiane ID"); - } - //Utility class - private SabianeIdHelper(){} -} diff --git a/src/main/java/fr/insee/protools/backend/service/sabiane/delegate/SabianePilotageCreateContextTask.java b/src/main/java/fr/insee/protools/backend/service/sabiane/delegate/SabianePilotageCreateContextTask.java deleted file mode 100644 index eb450cf1..00000000 --- a/src/main/java/fr/insee/protools/backend/service/sabiane/delegate/SabianePilotageCreateContextTask.java +++ /dev/null @@ -1,278 +0,0 @@ -package fr.insee.protools.backend.service.sabiane.delegate; - -import com.fasterxml.jackson.databind.JsonNode; -import fr.insee.protools.backend.dto.sabiane.pilotage.*; -import fr.insee.protools.backend.service.DelegateContextVerifier; -import fr.insee.protools.backend.service.context.ContextService; -import fr.insee.protools.backend.service.context.ContextServiceImpl; -import fr.insee.protools.backend.service.context.exception.BadContextDateTimeParseBPMNError; -import fr.insee.protools.backend.service.sabiane.pilotage.SabianePilotageService; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.flowable.engine.delegate.DelegateExecution; -import org.flowable.engine.delegate.JavaDelegate; -import org.springframework.stereotype.Component; - -import java.time.Instant; -import java.util.*; - -import static fr.insee.protools.backend.service.context.ContextConstants.*; - -@Slf4j -@Component -@RequiredArgsConstructor -public class SabianePilotageCreateContextTask implements JavaDelegate, DelegateContextVerifier { - - private static final String REFERENT_PRIMARY = "PRIMARY"; - private static final String REFERENT_SECONDARY = "SECONDARY"; - private final ContextService protoolsContext; - private final SabianePilotageService sabianePilotageService; - - @Override - public void execute(DelegateExecution execution) { - JsonNode contextRootNode = protoolsContext.getContextByProcessInstance(execution.getProcessInstanceId()); - checkContextOrThrow(log,execution.getProcessInstanceId(), contextRootNode); - - log.info("ProcessInstanceId={} - campagne={}" - ,execution.getProcessInstanceId(),contextRootNode.path(CTX_CAMPAGNE_CONTEXTE).asText()); - - CampaignContextDto dto = computeCampaignContextDto(contextRootNode); - sabianePilotageService.postCampaign(dto); - log.debug("ProcessInstanceId={} end",execution.getProcessInstanceId()); - } - - private CampaignContextDto computeCampaignContextDto(JsonNode contextRootNode) { - - String campaignId = contextRootNode.path(CTX_CAMPAGNE_ID).asText(); - String campaignLabel = contextRootNode.path(CTX_CAMPAGNE_LABEL).asText(); - String campaignAssistanceMail = contextRootNode.path(CTX_METADONNEES).path(CTX_META_ASSISTANCE_NIVO2_MAIL).asText(); - - //TODO : vérifier les valeurs dans le check de la conf - String essaisContact = contextRootNode.path(CTX_METADONNEES).path(CTX_META_ESSAIS_CONTACT).asText(); - ContactAttemptConfiguration contactAttemptConfiguration = ContactAttemptConfiguration.valueOfLabel(essaisContact); - - String bilanContact = contextRootNode.path(CTX_METADONNEES).path(CTX_META_BILAN_CONTACT).asText(); - ContactOutcomeConfiguration contactOutcomeConfiguration = ContactOutcomeConfiguration.valueOfLabel(bilanContact); - - String reperage = contextRootNode.path(CTX_METADONNEES).path(CTX_META_REPERAGE).asText(); - IdentificationConfiguration identificationConfiguration = IdentificationConfiguration.valueOfLabel(reperage); - - List visibilityContextDtos = computeVisibilities(contextRootNode); - List referents = computeReferents(contextRootNode); - - return CampaignContextDto.builder() - .campaign(campaignId) - .campaignLabel(campaignLabel) - .visibilities(visibilityContextDtos) - .referents(referents) - .email(campaignAssistanceMail) - .identificationConfiguration(identificationConfiguration) - .contactOutcomeConfiguration(contactOutcomeConfiguration) - .contactAttemptConfiguration(contactAttemptConfiguration) - .build(); - } - - private List computeReferents(JsonNode contextRootNode) { - JsonNode referentsPrincipauxNode = contextRootNode.path(CTX_METADONNEES).path(CTX_META_REFERENTS_PRINCIPAUX); - JsonNode referentsSecondairesNode = contextRootNode.path(CTX_METADONNEES).path(CTX_META_REFERENTS_SECONDAIRES); - - List result = new ArrayList<>(getReferents(referentsPrincipauxNode.elements(), true)); - result.addAll(getReferents(referentsSecondairesNode.elements(),false)); - return result; - } - - private List getReferents(Iterator refIterator, boolean isPrincipal){ - List result = new ArrayList<>(); - while(refIterator.hasNext()){ - var referentNode = refIterator.next(); - String prenom = referentNode.path(CTX_META_REFERENT_PRENOM).asText(); - String nom = referentNode.path(CTX_META_REFERENT_NOM).asText(); - String telephone = referentNode.path(CTX_META_REFERENT_TELEPHONE).asText(); - String role = (isPrincipal)? REFERENT_PRIMARY : REFERENT_SECONDARY; - result.add(ReferentDto.builder() - .firstName(prenom) - .lastName(nom) - .phoneNumber(telephone) - .role(role) - .build()); - } - return result; - } - - private List computeVisibilities(JsonNode contextRootNode) - { - List result = new ArrayList<>(); - //need to compute mins/maxs of partitions - var partitionIterator =contextRootNode.path(CTX_PARTITIONS).elements(); - - Instant maxDateFinCollecte=null; - Instant minDateDebutCollecte=null; - Instant maxDateFinTraitement=null; - Instant minDateDebutReperage=null; - Instant minDateDebutVisibiliteEnqueteur=null; - Instant maxDateDebutVisibiliteGestionnaire=null; - - while (partitionIterator.hasNext()) { - var partitionNode = partitionIterator.next(); - Instant dateFinCollecte = ContextServiceImpl.getInstantFromPartition(partitionNode,CTX_PARTITION_DATE_FIN_COLLECTE); - Instant dateDebutCollecte = ContextServiceImpl.getInstantFromPartition(partitionNode,CTX_PARTITION_DATE_DEBUT_COLLECTE); - Instant dateFinTraitement = ContextServiceImpl.getInstantFromPartition(partitionNode,CTX_PARTITION_SABIANE_DATE_FIN_TRAITEMENT); - Instant dateDebutReperage = ContextServiceImpl.getInstantFromPartition(partitionNode,CTX_PARTITION_SABIANE_DATE_DEBUT_REPERAGE); - Instant dateDebutVisibiliteEnqueteur = ContextServiceImpl.getInstantFromPartition(partitionNode,CTX_PARTITION_SABIANE_DATE_DEBUT_VISIBILITE_ENQUETEUR); - Instant dateDebutVisibiliteGestionnaire = ContextServiceImpl.getInstantFromPartition(partitionNode,CTX_PARTITION_SABIANE_DATE_DEBUT_VISIBILITE_GESTIONNAIRE); - - if(maxDateFinCollecte==null || maxDateFinCollecte.isBefore(dateFinCollecte)){ - maxDateFinCollecte=dateFinCollecte; - } - - if(minDateDebutCollecte==null || minDateDebutCollecte.isAfter(dateDebutCollecte)){ - minDateDebutCollecte=dateDebutCollecte; - } - - if(maxDateFinTraitement==null || maxDateFinTraitement.isBefore(dateFinTraitement)){ - maxDateFinTraitement=dateFinTraitement; - } - - if(minDateDebutReperage==null || minDateDebutReperage.isAfter(dateDebutReperage)){ - minDateDebutReperage=dateDebutReperage; - } - - if(minDateDebutVisibiliteEnqueteur==null || minDateDebutVisibiliteEnqueteur.isAfter(dateDebutVisibiliteEnqueteur)){ - minDateDebutVisibiliteEnqueteur=dateDebutVisibiliteEnqueteur; - } - - if(maxDateDebutVisibiliteGestionnaire==null || maxDateDebutVisibiliteGestionnaire.isBefore(dateDebutVisibiliteGestionnaire)){ - maxDateDebutVisibiliteGestionnaire=dateDebutVisibiliteGestionnaire; - } - } - - var siteGestionIterator = contextRootNode.path(CTX_METADONNEES).path(CTX_META_SITES_GESTION).elements(); - while(siteGestionIterator.hasNext()){ - JsonNode siteGestion = siteGestionIterator.next(); - VisibilityContextDto visibilityContextDto = VisibilityContextDto.builder() - .collectionEndDate(maxDateFinCollecte.toEpochMilli()) - .collectionStartDate(minDateDebutCollecte.toEpochMilli()) - .endDate(maxDateFinTraitement.toEpochMilli()) - .identificationPhaseStartDate(minDateDebutReperage.toEpochMilli()) - .interviewerStartDate(minDateDebutVisibiliteEnqueteur.toEpochMilli()) - .managementStartDate(maxDateDebutVisibiliteGestionnaire.toEpochMilli()) - .organizationalUnit(siteGestion.asText()) - .build(); - result.add(visibilityContextDto); - } - return result; - } - - @Override - @SuppressWarnings("java:S3776") //disable the warning about cognitive complexity as it is long but simple - public Set getContextErrors(JsonNode contextRootNode) { - if(contextRootNode==null){ - return Set.of("Context is missing"); - } - Set results=new HashSet<>(); - Set requiredNodes = - Set.of( - //Global & Campaign - CTX_METADONNEES, CTX_CAMPAGNE_ID, CTX_CAMPAGNE_LABEL, CTX_CAMPAGNE_CONTEXTE, CTX_PARTITIONS - ); - Set requiredMetadonnees = - Set.of( - CTX_META_LABEL_COURT_OPERATION,CTX_META_LABEL_LONG_OPERATION, - CTX_META_ASSISTANCE_NIVO2_MAIL, - CTX_META_REPERAGE,CTX_META_ESSAIS_CONTACT,CTX_META_BILAN_CONTACT, - CTX_META_REFERENTS_PRINCIPAUX, CTX_META_REFERENTS_SECONDAIRES, - //array with at least one element - CTX_META_SITES_GESTION - ); - Set requiredReferent = - Set.of(CTX_META_REFERENT_NOM,CTX_META_REFERENT_PRENOM,CTX_META_REFERENT_TELEPHONE); - Set requiredPartitionDates= - Set.of(CTX_PARTITION_DATE_DEBUT_COLLECTE, CTX_PARTITION_DATE_FIN_COLLECTE, - //specific sabiane - CTX_PARTITION_SABIANE_DATE_DEBUT_VISIBILITE_GESTIONNAIRE, - CTX_PARTITION_SABIANE_DATE_DEBUT_VISIBILITE_ENQUETEUR, - CTX_PARTITION_SABIANE_DATE_DEBUT_REPERAGE, - CTX_PARTITION_SABIANE_DATE_FIN_TRAITEMENT); - //For a partition, we need all the dates + the ID + label - Set requiredPartition = - new HashSet<>(requiredPartitionDates); - requiredPartition.add(CTX_PARTITION_ID); - requiredPartition.add(CTX_PARTITION_LABEL); - - - results.addAll(DelegateContextVerifier.computeMissingChildrenMessages(requiredNodes,contextRootNode,getClass())); - results.addAll(DelegateContextVerifier.computeMissingChildrenMessages(requiredMetadonnees,contextRootNode.path(CTX_METADONNEES),getClass())); - - var referentIterator=contextRootNode.path(CTX_META_REFERENTS_PRINCIPAUX).elements(); - while (referentIterator.hasNext()) { - var referentNode = referentIterator.next(); - results.addAll(DelegateContextVerifier.computeMissingChildrenMessages(requiredReferent,referentNode,getClass())); - } - - referentIterator=contextRootNode.path(CTX_META_REFERENTS_SECONDAIRES).elements(); - while (referentIterator.hasNext()) { - var referentNode = referentIterator.next(); - results.addAll(DelegateContextVerifier.computeMissingChildrenMessages(requiredReferent,referentNode,getClass())); - } - - var partitionIterator =contextRootNode.path(CTX_PARTITIONS).elements(); - //Partitions - while (partitionIterator.hasNext()) { - var partitionNode = partitionIterator.next(); - results.addAll(DelegateContextVerifier.computeMissingChildrenMessages(requiredPartition,partitionNode,getClass())); - - for(var dateNode : requiredPartitionDates) { - //Check the date format - try { - ContextServiceImpl.getInstantFromPartition(partitionNode, dateNode); - } catch (BadContextDateTimeParseBPMNError e) { - results.add(e.getMessage()); - } - } - } - - //Check sites de gestion (an array with at least one element) - JsonNode sitesGestionNode= contextRootNode.path(CTX_METADONNEES).path(CTX_META_SITES_GESTION); - if(!sitesGestionNode.isArray()){ - results.add(DelegateContextVerifier.computeIncorrectMessage(CTX_META_SITES_GESTION," should be an array", getClass())); - } - else if(sitesGestionNode.isEmpty()){ - results.add(DelegateContextVerifier.computeIncorrectMessage(CTX_META_SITES_GESTION," should not be an empty an array", getClass())); - } - else{ - var iter = sitesGestionNode.elements(); - while (iter.hasNext()){ - var value = iter.next(); - if(!value.isTextual()){ - results.add(DelegateContextVerifier.computeIncorrectMessage(CTX_META_SITES_GESTION," contains non textual values", getClass())); - break; - } - } - } - - //Check value of enums - try { - String essaisContact = contextRootNode.path(CTX_METADONNEES).path(CTX_META_ESSAIS_CONTACT).asText(); - ContactAttemptConfiguration.valueOfLabel(essaisContact); - }catch (IllegalArgumentException e){ - results.add(DelegateContextVerifier.computeIncorrectEnumMessage(CTX_META_ESSAIS_CONTACT,contextRootNode.path(CTX_METADONNEES).path(CTX_META_ESSAIS_CONTACT).asText(),Arrays.toString(ContactAttemptConfiguration.labels()),getClass())); - } - - try { - String bilanContact = contextRootNode.path(CTX_METADONNEES).path(CTX_META_BILAN_CONTACT).asText(); - ContactOutcomeConfiguration.valueOfLabel(bilanContact); - }catch (IllegalArgumentException e){ - results.add(DelegateContextVerifier.computeIncorrectEnumMessage(CTX_META_BILAN_CONTACT,contextRootNode.path(CTX_METADONNEES).path(CTX_META_BILAN_CONTACT).asText(),Arrays.toString(ContactOutcomeConfiguration.labels()),getClass())); - } - - try { - String reperage = contextRootNode.path(CTX_METADONNEES).path(CTX_META_REPERAGE).asText(); - IdentificationConfiguration.valueOfLabel(reperage); - }catch (IllegalArgumentException e){ - results.add(DelegateContextVerifier.computeIncorrectEnumMessage(CTX_META_REPERAGE,contextRootNode.path(CTX_METADONNEES).path(CTX_META_REPERAGE).asText(),Arrays.toString(IdentificationConfiguration.labels()),getClass())); - } - - return results; - - } -} diff --git a/src/main/java/fr/insee/protools/backend/service/sabiane/delegate/SabianePilotageCreateSUTask.java b/src/main/java/fr/insee/protools/backend/service/sabiane/delegate/SabianePilotageCreateSUTask.java deleted file mode 100644 index 1dd4f339..00000000 --- a/src/main/java/fr/insee/protools/backend/service/sabiane/delegate/SabianePilotageCreateSUTask.java +++ /dev/null @@ -1,359 +0,0 @@ -package fr.insee.protools.backend.service.sabiane.delegate; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import fr.insee.protools.backend.dto.rem.*; -import fr.insee.protools.backend.dto.sabiane.pilotage.*; -import fr.insee.protools.backend.service.DelegateContextVerifier; -import fr.insee.protools.backend.service.context.ContextService; -import fr.insee.protools.backend.service.context.enums.PartitionTypeEchantillon; -import fr.insee.protools.backend.service.exception.IncorrectSUBPMNError; -import fr.insee.protools.backend.service.platine.utils.PlatineHelper; -import fr.insee.protools.backend.service.rem.RemDtoUtils; -import fr.insee.protools.backend.service.sabiane.SabianeIdHelper; -import fr.insee.protools.backend.service.sabiane.pilotage.SabianePilotageService; -import fr.insee.protools.backend.service.utils.FlowableVariableUtils; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.EnumUtils; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.tuple.Pair; -import org.flowable.engine.delegate.DelegateExecution; -import org.flowable.engine.delegate.JavaDelegate; -import org.springframework.stereotype.Component; - -import java.time.Instant; -import java.time.LocalDate; -import java.time.ZoneId; -import java.time.ZonedDateTime; -import java.time.format.DateTimeFormatter; -import java.time.format.DateTimeParseException; -import java.util.*; -import java.util.stream.Collectors; - -import static com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_MISSING_CREATOR_PROPERTIES; -import static com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES; -import static fr.insee.protools.backend.service.FlowableVariableNameConstants.VARNAME_CURRENT_PARTITION_ID; -import static fr.insee.protools.backend.service.FlowableVariableNameConstants.VARNAME_REM_SURVEY_UNIT; -import static fr.insee.protools.backend.service.context.ContextConstants.*; -import static fr.insee.protools.backend.service.utils.ContextUtils.getCurrentPartitionNode; - -@Slf4j -@Component -@RequiredArgsConstructor -public class SabianePilotageCreateSUTask implements JavaDelegate, DelegateContextVerifier { - - private final ContextService protoolsContext; - private final SabianePilotageService sabianePilotageService; - - private static final DateTimeFormatter birthdateFormatter = DateTimeFormatter.ofPattern("yyyyMMdd"); - private static final ZoneId parisTimezone = ZoneId.of("Europe/Paris"); - private static final ObjectMapper objectMapper = new ObjectMapper().configure(FAIL_ON_UNKNOWN_PROPERTIES, false).configure(FAIL_ON_MISSING_CREATOR_PROPERTIES, true); - - @Override - public void execute(DelegateExecution execution) { - JsonNode contextRootNode = protoolsContext.getContextByProcessInstance(execution.getProcessInstanceId()); - checkContextOrThrow(log, execution.getProcessInstanceId(), contextRootNode); - - Long currentPartitionId = FlowableVariableUtils.getVariableOrThrow(execution, VARNAME_CURRENT_PARTITION_ID, Long.class); - JsonNode remSUNode = FlowableVariableUtils.getVariableOrThrow(execution, VARNAME_REM_SURVEY_UNIT, JsonNode.class); - JsonNode currentPartitionNode = getCurrentPartitionNode(contextRootNode, currentPartitionId); - - Boolean priority = currentPartitionNode.path(CTX_PARTITION_PRIORITAIRE).asBoolean(); - boolean isLogement = currentPartitionNode.path(CTX_PARTITION_TYPE_ECHANTILLON).textValue().equalsIgnoreCase(PartitionTypeEchantillon.LOGEMENT.getAsString()); - - //Create the DTO object - SurveyUnitContextDto dto = createSabianeSUContextDto(contextRootNode, currentPartitionId, remSUNode, isLogement, priority); - - log.info("ProcessInstanceId={} - currentPartitionId={} - remSU.id={}", execution.getProcessInstanceId(), currentPartitionId, dto.getId()); - - //Call service - sabianePilotageService.postSurveyUnits(List.of(dto)); - - log.debug("ProcessInstanceId={} end", execution.getProcessInstanceId()); - } - - @Override - public Set getContextErrors(JsonNode contextRootNode) { - if(contextRootNode==null){ - return Set.of("Context is missing"); - } - Set results=new HashSet<>(); - - Set requiredNodes = - Set.of( - //Global & Campaign - CTX_CAMPAGNE_ID, CTX_PARTITIONS - ); - Set requiredPartition = - Set.of(CTX_PARTITION_ID, CTX_PARTITION_TYPE_ECHANTILLON,CTX_PARTITION_PRIORITAIRE); - - results.addAll(DelegateContextVerifier.computeMissingChildrenMessages(requiredNodes,contextRootNode,getClass())); - - //Partitions - if(!contextRootNode.path(CTX_PARTITIONS).isArray() || contextRootNode.path(CTX_PARTITIONS).isEmpty()){ - results.add(DelegateContextVerifier.computeIncorrectMessage(CTX_PARTITIONS," should be a non empty array", getClass())); - } - else{ - var partitionIterator =contextRootNode.path(CTX_PARTITIONS).elements(); - while (partitionIterator.hasNext()) { - var partitionNode = partitionIterator.next(); - results.addAll(DelegateContextVerifier.computeMissingChildrenMessages(requiredPartition,partitionNode,getClass())); - - //Check value of Enum - String enumVal = partitionNode.path(CTX_PARTITION_TYPE_ECHANTILLON).asText(); - if(! EnumUtils.isValidEnumIgnoreCase(PartitionTypeEchantillon.class, enumVal)){ - results.add(DelegateContextVerifier.computeIncorrectEnumMessage(CTX_PARTITION_TYPE_ECHANTILLON,enumVal,Arrays.toString(PartitionTypeEchantillon.values()),getClass())); - } - } - } - - return results; - } - - /** - * Compute a timestamp considering that {@code remBirthdate} is localized in - * "Europe/Paris" timezone and is at the start of day - * @param remBirthdate A birthdate. Can be of the form - *
    - *
  • yyyyMMdd - ex: 20110823
  • - *
  • yyyyMM then assume dd is 01 - ex 201108 ==> 20110801
  • - *
  • yyyy then assume MM is 01 and dd is 01 - ex: 2011 ==> 20110101
  • - *
- * @return the unix timestamp (number of seconds since epoch) corresponding to this birthdate - */ - protected static Long computeSabianeBirthDateFromRem(String remBirthdate) { - if(StringUtils.isBlank(remBirthdate)) - return null; - - String adjudstedBirthDate = remBirthdate.trim(); - int len = adjudstedBirthDate.length(); - switch (len) { - case 4: - adjudstedBirthDate += "0101";//If 4 char (ex: 2009) consider 1st junary - break; - case 6: - adjudstedBirthDate += "01";//If 6 char (ex: 200912) : consider 1st day of month - break; - default: - } - try { - LocalDate localDate = LocalDate.parse(adjudstedBirthDate, birthdateFormatter); - ZonedDateTime zonedDateTime = localDate.atStartOfDay(parisTimezone); - return zonedDateTime.toInstant().getEpochSecond(); - } catch (DateTimeParseException e) { - throw new IncorrectSUBPMNError("Error while parsing the json retrieved from REM : the birthdate" + remBirthdate + " is incorrect."); - } - } - - private static SabianePhoneNumberDto createSabianePhoneNumberFromREM(PhoneNumberDto remPhone, Source sabianeSource) { - return new SabianePhoneNumberDto(sabianeSource, remPhone.getFavorite(), remPhone.getNumber()); - } - - protected static List createSabianePhoneList(List remPhones) { - List res = new ArrayList<>(2); - //Get the favorites numbers (excluding interviewers ones) - List favoritesNumeros = - remPhones.stream() - .filter(e -> !REMPhoneSource.INTERVIEWER.equals(e.getSource())) - .filter(e->Boolean.TRUE.equals(e.getFavorite())) - .toList(); - - //INTERVIEWER : Keep all phones numbers - remPhones.stream() - .filter(e -> REMPhoneSource.INTERVIEWER.equals(e.getSource())) - .forEach(phoneNumberDto -> res.add(createSabianePhoneNumberFromREM(phoneNumberDto, Source.INTERVIEWER))); - - - List nonInterviewerNonFavoriteByPriority = - remPhones.stream() - .filter(e->Boolean.FALSE.equals(e.getFavorite())) - //Discard interviewer as they are handled just before - .filter(phoneNumberDto -> !(phoneNumberDto.getSource().equals(REMPhoneSource.INTERVIEWER))) - .sorted(Comparator.comparingInt(obj -> { - //Selection priority order INITIAL>DIRECTORY>OTHER - switch (obj.getSource()) { - case INITIAL: - return 0; - case DIRECTORY: - return 1; - case OTHER: - return 2; - default: - return 3; // Handle other cases if necessary - } - })) - .collect(Collectors.toCollection(ArrayList::new));//Must be mutable - - switch (favoritesNumeros.size()) { - case 0://no favorite number : FILL FISCAL and DIRECTORY using priority (initial, directory, other) - if (!nonInterviewerNonFavoriteByPriority.isEmpty()) { - PhoneNumberDto remInitialNonFavorite = nonInterviewerNonFavoriteByPriority.remove(0); - res.add(createSabianePhoneNumberFromREM(remInitialNonFavorite, Source.FISCAL)); - } - if (!nonInterviewerNonFavoriteByPriority.isEmpty()) { - PhoneNumberDto remInitialNonFavorite = nonInterviewerNonFavoriteByPriority.remove(0); - res.add(createSabianePhoneNumberFromREM(remInitialNonFavorite, Source.DIRECTORY)); - } - break; - case 1: - res.add(createSabianePhoneNumberFromREM(favoritesNumeros.get(0), Source.FISCAL)); - if (!nonInterviewerNonFavoriteByPriority.isEmpty()) { - PhoneNumberDto remInitialNonFavorite = nonInterviewerNonFavoriteByPriority.remove(0); - res.add(createSabianePhoneNumberFromREM(remInitialNonFavorite, Source.DIRECTORY)); - } - break; - case 2: - res.add(createSabianePhoneNumberFromREM(favoritesNumeros.get(0), Source.FISCAL)); - res.add(createSabianePhoneNumberFromREM(favoritesNumeros.get(1), Source.DIRECTORY)); - break; - default: //More than 2 favorite numbers - throw new IncorrectSUBPMNError("Error while parsing the json retrieved from REM : more than 2 favorite phone number"); - } - return res; - } - - private static SabianePersonDto createSabianePersonFromRemPerson(PersonDto remPerson, Boolean isPrivileged) { - return SabianePersonDto.builder() - .title(convertREMGenderToSabianeCivilityTitle(remPerson.getGender())) - .firstName(remPerson.getFirstName()) - .lastName(remPerson.getLastName()) - .email(remPerson.getEmails().stream().findFirst().map(EmailDto::getMailAddress).orElse("")) - .birthdate(computeSabianeBirthDateFromRem(remPerson.getDateOfBirth())) - .favoriteEmail(Boolean.FALSE).privileged(isPrivileged) - .phoneNumbers(createSabianePhoneList(remPerson.getPhoneNumbers())) - .build(); - } - - protected static SurveyUnitContextDto createSabianeSUContextDto(JsonNode contextRootNode, Long currentPartitionId, JsonNode remSUNode, Boolean isLogement, Boolean priority) { - REMSurveyUnitDto remSurveyUnitDto = PlatineHelper.parseRemSUNode(objectMapper, VARNAME_REM_SURVEY_UNIT, remSUNode); - Pair> mainAndSecondaryPerson = RemDtoUtils.findContactAndSecondary(remSUNode, remSurveyUnitDto, isLogement); - String id = SabianeIdHelper.computeSabianeID(currentPartitionId.toString(), remSurveyUnitDto.getRepositoryId().toString()); - - List sabianePersons = new ArrayList<>(2); - sabianePersons.add(createSabianePersonFromRemPerson(mainAndSecondaryPerson.getLeft(), true)); //first is privileged - mainAndSecondaryPerson.getRight().ifPresent(personDto -> sabianePersons.add(createSabianePersonFromRemPerson(personDto, false))); - - //Organisation Unit (probably useless in production) - Optional poleGestionOpale = RemDtoUtils.searchAdditionalInformation(RemDtoUtils.REM_ADDITIONALINFOS_POLE_GESTION_OPALE,remSUNode); - - String noGrap = (remSurveyUnitDto.getOtherIdentifier()==null)?null:remSurveyUnitDto.getOtherIdentifier().getNograp(); - return SurveyUnitContextDto.builder() - .id(id) - .persons(sabianePersons) - .address(computeSabianeAdress(remSurveyUnitDto.getAddress(), mainAndSecondaryPerson.getLeft())) - .organizationUnitId(poleGestionOpale.orElse(null)) - .priority(priority) - .campaign(contextRootNode.path(CTX_CAMPAGNE_ID).textValue()) - .sampleIdentifiers( - SampleIdentifiersDto.builder() - .autre("0") - .bs(0) - .ec("0") - .le(0) - .nograp(noGrap).noi(0).nole(0).nolog(0).numfa(0).rges(0).ssech(currentPartitionId).build()) - .states(List.of(StateDto.builder().date(Instant.now().toEpochMilli()).type(StateType.NVM).build())) - .build(); - } - - /** - * @param str the string to parse - * @return l2 and l3 part of an address by splitting {@code str} at 38 char. If {@code str} is null or empty - * return a pair of empty strings - */ - protected static Pair computeL2L3(String str) { - if (str == null || str.isEmpty() || str.isBlank()) { - return Pair.of(StringUtils.EMPTY, StringUtils.EMPTY); - } - if (str.length() <= 38) { - return Pair.of(str, StringUtils.EMPTY); - } - return Pair.of(str.substring(0, 38), str.substring(38)); - } - - /** - * @param remGender - * @return A {@code SabianeTitle} for the passed string (supposedly a rem gender). MISTER if value is 1. MISS in every other case - */ - protected static SabianeTitle convertREMGenderToSabianeCivilityTitle(String remGender) { - if(remGender == null){ - return SabianeTitle.MISS; - } - return switch (remGender) { - //TODO: enable when pass to java 19 (preview in 17) - //case null: - // yield SabianeTitle.MISS; - case "1": - yield SabianeTitle.MISTER; - default: - yield SabianeTitle.MISS; - }; - } - - protected static AddressDto computeSabianeAdress(REMAddressDto remAddressDto, PersonDto contact) { - - //l1 : “M” si REM.person.gender = "1" ; “MME” sinon + “firstName” + “lastName” (pour la personne mise en privileged) - StringBuilder l1Builder = new StringBuilder(convertREMGenderToSabianeCivilityTitle(contact.getGender()).getFrenchCivility()); - l1Builder.append(org.apache.commons.lang3.StringUtils.SPACE); - if(!StringUtils.isBlank(contact.getFirstName())){ - l1Builder.append(contact.getFirstName()); - l1Builder.append(org.apache.commons.lang3.StringUtils.SPACE); - } - if(!StringUtils.isBlank(contact.getLastName())){ - l1Builder.append(contact.getLastName()); - } - String l1=l1Builder.toString().trim(); - - //l2 : partie de “REM.address.addressSupplement” <=38 caractères - //l3 : partie de “REM.address.addressSupplement” > 38 caractères - Pair l2L3 = computeL2L3(remAddressDto.getAddressSupplement()); - String l2 = l2L3.getLeft(); - String l3 = l2L3.getRight(); - - //l4: “REM.address.streetNumber” + “REM.address.repetitionIndex” + “REM.address.streetType” + “REM.address.streetName” - StringBuilder l4Builder = new StringBuilder(); - if(!StringUtils.isBlank(remAddressDto.getStreetNumber())){ - l4Builder.append(remAddressDto.getStreetNumber()); - l4Builder.append(org.apache.commons.lang3.StringUtils.SPACE); - } - if(!StringUtils.isBlank(remAddressDto.getRepetitionIndex())){ - l4Builder.append(remAddressDto.getRepetitionIndex()); - l4Builder.append(org.apache.commons.lang3.StringUtils.SPACE); - } - if(!StringUtils.isBlank(remAddressDto.getStreetType())){ - l4Builder.append(remAddressDto.getStreetType()); - l4Builder.append(org.apache.commons.lang3.StringUtils.SPACE); - } - if(!StringUtils.isBlank(remAddressDto.getStreetName())){ - l4Builder.append(remAddressDto.getStreetName()); - } - String l4 = l4Builder.toString().trim(); - - //l5: “REM.address.specialDistribution” - String l5 = (StringUtils.isBlank(remAddressDto.getSpecialDistribution()) ? "" : remAddressDto.getSpecialDistribution()); - - //l6: “REM.address.zipCode” + “REM.address.cityName” - StringBuilder l6Builder = new StringBuilder(); - if(!StringUtils.isBlank(remAddressDto.getZipCode())){ - l6Builder.append(remAddressDto.getZipCode()); - l6Builder.append(org.apache.commons.lang3.StringUtils.SPACE); - } - if(!StringUtils.isBlank(remAddressDto.getCityName())){ - l6Builder.append(remAddressDto.getCityName()); - } - String l6 = l6Builder.toString().trim(); - - //l7: REM.countryName ou “FRANCE” si null - String l7 = (StringUtils.isBlank(remAddressDto.getCountryName()) ? "FRANCE" : remAddressDto.getCountryName()); - - if(remAddressDto.getLocationHelp()!=null) { - return AddressDto.builder().elevator(remAddressDto.getLocationHelp().getElevator()).building(remAddressDto.getLocationHelp().getBuilding()) - .floor(remAddressDto.getLocationHelp().getFloor()).door(remAddressDto.getLocationHelp().getDoor()).staircase(remAddressDto.getLocationHelp().getStaircase()) - .cityPriorityDistrict(remAddressDto.getLocationHelp().getCityPriorityDistrict()) - .l1(l1).l2(l2).l3(l3).l4(l4).l5(l5).l6(l6).l7(l7).build(); - } - else{ - return AddressDto.builder().l1(l1).l2(l2).l3(l3).l4(l4).l5(l5).l6(l6).l7(l7).build(); - } - } -} diff --git a/src/main/java/fr/insee/protools/backend/service/sabiane/delegate/SabianeQuestionnaireCreateContextTask.java b/src/main/java/fr/insee/protools/backend/service/sabiane/delegate/SabianeQuestionnaireCreateContextTask.java deleted file mode 100644 index 2bcaa0f0..00000000 --- a/src/main/java/fr/insee/protools/backend/service/sabiane/delegate/SabianeQuestionnaireCreateContextTask.java +++ /dev/null @@ -1,86 +0,0 @@ -package fr.insee.protools.backend.service.sabiane.delegate; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import fr.insee.protools.backend.dto.platine_sabiane_questionnaire.MetadataConstants; -import fr.insee.protools.backend.dto.platine_sabiane_questionnaire.campaign.MetadataValue; -import fr.insee.protools.backend.dto.platine_sabiane_questionnaire.campaign.MetadataValueItem; -import fr.insee.protools.backend.dto.platine_sabiane_questionnaire.campaign.MetadataVariables; -import fr.insee.protools.backend.service.DelegateContextVerifier; -import fr.insee.protools.backend.service.common.platine_sabiane.QuestionnaireHelper; -import fr.insee.protools.backend.service.context.ContextService; -import fr.insee.protools.backend.service.nomenclature.NomenclatureService; -import fr.insee.protools.backend.service.questionnaire_model.QuestionnaireModelService; -import fr.insee.protools.backend.service.sabiane.questionnaire.SabianeQuestionnaireService; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.flowable.engine.delegate.DelegateExecution; -import org.flowable.engine.delegate.JavaDelegate; -import org.springframework.stereotype.Component; - -import java.util.List; -import java.util.Set; - -import static fr.insee.protools.backend.service.context.ContextConstants.*; - -@Slf4j -@Component -@RequiredArgsConstructor -public class SabianeQuestionnaireCreateContextTask implements JavaDelegate, DelegateContextVerifier { - - private final ContextService protoolsContext; - private final ObjectMapper objectMapper; - private final NomenclatureService nomenclatureService; - private final QuestionnaireModelService questionnaireModelService; - private final SabianeQuestionnaireService sabianeQuestionnaireService; - - @Override - public void execute(DelegateExecution execution) { - JsonNode contextRootNode = protoolsContext.getContextByProcessInstance(execution.getProcessInstanceId()); - //check context - checkContextOrThrow(log,execution.getProcessInstanceId(), contextRootNode); - log.info("ProcessInstanceId={} - campagne={}" - ,execution.getProcessInstanceId(),contextRootNode.path(CTX_CAMPAGNE_CONTEXTE).asText()); - - MetadataValue metadataDto = createMetadataDto(contextRootNode); - QuestionnaireHelper.createQuestionnaire(contextRootNode,sabianeQuestionnaireService,nomenclatureService, - questionnaireModelService,execution.getProcessInstanceId(),metadataDto); - - log.debug("ProcessInstanceId={} end",execution.getProcessInstanceId()); - } - - @Override - public Set getContextErrors(JsonNode contextRootNode) { - if(contextRootNode==null){ - return Set.of(String.format("Class=%s : Context is missing ", this.getClass().getSimpleName())); - } - - //Standard verifications (common between platine and sabiane) - Set missingNodes = - QuestionnaireHelper.getCreateCtxContextErrors(contextRootNode); - - //Metadata used by sabiane - Set requiredMetadonnes = - Set.of(CTX_META_LABEL_LONG_OPERATION); - - if (contextRootNode.get(CTX_METADONNEES) != null) { - missingNodes.addAll(DelegateContextVerifier.computeMissingChildrenMessages(requiredMetadonnes,contextRootNode.path(CTX_METADONNEES),getClass())); - } - - return missingNodes; - } - - MetadataValue createMetadataDto(JsonNode contextRootNode){ - JsonNode metadataNode = contextRootNode.path(CTX_METADONNEES); - return MetadataValue.builder() - .value(MetadataVariables.builder() - .variables( - List.of( - new MetadataValueItem(MetadataConstants.Enq_LibelleEnquete,metadataNode.path(CTX_META_LABEL_LONG_OPERATION).asText()) - ) - ) - .inseeContext(contextRootNode.path(CTX_CAMPAGNE_CONTEXTE).asText()) - .build()) - .build(); - } -} diff --git a/src/main/java/fr/insee/protools/backend/service/sabiane/delegate/SabianeQuestionnaireCreateSUTask.java b/src/main/java/fr/insee/protools/backend/service/sabiane/delegate/SabianeQuestionnaireCreateSUTask.java deleted file mode 100644 index 7c559a72..00000000 --- a/src/main/java/fr/insee/protools/backend/service/sabiane/delegate/SabianeQuestionnaireCreateSUTask.java +++ /dev/null @@ -1,36 +0,0 @@ -package fr.insee.protools.backend.service.sabiane.delegate; - -import com.fasterxml.jackson.databind.JsonNode; -import fr.insee.protools.backend.service.DelegateContextVerifier; -import fr.insee.protools.backend.service.common.platine_sabiane.QuestionnaireHelper; -import fr.insee.protools.backend.service.context.ContextService; -import fr.insee.protools.backend.service.sabiane.questionnaire.SabianeQuestionnaireService; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.flowable.engine.delegate.DelegateExecution; -import org.flowable.engine.delegate.JavaDelegate; -import org.springframework.stereotype.Component; - -import java.util.Set; - -@Slf4j -@Component -@RequiredArgsConstructor -public class SabianeQuestionnaireCreateSUTask implements JavaDelegate, DelegateContextVerifier { - - private final ContextService protoolsContext; - private final SabianeQuestionnaireService sabianeQuestionnaireService; - - @Override - public void execute(DelegateExecution execution) { - JsonNode contextRootNode = protoolsContext.getContextByProcessInstance(execution.getProcessInstanceId()); - checkContextOrThrow(log,execution.getProcessInstanceId(), contextRootNode); - QuestionnaireHelper.createSUTaskSabiane(execution,protoolsContext,sabianeQuestionnaireService); - } - - @Override - public Set getContextErrors(JsonNode contextRootNode) { - return QuestionnaireHelper.getCreateSUContextErrorsSabiane(contextRootNode); - } - -} diff --git a/src/main/java/fr/insee/protools/backend/service/sabiane/pilotage/SabianePilotageService.java b/src/main/java/fr/insee/protools/backend/service/sabiane/pilotage/SabianePilotageService.java deleted file mode 100644 index ecc9a1ff..00000000 --- a/src/main/java/fr/insee/protools/backend/service/sabiane/pilotage/SabianePilotageService.java +++ /dev/null @@ -1,53 +0,0 @@ -package fr.insee.protools.backend.service.sabiane.pilotage; - -import fr.insee.protools.backend.dto.sabiane.pilotage.CampaignContextDto; -import fr.insee.protools.backend.dto.sabiane.pilotage.SurveyUnitContextDto; -import fr.insee.protools.backend.webclient.WebClientHelper; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.slf4j.event.Level; -import org.springframework.stereotype.Service; - -import java.util.List; - -import static fr.insee.protools.backend.webclient.configuration.ApiConfigProperties.KNOWN_API.KNOWN_API_SABIANE_PILOTAGE; - - -@Service -@Slf4j -@RequiredArgsConstructor -public class SabianePilotageService { - - private final WebClientHelper webClientHelper; - - public void postCampaign(CampaignContextDto campaignContextDto) { - WebClientHelper.logJson("postCampaign: ",campaignContextDto, log,Level.DEBUG); - - //TODO: This call returns that if campaign already exists : statusCode=400 BAD_REQUEST - contentType=Optional[text/plain;charset=UTF-8] - Campaign with id 'MBG2022X01' already exists - var response = webClientHelper.getWebClient(KNOWN_API_SABIANE_PILOTAGE) - .post() - .uri("/api/campaign") - .bodyValue(campaignContextDto) - .retrieve() - .bodyToMono(String.class) - .block(); - log.trace("postCampaign: campaign={} - response={} ", campaignContextDto.getCampaign(), response); - } - public void postSurveyUnits(List values) { - log.debug("postSurveyUnits - values.size={}", values == null ? 0 : values.size()); - if (values == null) { - log.debug("postSurveyUnits - values==null ==> Nothing to do"); - return; - } - var response = webClientHelper.getWebClient(KNOWN_API_SABIANE_PILOTAGE) - .post() - .uri("/api/survey-units") - .bodyValue(values) - .retrieve() - .bodyToMono(String.class) - .block(); - log.trace("postSurveyUnits - response={} ", response); - } -} - - diff --git a/src/main/java/fr/insee/protools/backend/service/sabiane/questionnaire/SabianeQuestionnaireService.java b/src/main/java/fr/insee/protools/backend/service/sabiane/questionnaire/SabianeQuestionnaireService.java deleted file mode 100644 index c3b2b881..00000000 --- a/src/main/java/fr/insee/protools/backend/service/sabiane/questionnaire/SabianeQuestionnaireService.java +++ /dev/null @@ -1,31 +0,0 @@ -package fr.insee.protools.backend.service.sabiane.questionnaire; - -import fr.insee.protools.backend.service.common.platine_sabiane.QuestionnairePlatineSabianeService; -import fr.insee.protools.backend.webclient.WebClientHelper; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.slf4j.Logger; -import org.springframework.stereotype.Service; -import org.springframework.web.reactive.function.client.WebClient; - -import static fr.insee.protools.backend.webclient.configuration.ApiConfigProperties.KNOWN_API.KNOWN_API_SABIANE_QUESTIONNAIRE; - - -@Service -@Slf4j -@RequiredArgsConstructor -public class SabianeQuestionnaireService implements QuestionnairePlatineSabianeService { - private final WebClientHelper webClientHelper; - - @Override - public WebClient webClient() { - return webClientHelper.getWebClient(KNOWN_API_SABIANE_QUESTIONNAIRE); - } - - @Override - public Logger getLogger() { - return log; - } -} - - diff --git a/src/main/java/fr/insee/protools/backend/service/scheduled/TaskService.java b/src/main/java/fr/insee/protools/backend/service/scheduled/TaskService.java new file mode 100644 index 00000000..deaaf9ed --- /dev/null +++ b/src/main/java/fr/insee/protools/backend/service/scheduled/TaskService.java @@ -0,0 +1,24 @@ +package fr.insee.protools.backend.service.scheduled; + +import fr.insee.protools.backend.repository.IUniteEnquetee; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +@Component +@Slf4j +public class TaskService { + + private final IUniteEnquetee iUniteEnquetee; + + public TaskService(IUniteEnquetee iUniteEnquetee) { + this.iUniteEnquetee = iUniteEnquetee; + } + + public boolean isTerminated(String processInstanceId, String currentActivityId, long nbInterogation) throws InterruptedException { + log.info("IUniteEnquetee.isTerminated"); +// TODO : iUniteEnquetee.getCommandesBygetProcessInstanceIdAndIdTask(1,2) + return iUniteEnquetee.isTerminated(processInstanceId, currentActivityId, nbInterogation); + } + + +} \ No newline at end of file diff --git a/src/main/java/fr/insee/protools/backend/service/sugoi/ISugoiService.java b/src/main/java/fr/insee/protools/backend/service/sugoi/ISugoiService.java new file mode 100644 index 00000000..60080f2d --- /dev/null +++ b/src/main/java/fr/insee/protools/backend/service/sugoi/ISugoiService.java @@ -0,0 +1,10 @@ +package fr.insee.protools.backend.service.sugoi; + +import fr.insee.protools.backend.dto.sugoi.User; + +public interface ISugoiService { + + User postCreateUser(User userBody); + + void postInitPassword(String userId, String password); +} diff --git a/src/main/java/fr/insee/protools/backend/service/sugoi/SugoiCreateUserTask.java b/src/main/java/fr/insee/protools/backend/service/sugoi/SugoiCreateUserTask.java deleted file mode 100644 index 067f6879..00000000 --- a/src/main/java/fr/insee/protools/backend/service/sugoi/SugoiCreateUserTask.java +++ /dev/null @@ -1,46 +0,0 @@ -package fr.insee.protools.backend.service.sugoi; - -import fr.insee.protools.backend.dto.sugoi.Habilitation; -import fr.insee.protools.backend.dto.sugoi.User; -import fr.insee.protools.backend.service.DelegateContextVerifier; -import fr.insee.protools.backend.service.utils.password.PasswordService; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.flowable.engine.delegate.DelegateExecution; -import org.flowable.engine.delegate.JavaDelegate; -import org.springframework.stereotype.Component; - -import java.util.List; - -import static fr.insee.protools.backend.service.FlowableVariableNameConstants.VARNAME_DIRECTORYACCESS_ID_CONTACT; -import static fr.insee.protools.backend.service.FlowableVariableNameConstants.VARNAME_DIRECTORYACCESS_PWD_CONTACT; - -@Slf4j -@Component -@RequiredArgsConstructor -public class SugoiCreateUserTask implements JavaDelegate, DelegateContextVerifier { - - protected static final Habilitation PLATINE_HABILITATION = new Habilitation("platine", "repondant", null); - protected static final User createSugoiUserBody = User.builder().habilitations(List.of(PLATINE_HABILITATION)).build(); - - private final SugoiService sugoiService; - private final PasswordService passwordService; - - @Override - public void execute(DelegateExecution execution) { - log.debug("ProcessInstanceId={} begin", execution.getProcessInstanceId()); - - //Create User - User createdUser = sugoiService.postCreateUsers(createSugoiUserBody); - //init password - String userPassword = passwordService.generatePassword(); - sugoiService.postInitPassword(createdUser.getUsername(), userPassword); - - execution.setVariableLocal(VARNAME_DIRECTORYACCESS_ID_CONTACT, createdUser.getUsername()); - //TODO : find a way to not store password in protools variables - execution.setVariableLocal(VARNAME_DIRECTORYACCESS_PWD_CONTACT, userPassword); - - log.info("ProcessInstanceId={} username={} end", execution.getProcessInstanceId(), createdUser.getUsername()); - } - -} diff --git a/src/main/java/fr/insee/protools/backend/service/sugoi/SugoiService.java b/src/main/java/fr/insee/protools/backend/service/sugoi/SugoiServiceImpl.java similarity index 60% rename from src/main/java/fr/insee/protools/backend/service/sugoi/SugoiService.java rename to src/main/java/fr/insee/protools/backend/service/sugoi/SugoiServiceImpl.java index 934227da..293ed9cf 100644 --- a/src/main/java/fr/insee/protools/backend/service/sugoi/SugoiService.java +++ b/src/main/java/fr/insee/protools/backend/service/sugoi/SugoiServiceImpl.java @@ -3,48 +3,55 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; import fr.insee.protools.backend.dto.sugoi.User; +import fr.insee.protools.backend.restclient.RestClientHelper; +import fr.insee.protools.backend.restclient.configuration.ApiConfigProperties; +import fr.insee.protools.backend.restclient.exception.runtime.HttpClient4xxBPMNError; +import fr.insee.protools.backend.service.exception.SugoiServiceCallBPMNError; import fr.insee.protools.backend.service.exception.UsernameAlreadyExistsSugoiBPMNError; -import fr.insee.protools.backend.webclient.WebClientHelper; -import fr.insee.protools.backend.webclient.exception.runtime.WebClient4xxBPMNError; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Service; -import static fr.insee.protools.backend.webclient.configuration.ApiConfigProperties.KNOWN_API.KNOWN_API_SUGOI; +import static fr.insee.protools.backend.restclient.configuration.ApiConfigProperties.KNOWN_API.KNOWN_API_SUGOI; @Service @Slf4j @RequiredArgsConstructor -public class SugoiService { - //TODO: a quel niveau configure on ça? +public class SugoiServiceImpl implements ISugoiService{ + + private static final ApiConfigProperties.KNOWN_API API = KNOWN_API_SUGOI; static final String STORAGE = "default"; - private final WebClientHelper webClientHelper; + private final RestClientHelper restClientHelper; private final ObjectMapper objectMapper; @Value("${fr.insee.protools.api.sugoi.dmz-account-creation-realm:questionnaire-particuliers}") private String realm; - public User postCreateUsers(User userBody) { - log.info("postCreateUsers"); + @Override + public User postCreateUser(User userBody) { + if(userBody==null){ + String msg="called SUGOI postCreateUser with empty userBody"; + log.error(msg); + throw new SugoiServiceCallBPMNError(msg); + } + try { - User userCreated = webClientHelper.getWebClient(KNOWN_API_SUGOI) + User userCreated = restClientHelper.getRestClient(API) .post() .uri(uriBuilder -> uriBuilder .path("/realms/{realm}/storages/{storage}/users") .build(realm, STORAGE)) - .bodyValue(userBody) + .body(userBody) .retrieve() - .bodyToMono(User.class) - .block(); - log.trace("postCreateUsers - response={} ", userCreated); - log.info("postCreateUsers: end"); + .body(User.class); + log.info("postCreateUsers - response={} ", userCreated); return userCreated; - } catch (WebClient4xxBPMNError e) { + } catch (HttpClient4xxBPMNError e) { if (e.getHttpStatusCodeError().equals(HttpStatus.CONFLICT)) { String msg = - "Error 409/CONFLICT during SUGOI post create users userBody.username=" + ((userBody == null) ? "null" : userBody.getUsername()) + "Error 409/CONFLICT during SUGOI post create users userBody.username=" + userBody.getUsername() + " (check that the username already exists in SUGOI) - msg=" + e.getMessage(); log.error(msg); throw new UsernameAlreadyExistsSugoiBPMNError(msg); @@ -54,21 +61,20 @@ public User postCreateUsers(User userBody) { } } - + @Override public void postInitPassword(String userId, String password) { - log.info("postInitPassword - userId={} begin", userId); + log.debug("postInitPassword - userId={} begin", userId); ObjectNode body = objectMapper.createObjectNode(); body.put("password", password); - webClientHelper.getWebClient(KNOWN_API_SUGOI) + restClientHelper.getRestClient(API) .post() .uri(uriBuilder -> uriBuilder .path("/realms/{realm}/users/{id}/init-password") .queryParam("change-password-reset-status", true) .build(realm, userId)) - .bodyValue(body) + .body(body) .retrieve() - .toBodilessEntity() - .block(); + .toBodilessEntity(); log.info("postInitPassword - userId={} end", userId); } } diff --git a/src/main/java/fr/insee/protools/backend/service/sugoi/delegate/CleanPasswordsTask.java b/src/main/java/fr/insee/protools/backend/service/sugoi/delegate/CleanPasswordsTask.java new file mode 100644 index 00000000..59358818 --- /dev/null +++ b/src/main/java/fr/insee/protools/backend/service/sugoi/delegate/CleanPasswordsTask.java @@ -0,0 +1,49 @@ +package fr.insee.protools.backend.service.sugoi.delegate; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.flowable.engine.HistoryService; +import org.flowable.engine.delegate.DelegateExecution; +import org.flowable.engine.delegate.JavaDelegate; +import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl; +import org.flowable.variable.api.history.HistoricVariableInstance; +import org.flowable.variable.api.history.HistoricVariableInstanceQuery; +import org.flowable.variable.service.HistoricVariableService; +import org.flowable.variable.service.impl.persistence.entity.HistoricVariableInstanceEntity; +import org.springframework.stereotype.Component; + +import java.util.List; + +import static fr.insee.protools.backend.service.FlowableVariableNameConstants.VARNAME_DIRECTORYACCESS_PWD_FOR_INTERRO_ID_MAP; + +/** + * Supprime tous les mots de passe et toutes les occurences de l'historique + */ +@Slf4j +@Component +@RequiredArgsConstructor +public class CleanPasswordsTask implements JavaDelegate { + + private final ProcessEngineConfigurationImpl processEngineConfiguration; + + @Override + public void execute(DelegateExecution execution) { + log.debug("ProcessInstanceId={} begin", execution.getProcessInstanceId()); + + //Supprime la variable mot de passe si elle existe + execution.removeVariable(VARNAME_DIRECTORYACCESS_PWD_FOR_INTERRO_ID_MAP); + + //La supprime aussi de l'historique + HistoricVariableService historicVariableService = processEngineConfiguration.getVariableServiceConfiguration().getHistoricVariableService(); + HistoryService historyService = processEngineConfiguration.getHistoryService(); + + HistoricVariableInstanceQuery query = historyService.createHistoricVariableInstanceQuery() + .processInstanceId(execution.getProcessInstanceId()) + .variableName(VARNAME_DIRECTORYACCESS_PWD_FOR_INTERRO_ID_MAP); + + List variableInstances = query.list(); + for (HistoricVariableInstance variableInstance : variableInstances) { + historicVariableService.deleteHistoricVariableInstance((HistoricVariableInstanceEntity) variableInstance); + } + } +} diff --git a/src/main/java/fr/insee/protools/backend/service/sugoi/delegate/CleanUserPasswordTask.java b/src/main/java/fr/insee/protools/backend/service/sugoi/delegate/CleanUserPasswordTask.java new file mode 100644 index 00000000..ac91edc2 --- /dev/null +++ b/src/main/java/fr/insee/protools/backend/service/sugoi/delegate/CleanUserPasswordTask.java @@ -0,0 +1,49 @@ +package fr.insee.protools.backend.service.sugoi.delegate; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.flowable.engine.HistoryService; +import org.flowable.engine.delegate.DelegateExecution; +import org.flowable.engine.delegate.JavaDelegate; +import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl; +import org.flowable.variable.api.history.HistoricVariableInstance; +import org.flowable.variable.api.history.HistoricVariableInstanceQuery; +import org.flowable.variable.service.HistoricVariableService; +import org.flowable.variable.service.impl.persistence.entity.HistoricVariableInstanceEntity; +import org.springframework.stereotype.Component; + +import java.util.List; + +import static fr.insee.protools.backend.service.FlowableVariableNameConstants.VARNAME_DIRECTORYACCESS_PWD_CONTACT; + +/** + * Supprime la variable mot de passe et supprime aussi toutes les occurences de l'historique + */ +@Slf4j +@Component +@RequiredArgsConstructor +public class CleanUserPasswordTask implements JavaDelegate { + + private final ProcessEngineConfigurationImpl processEngineConfiguration; + + @Override + public void execute(DelegateExecution execution) { + log.debug("ProcessInstanceId={} begin", execution.getProcessInstanceId()); + + //Supprime la variable mot de passe si elle existe + execution.removeVariable(VARNAME_DIRECTORYACCESS_PWD_CONTACT); + + //La supprime aussi de l'historique + HistoricVariableService historicVariableService = processEngineConfiguration.getVariableServiceConfiguration().getHistoricVariableService(); + HistoryService historyService = processEngineConfiguration.getHistoryService(); + + HistoricVariableInstanceQuery query = historyService.createHistoricVariableInstanceQuery() + .processInstanceId(execution.getProcessInstanceId()) + .variableName(VARNAME_DIRECTORYACCESS_PWD_CONTACT); + + List variableInstances = query.list(); + for (HistoricVariableInstance variableInstance : variableInstances) { + historicVariableService.deleteHistoricVariableInstance((HistoricVariableInstanceEntity) variableInstance); + } + } +} diff --git a/src/main/java/fr/insee/protools/backend/service/sugoi/delegate/LogCredentialsTask.java b/src/main/java/fr/insee/protools/backend/service/sugoi/delegate/LogCredentialsTask.java new file mode 100644 index 00000000..9c63551d --- /dev/null +++ b/src/main/java/fr/insee/protools/backend/service/sugoi/delegate/LogCredentialsTask.java @@ -0,0 +1,44 @@ +package fr.insee.protools.backend.service.sugoi.delegate; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.flowable.engine.HistoryService; +import org.flowable.engine.delegate.DelegateExecution; +import org.flowable.engine.delegate.JavaDelegate; +import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl; +import org.flowable.variable.api.history.HistoricVariableInstance; +import org.flowable.variable.api.history.HistoricVariableInstanceQuery; +import org.springframework.stereotype.Component; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import static fr.insee.protools.backend.service.FlowableVariableNameConstants.VARNAME_DIRECTORYACCESS_PWD_CONTACT; + +/** + * Supprime la variable mot de passe et supprime aussi toutes les occurences de l'historique + */ +@Slf4j +@Component +@RequiredArgsConstructor +public class LogCredentialsTask implements JavaDelegate { + + private final ProcessEngineConfigurationImpl processEngineConfiguration; + + @Override + public void execute(DelegateExecution execution) { + HistoryService historyService = processEngineConfiguration.getHistoryService(); + HistoricVariableInstanceQuery query = historyService.createHistoricVariableInstanceQuery() + .processInstanceId(execution.getProcessInstanceId()) + .variableName(VARNAME_DIRECTORYACCESS_PWD_CONTACT); + List variableInstances = query.list(); + + Set excludeKeys = new HashSet<>(); + excludeKeys.add("context"); + + execution.getVariables().entrySet().stream() + .filter(entry -> !excludeKeys.contains(entry.getKey())) + .forEach(entry -> log.info(entry.getKey() + ": " + entry.getValue())); + } +} diff --git a/src/main/java/fr/insee/protools/backend/service/sugoi_rem/delegate/SugoiREMCreateMissingAccountListTask.java b/src/main/java/fr/insee/protools/backend/service/sugoi_rem/delegate/SugoiREMCreateMissingAccountListTask.java new file mode 100644 index 00000000..e84216ce --- /dev/null +++ b/src/main/java/fr/insee/protools/backend/service/sugoi_rem/delegate/SugoiREMCreateMissingAccountListTask.java @@ -0,0 +1,78 @@ +package fr.insee.protools.backend.service.sugoi_rem.delegate; + +import fr.insee.protools.backend.dto.ContexteProcessus; +import fr.insee.protools.backend.dto.sugoi.Habilitation; +import fr.insee.protools.backend.dto.sugoi.User; +import fr.insee.protools.backend.service.DelegateContextVerifier; +import fr.insee.protools.backend.service.context.IContextService; +import fr.insee.protools.backend.service.rem.RemServiceImpl; +import fr.insee.protools.backend.service.sugoi.ISugoiService; +import fr.insee.protools.backend.service.utils.FlowableVariableUtils; +import fr.insee.protools.backend.service.utils.password.PasswordService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.flowable.engine.delegate.DelegateExecution; +import org.flowable.engine.delegate.JavaDelegate; +import org.springframework.stereotype.Component; + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import static fr.insee.protools.backend.service.FlowableVariableNameConstants.VARNAME_CURRENT_PARTITION_ID; +import static fr.insee.protools.backend.service.FlowableVariableNameConstants.VARNAME_DIRECTORYACCESS_PWD_FOR_INTERRO_ID_MAP; + +@Slf4j +@Component +@RequiredArgsConstructor +public class SugoiREMCreateMissingAccountListTask implements JavaDelegate, DelegateContextVerifier { + + protected static final Habilitation PLATINE_HABILITATION = new Habilitation("platine", "repondant", null); + protected static final User createSugoiUserBody = User.builder().habilitations(List.of(PLATINE_HABILITATION)).build(); + + private final ISugoiService sugoiService; + private final RemServiceImpl remService; + + private final PasswordService passwordService; + private final IContextService protoolsContext; + + public static final int HOUSEHOLD_PASSWORD_SIZE=8; + public static final int DEFAULT_PASSWORD_SIZE=12; + + @Override + public void execute(DelegateExecution execution) { + log.debug("ProcessInstanceId={} begin", execution.getProcessInstanceId()); + ContexteProcessus context = protoolsContext.getContextDtoByProcessInstance(execution.getProcessInstanceId()); + checkContextOrThrow(log,execution.getProcessInstanceId(), context); + + String currentPartitionId = FlowableVariableUtils.getVariableOrThrow(execution, VARNAME_CURRENT_PARTITION_ID, String.class); + List interrogationIdsWithoutAccount = remService.getInterrogationIdsWithoutAccountForPartition(currentPartitionId); + + Map userByInterroId = new LinkedHashMap<>(interrogationIdsWithoutAccount.size()); + Map pwdByInterroId = new LinkedHashMap<>(interrogationIdsWithoutAccount.size()); + + int passwordSize = getPasswordSize(context); + for (String interrogationId : interrogationIdsWithoutAccount){ + //Create User + User createdUser = sugoiService.postCreateUser(createSugoiUserBody); + //init password + String userPassword = passwordService.generatePassword(passwordSize); + sugoiService.postInitPassword(createdUser.getUsername(), userPassword); + userByInterroId.put(interrogationId,createdUser.getUsername()); + pwdByInterroId.put(interrogationId,userPassword); + log.debug("ProcessInstanceId={} - username={} ", execution.getProcessInstanceId(),createdUser.getUsername()); + } + + remService.patchInterrogationsSetAccounts(userByInterroId); + + execution.setVariableLocal(VARNAME_DIRECTORYACCESS_PWD_FOR_INTERRO_ID_MAP, pwdByInterroId); + log.info("ProcessInstanceId={} - size={} end", execution.getProcessInstanceId(), userByInterroId.size()); + } + + public static int getPasswordSize(ContexteProcessus context){ + if(context.getContexte().equals(ContexteProcessus.Contexte.MENAGE)){ + return HOUSEHOLD_PASSWORD_SIZE; + } + return DEFAULT_PASSWORD_SIZE; + } +} diff --git a/src/main/java/fr/insee/protools/backend/service/traiterxxxx/ITraiterXXXService.java b/src/main/java/fr/insee/protools/backend/service/traiterxxxx/ITraiterXXXService.java new file mode 100644 index 00000000..d2d750b4 --- /dev/null +++ b/src/main/java/fr/insee/protools/backend/service/traiterxxxx/ITraiterXXXService.java @@ -0,0 +1,12 @@ +package fr.insee.protools.backend.service.traiterxxxx; + +import com.fasterxml.jackson.databind.JsonNode; + +import java.util.List; + +public interface ITraiterXXXService { + + List getRemiseEnCollecteForPartition(String partitionId); + + void postContext(String campaignId, JsonNode contextRootNode); +} diff --git a/src/main/java/fr/insee/protools/backend/service/traiterxxxx/TraiterXXXServiceImpl.java b/src/main/java/fr/insee/protools/backend/service/traiterxxxx/TraiterXXXServiceImpl.java new file mode 100644 index 00000000..572871cc --- /dev/null +++ b/src/main/java/fr/insee/protools/backend/service/traiterxxxx/TraiterXXXServiceImpl.java @@ -0,0 +1,51 @@ +package fr.insee.protools.backend.service.traiterxxxx; + +import com.fasterxml.jackson.databind.JsonNode; +import fr.insee.protools.backend.restclient.RestClientHelper; +import fr.insee.protools.backend.restclient.configuration.ApiConfigProperties; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.stereotype.Service; + +import java.util.List; + +import static fr.insee.protools.backend.restclient.configuration.ApiConfigProperties.KNOWN_API.KNOWN_API_TRAITERXXX; + +@Service +@Slf4j +@RequiredArgsConstructor +public class TraiterXXXServiceImpl implements ITraiterXXXService{ + + private final RestClientHelper restClientHelper; + private static final ApiConfigProperties.KNOWN_API API = KNOWN_API_TRAITERXXX; + + @Override + public List getRemiseEnCollecteForPartition(String partitionId) { + log.debug("getRemiseEnCollecteForPartition - partitionId={} ",partitionId); + ParameterizedTypeReference> typeReference = new ParameterizedTypeReference<>() { }; + + List response = restClientHelper.getRestClient(API) + .get() + .uri(uriBuilder -> uriBuilder + .path("/remise-en-collecte") + .queryParam("partition_id", partitionId) + .build()) + .retrieve() + .body(typeReference); + log.trace("getRemiseEnCollecteForPartition={} - response={} ", partitionId, response); + return response; + } + + @Override + public void postContext(String campaignId,JsonNode contextRootNode) { + log.trace("postContext: campaignId={}",campaignId); + var response = restClientHelper.getRestClient(API) + .post() + .uri("/context") + .body(contextRootNode) + .retrieve() + .body(String.class); + log.trace("postContext: campaignId={} - response={} ",campaignId,response); + } +} diff --git a/src/main/java/fr/insee/protools/backend/service/traiterxxxx/delegate/TraiterXXXCreateContextTaskREST.java b/src/main/java/fr/insee/protools/backend/service/traiterxxxx/delegate/TraiterXXXCreateContextTaskREST.java new file mode 100644 index 00000000..6009f98b --- /dev/null +++ b/src/main/java/fr/insee/protools/backend/service/traiterxxxx/delegate/TraiterXXXCreateContextTaskREST.java @@ -0,0 +1,34 @@ +package fr.insee.protools.backend.service.traiterxxxx.delegate; + +import com.fasterxml.jackson.databind.JsonNode; +import fr.insee.protools.backend.dto.ContexteProcessus; +import fr.insee.protools.backend.service.DelegateContextVerifier; +import fr.insee.protools.backend.service.context.IContextService; +import fr.insee.protools.backend.service.traiterxxxx.ITraiterXXXService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.flowable.engine.delegate.DelegateExecution; +import org.flowable.engine.delegate.JavaDelegate; +import org.springframework.stereotype.Component; + +@Slf4j +@RequiredArgsConstructor +@Component +public class TraiterXXXCreateContextTaskREST implements JavaDelegate, DelegateContextVerifier { + private final IContextService protoolsContext; + private final ITraiterXXXService service; + + @Override + public void execute(DelegateExecution execution) { + log.info("ProcessInstanceId={} begin",execution.getProcessInstanceId()); + JsonNode contextRootNode = protoolsContext.getContextJsonNodeByProcessInstance(execution.getProcessInstanceId()); + ContexteProcessus contexteProcessus = protoolsContext.getContextDtoByProcessInstance(execution.getProcessInstanceId()); + + checkContextOrThrow(log,execution.getProcessInstanceId(), contexteProcessus); + String campainId = contexteProcessus.getId().toString(); + + service.postContext(campainId,contextRootNode); + + log.info("ProcessInstanceId={} end",execution.getProcessInstanceId()); + } +} diff --git a/src/main/java/fr/insee/protools/backend/service/traiterxxxx/delegate/TraiterXXXGetRemiseEnCollecteTaskREST.java b/src/main/java/fr/insee/protools/backend/service/traiterxxxx/delegate/TraiterXXXGetRemiseEnCollecteTaskREST.java new file mode 100644 index 00000000..94afb5cd --- /dev/null +++ b/src/main/java/fr/insee/protools/backend/service/traiterxxxx/delegate/TraiterXXXGetRemiseEnCollecteTaskREST.java @@ -0,0 +1,34 @@ +package fr.insee.protools.backend.service.traiterxxxx.delegate; + +import com.fasterxml.jackson.databind.JsonNode; +import fr.insee.protools.backend.service.DelegateContextVerifier; +import fr.insee.protools.backend.service.traiterxxxx.ITraiterXXXService; +import fr.insee.protools.backend.service.utils.FlowableVariableUtils; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.flowable.engine.delegate.DelegateExecution; +import org.flowable.engine.delegate.JavaDelegate; +import org.springframework.stereotype.Component; + +import java.util.List; + +import static fr.insee.protools.backend.service.FlowableVariableNameConstants.VARNAME_CURRENT_PARTITION_ID; +import static fr.insee.protools.backend.service.FlowableVariableNameConstants.VARNAME_INTERRO_REMISE_EN_COLLECTE_LIST; + +@Slf4j +@RequiredArgsConstructor +@Component +public class TraiterXXXGetRemiseEnCollecteTaskREST implements JavaDelegate, DelegateContextVerifier { + private final ITraiterXXXService service; + + @Override + public void execute(DelegateExecution execution) { + String currentPartitionId = FlowableVariableUtils.getVariableOrThrow(execution, VARNAME_CURRENT_PARTITION_ID, String.class); + log.info("ProcessInstanceId={} - currentPartitionId={} begin",execution.getProcessInstanceId(),currentPartitionId); + + List interroRemiseEnCollecteList = service.getRemiseEnCollecteForPartition(currentPartitionId); + execution.getParent().setVariableLocal(VARNAME_INTERRO_REMISE_EN_COLLECTE_LIST,interroRemiseEnCollecteList); + + log.info("ProcessInstanceId={} - currentPartitionId={} - end",execution.getProcessInstanceId(),currentPartitionId); + } +} diff --git a/src/main/java/fr/insee/protools/backend/service/utils/ContextUtils.java b/src/main/java/fr/insee/protools/backend/service/utils/ContextUtils.java deleted file mode 100644 index bbf7b5b8..00000000 --- a/src/main/java/fr/insee/protools/backend/service/utils/ContextUtils.java +++ /dev/null @@ -1,27 +0,0 @@ -package fr.insee.protools.backend.service.utils; - -import com.fasterxml.jackson.databind.JsonNode; -import org.flowable.common.engine.api.FlowableIllegalArgumentException; - -import static fr.insee.protools.backend.service.context.ContextConstants.CTX_PARTITIONS; -import static fr.insee.protools.backend.service.context.ContextConstants.CTX_PARTITION_ID; - -public class ContextUtils { - - //Search for the current partition in the contexte. - public static JsonNode getCurrentPartitionNode(JsonNode contextRootNode, Long currentPartitionId) { - JsonNode currentPartitionNode=null; - // Search for the correct partition based on it's ID - for (JsonNode subNode : contextRootNode.path(CTX_PARTITIONS)) { - if (subNode.has(CTX_PARTITION_ID) && subNode.get(CTX_PARTITION_ID).asLong()==currentPartitionId) { - currentPartitionNode = subNode; - break; - } - } - if (currentPartitionNode == null) { - throw new FlowableIllegalArgumentException(String.format("Partition id=[%d] not found in contexte", currentPartitionId)); - } - return currentPartitionNode; - } - private ContextUtils(){} -} diff --git a/src/main/java/fr/insee/protools/backend/service/utils/FlowableVariableUtils.java b/src/main/java/fr/insee/protools/backend/service/utils/FlowableVariableUtils.java index a9dae8b3..401b33bc 100644 --- a/src/main/java/fr/insee/protools/backend/service/utils/FlowableVariableUtils.java +++ b/src/main/java/fr/insee/protools/backend/service/utils/FlowableVariableUtils.java @@ -11,6 +11,7 @@ public class FlowableVariableUtils { * Throws Protools VariableClassCastException if the cast is not successful * Throws FlowableIllegalArgumentException if the variable is not found */ + @SuppressWarnings("squid:S1192") public static T getVariableOrThrow(DelegateExecution execution, String variableName, Class variableClass ){ T res; try{ @@ -18,6 +19,9 @@ public static T getVariableOrThrow(DelegateExecution execution, String varia if(res==null){ throw new FlowableIllegalArgumentException(getMissingVariableMessage(variableName)); } + else if(!variableClass.isAssignableFrom(res.getClass())){ + throw new VariableClassCastException(String.format("Variable ID=[%s] val=[%s] cannot be casted to %s", variableName, res, variableClass)); + } } catch (ClassCastException e) { throw new VariableClassCastException(String.format("Variable ID=[%s] val=[%s] cannot be casted to %s", variableName, execution.getVariable(variableName), variableClass)); @@ -31,4 +35,18 @@ private FlowableVariableUtils(){} public static String getMissingVariableMessage(String variableName){ return "Variable '" + variableName + "' was not found"; } + + /** + * Helper to call VariableScopeImpl#getVariable(String,Class). + * Throws Protools VariableClassCastException if the cast is not successful + * return null if the variable is not defined + */ + public static T getVariableOrNull(DelegateExecution execution, String variableName, Class variableClass ){ + try{ + return execution.getVariable(variableName, variableClass); + } + catch (ClassCastException e) { + throw new VariableClassCastException(String.format("Variable ID=[%s] val=[%s] cannot be casted to %s", variableName, execution.getVariable(variableName), variableClass)); + } + } } diff --git a/src/main/java/fr/insee/protools/backend/service/utils/delegate/PaginationHelper.java b/src/main/java/fr/insee/protools/backend/service/utils/delegate/PaginationHelper.java new file mode 100644 index 00000000..ab3194d1 --- /dev/null +++ b/src/main/java/fr/insee/protools/backend/service/utils/delegate/PaginationHelper.java @@ -0,0 +1,82 @@ +package fr.insee.protools.backend.service.utils.delegate; + +import com.fasterxml.jackson.databind.JsonNode; +import fr.insee.protools.backend.restclient.pagination.PageResponse; +import fr.insee.protools.backend.service.exception.PageableAPIBPMNError; +import fr.insee.protools.backend.service.utils.FlowableVariableUtils; +import org.flowable.engine.delegate.DelegateExecution; + +import java.util.List; +import java.util.Map; + + +public interface PaginationHelper { + + org.slf4j.Logger getLogger(); + + /** + * Custom Treatment for the page + * + * @return a Modifiable MAP with variables to update on the process instance (so we can make a single setVariablesLocal in getAndTreat) + */ + Map treatPage(DelegateExecution execution, List contentList); + + /** + * Default way to read elements with a paginated API. + * getAndTreat It will read a page using IGetFromService. + * For this page it will call treatPage + * variables in the map returned by treatPage() will be added to the local variables of the execution + * It will update the varname_is_last_page and varname_current_page variables + * + * @param execution + * @param varname_current_page + * @param varname_is_last_page + * @param getService a functional interface to be used for the read + * @param getServiceParams the parameters for the functional interface call + */ + default void getAndTreat(DelegateExecution execution, String varname_current_page, String varname_is_last_page, IGetFromService getService, Object... getServiceParams) { + getLogger().info("ProcessInstanceId={} begin", execution.getProcessInstanceId()); + + Integer currentPage = FlowableVariableUtils.getVariableOrNull(execution, varname_current_page, Integer.class); + Boolean isLastPage = FlowableVariableUtils.getVariableOrNull(execution, varname_is_last_page, Boolean.class); + + Integer expectedPage; + if (currentPage == null) { + expectedPage = 0; + } else { + expectedPage = currentPage + 1; + } + + if (isLastPage == null) { + isLastPage = Boolean.FALSE; + } + + if (Boolean.TRUE.equals(isLastPage)) { + getLogger().warn("ProcessInstanceId={} : last page already reached", execution.getProcessInstanceId()); + } else { + + PageResponse pageResponse = getService.apply(expectedPage, getServiceParams); + + //Verify that we got the correct page with not null content + if (!pageResponse.getCurrentPage().equals(expectedPage)) { + throw new PageableAPIBPMNError(String.format("Error while reading interrogations from REM - expected page=%s got page=%s", expectedPage, pageResponse.getCurrentPage())); + } else if (pageResponse.getContent() == null) { + throw new PageableAPIBPMNError("Error while reading interrogations from REM - content is null"); + } + + //Treat the response + Map variables = treatPage(execution, pageResponse.getContent()); + + //Add pagination details to the variables we are going to insert + variables.put(varname_current_page, expectedPage); + variables.put(varname_is_last_page, pageResponse.isLastPage()); + execution.getParent().setVariablesLocal(variables); + getLogger().debug("ProcessInstanceId={} - readSize={} end", execution.getProcessInstanceId(), pageResponse.getContent().size()); + } + } + + @FunctionalInterface + interface IGetFromService { + PageResponse apply(Integer pageToRead, Object... params); + } +} diff --git a/src/main/java/fr/insee/protools/backend/service/utils/log/TimeLogUtils.java b/src/main/java/fr/insee/protools/backend/service/utils/log/TimeLogUtils.java new file mode 100644 index 00000000..d886745a --- /dev/null +++ b/src/main/java/fr/insee/protools/backend/service/utils/log/TimeLogUtils.java @@ -0,0 +1,19 @@ +package fr.insee.protools.backend.service.utils.log; +import java.time.Instant; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; + +public class TimeLogUtils { + + private TimeLogUtils() {} + private static final DateTimeFormatter formatter = DateTimeFormatter.ISO_OFFSET_DATE_TIME; + private static final ZoneId zone = ZoneId.systemDefault(); + + public static String format(Instant i){ + if(i==null) { + return "Empty"; + } + + return i.atZone(zone).format(formatter); + } +} diff --git a/src/main/java/fr/insee/protools/backend/service/utils/password/PasswordService.java b/src/main/java/fr/insee/protools/backend/service/utils/password/PasswordService.java index da2e8924..84abd86b 100644 --- a/src/main/java/fr/insee/protools/backend/service/utils/password/PasswordService.java +++ b/src/main/java/fr/insee/protools/backend/service/utils/password/PasswordService.java @@ -2,5 +2,5 @@ public interface PasswordService { - String generatePassword(); + String generatePassword(int pCreateSize); } diff --git a/src/main/java/fr/insee/protools/backend/service/utils/password/PasswordServiceImpl.java b/src/main/java/fr/insee/protools/backend/service/utils/password/PasswordServiceImpl.java index 8058a27f..e537c717 100644 --- a/src/main/java/fr/insee/protools/backend/service/utils/password/PasswordServiceImpl.java +++ b/src/main/java/fr/insee/protools/backend/service/utils/password/PasswordServiceImpl.java @@ -11,9 +11,6 @@ @Service public class PasswordServiceImpl implements PasswordService { - @Value("${fr.insee.protools.password.create.length:12}") - private int pCreateSize; - @Value("${fr.insee.protools.password.create.withDigits:true}") private boolean pCreateWithDigits; @@ -27,7 +24,7 @@ public class PasswordServiceImpl implements PasswordService { private boolean pCreateWithSpecial; @Override - public String generatePassword() { + public String generatePassword(int pCreateSize) { PasswordGenerator passwordGenerator = new PasswordGenerator(); return passwordGenerator.generatePassword( diff --git a/src/main/java/fr/insee/protools/backend/webclient/KeycloakHeadersFilter.java b/src/main/java/fr/insee/protools/backend/webclient/KeycloakHeadersFilter.java deleted file mode 100644 index 551634ec..00000000 --- a/src/main/java/fr/insee/protools/backend/webclient/KeycloakHeadersFilter.java +++ /dev/null @@ -1,42 +0,0 @@ -package fr.insee.protools.backend.webclient; - - -import fr.insee.protools.backend.webclient.configuration.APIProperties; -import fr.insee.protools.backend.webclient.exception.KeycloakTokenConfigBPMNError; -import fr.insee.protools.backend.webclient.exception.KeycloakTokenConfigUncheckedBPMNError; -import org.springframework.http.MediaType; -import org.springframework.web.reactive.function.client.ClientRequest; -import org.springframework.web.reactive.function.client.ClientResponse; -import org.springframework.web.reactive.function.client.ExchangeFilterFunction; -import org.springframework.web.reactive.function.client.ExchangeFunction; -import reactor.core.publisher.Mono; - -/** - * Class in charge of adding the correct bearer token for API calls - * It will retrieve a fresh token if needed using our KeycloakService - */ -class KeycloakHeadersFilter implements ExchangeFilterFunction { - - KeycloakService keycloakService; - //Configuration of the connexion to the auth server - private APIProperties.AuthProperties authProperties; - - public KeycloakHeadersFilter(KeycloakService keycloakService, APIProperties.AuthProperties authProperties) { - this.keycloakService = keycloakService; - this.authProperties = authProperties; - } - - @Override - public Mono filter(ClientRequest request, ExchangeFunction next) { - return next.exchange(ClientRequest.from(request) - .headers(headers -> { - try { - headers.setBearerAuth(keycloakService.getToken(authProperties)); - } catch (KeycloakTokenConfigBPMNError e) { - throw new KeycloakTokenConfigUncheckedBPMNError(e); - } - headers.setContentType(MediaType.APPLICATION_JSON); - }) - .build()); - } -} diff --git a/src/main/java/fr/insee/protools/backend/webclient/Token.java b/src/main/java/fr/insee/protools/backend/webclient/Token.java deleted file mode 100644 index 2a6cdf8d..00000000 --- a/src/main/java/fr/insee/protools/backend/webclient/Token.java +++ /dev/null @@ -1,11 +0,0 @@ -package fr.insee.protools.backend.webclient; - -class Token { - public final String value; - public final long endValidityTimeMillis; - - public Token(String value, long endValidityTimeMillis) { - this.value = value; - this.endValidityTimeMillis = endValidityTimeMillis; - } -} diff --git a/src/main/java/fr/insee/protools/backend/webclient/WebClientHelper.java b/src/main/java/fr/insee/protools/backend/webclient/WebClientHelper.java deleted file mode 100644 index 4c12e189..00000000 --- a/src/main/java/fr/insee/protools/backend/webclient/WebClientHelper.java +++ /dev/null @@ -1,307 +0,0 @@ -package fr.insee.protools.backend.webclient; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ArrayNode; -import com.fasterxml.jackson.databind.node.ObjectNode; -import fr.insee.protools.backend.webclient.configuration.APIProperties; -import fr.insee.protools.backend.webclient.configuration.ApiConfigProperties; -import fr.insee.protools.backend.webclient.exception.ApiNotConfiguredBPMNError; -import fr.insee.protools.backend.webclient.exception.KeycloakTokenConfigBPMNError; -import fr.insee.protools.backend.webclient.exception.runtime.WebClient4xxBPMNError; -import fr.insee.protools.backend.webclient.exception.runtime.WebClient5xxBPMNError; -import fr.insee.protools.backend.webclient.exception.runtime.WebClientNetworkExceptionBPMNError; -import fr.insee.protools.backend.webclient.exception.runtime.WebClientRequestExceptionBPMNError; -import io.netty.channel.ConnectTimeoutException; -import io.netty.handler.logging.LogLevel; -import lombok.extern.slf4j.Slf4j; -import org.slf4j.Logger; -import org.slf4j.event.Level; -import org.springframework.http.HttpStatus; -import org.springframework.http.HttpStatusCode; -import org.springframework.http.client.reactive.ReactorClientHttpConnector; -import org.springframework.lang.Nullable; -import org.springframework.stereotype.Component; -import org.springframework.web.reactive.function.client.ClientResponse; -import org.springframework.web.reactive.function.client.WebClient; -import org.springframework.web.reactive.function.client.WebClientRequestException; -import reactor.core.publisher.Mono; -import reactor.netty.http.client.HttpClient; -import reactor.netty.http.client.PrematureCloseException; -import reactor.netty.transport.logging.AdvancedByteBufFormat; - -import java.lang.reflect.Field; -import java.net.SocketException; -import java.net.UnknownHostException; -import java.nio.channels.UnresolvedAddressException; -import java.util.*; - -/** - * Helper class for WebClient - */ -@Component -@Slf4j -public class WebClientHelper { - - private static final int DEFAULT_FILE_BUFFER_SIZE = 100 * 1024*1024; - private static final int DEFAULT_API_BUFFER_SIZE = 100 * 1024*1024; - private final KeycloakService keycloakService; - private final ApiConfigProperties apiConfigProperties; - - private final EnumMap initializedClients = new EnumMap<>(ApiConfigProperties.KNOWN_API.class); - - public WebClientHelper(KeycloakService keycloakService, ApiConfigProperties apiConfigProperties) { - this.keycloakService = keycloakService; - this.apiConfigProperties = apiConfigProperties; - } - - //I cannot have a single builder and store it in a private variable because every call to .filter(...) append a new filter to the builder - private WebClient.Builder getBuilder() { - return WebClient.builder() - .defaultStatusHandler(HttpStatusCode::isError, clientResponse -> - { - String initialRequestDescription = extractClientResponseRequestDescriptionPrivateFiledUsingReflexion(clientResponse); - Mono result; - String errorMsg = String.format("request=[%s] - statusCode=[%s]", - initialRequestDescription,clientResponse.statusCode()); - if (clientResponse.statusCode() == HttpStatus.UNAUTHORIZED) { - //Keycloak error? - errorMsg = "HttpStatus.UNAUTHORIZED. WWW-Authenticate=[" + String.join("", clientResponse.headers().header("WWW-Authenticate") + "]"); - } - - String finalErrorMsg = errorMsg; - result = clientResponse.bodyToMono(String.class).defaultIfEmpty("No error message provided by API") - .flatMap(error -> { - if (clientResponse.statusCode().is4xxClientError()) { - return Mono.error(new WebClient4xxBPMNError(finalErrorMsg + " - " + error, clientResponse.statusCode())); - } else { - return Mono.error(new WebClient5xxBPMNError(finalErrorMsg + " - " + error)); - } - }); - return result; - } - ) - .filter((request, next) -> - next.exchange(request) - .onErrorResume(WebClientRequestException.class, ex -> { - //TODO : here i can access the method and URI ; could be usefull to log ?? - if(containsCauseOfType(ex, - List.of(SocketException.class,UnresolvedAddressException.class,PrematureCloseException.class, - ConnectTimeoutException.class, UnknownHostException.class))){ - return Mono.error(new WebClientNetworkExceptionBPMNError(ex)); - } - return Mono.error(new WebClientRequestExceptionBPMNError(ex)); - }) - ) - //To allow up to 20Mb - .codecs(configurer -> configurer.defaultCodecs().maxInMemorySize(DEFAULT_API_BUFFER_SIZE)) - .clientConnector( - new ReactorClientHttpConnector( - HttpClient.create() - //Handles a proxy conf passed on system properties - .proxyWithSystemProperties() - //enable logging of request/responses - //configurable in properties as if it was this class logers - .wiretap(this.getClass().getCanonicalName(), LogLevel.DEBUG, AdvancedByteBufFormat.TEXTUAL))); - } - - public static void logJson(String msg, Object dto, Logger logger, Level level) { - if (logger.isEnabledForLevel(level)) { - try { - String json = new ObjectMapper().writeValueAsString(dto); - String logLine = msg +" - " + json; - switch (level) { - case TRACE -> logger.trace(logLine); - case DEBUG -> logger.debug(logLine); - case INFO -> logger.info(logLine); - case WARN -> logger.warn(logLine); - case ERROR -> logger.error(logLine); - default -> logger.trace(logLine); - } - } catch (JsonProcessingException e) { - log.error("Could not parse json"); - } - } - } - - /** - * init a new WebClient proxy aware (default one ignore system proxy) - */ - public WebClient getWebClient() { - return getBuilder() - .build(); - } - - /** - * init a new WebClient proxy aware (default one ignore system proxy) - * with increased buffer size to 20Mo - * - * @return a Webclient - */ - public WebClient getWebClientForFile() { - return getWebClientForFile(DEFAULT_FILE_BUFFER_SIZE); - } - - public static int getDefaultFileBufferSize() { return DEFAULT_FILE_BUFFER_SIZE; } - - /** - * init a new WebClient proxy aware (default one ignore system proxy) - * with increased buffer size to - * - * @return a Webclient - */ - public WebClient getWebClientForFile(int byteCount) { - return getBuilder() - .codecs(configurer -> configurer.defaultCodecs().maxInMemorySize(byteCount)) - .build(); - } - - /** - * Get a webclient preconfigured for proxy and able to get the JWT token required for authentification - * - * @param api the client will connect to this api - * @return preconfigured WebClient for the api - */ - public WebClient getWebClient(ApiConfigProperties.KNOWN_API api) { - APIProperties apiProperties = apiConfigProperties.getAPIProperties(api); - if (apiProperties == null) { - throw new ApiNotConfiguredBPMNError(String.format("API %s is not configured in properties", api)); - } else if (Boolean.FALSE.equals(apiProperties.getEnabled())) { - throw new ApiNotConfiguredBPMNError(String.format("API %s is disabled in properties", api)); - } - return initializedClients.computeIfAbsent(api, - knownApi -> - getBuilder() - .filter(new KeycloakHeadersFilter(keycloakService, apiProperties.getAuth())) - .baseUrl(apiProperties.getUrl()) - .build()); - } - - - public Map getTokenDetailsByAPI(){ - Map result = new HashMap<>(); - for (var api :ApiConfigProperties.KNOWN_API.values() ) { - try { - APIProperties apiProperties = apiConfigProperties.getAPIProperties(api); - if (apiProperties == null) { - throw new ApiNotConfiguredBPMNError(String.format("API %s is not configured in properties", api)); - } else if (Boolean.FALSE.equals(apiProperties.getEnabled())) { - throw new ApiNotConfiguredBPMNError(String.format("API %s is disabled in properties", api)); - } - var token = keycloakService.getToken(apiProperties.getAuth()); - if(token !=null && !token.isBlank()) { - String details = analyseToken(token); - result.put(api.name(),details); - - } - } catch (KeycloakTokenConfigBPMNError | ApiNotConfiguredBPMNError e) { - result.put(api.name(),e.getMessage()); - } - catch (Exception e){ - result.put(api.name(),"Internal error with token"); - } - } - return result; - } - - /** - * @return A json with the configuration of the APIs handled by protools - */ - public JsonNode getAPIConfigDetails(){ - ObjectMapper objectMapper = new ObjectMapper(); - ArrayNode rootNode = objectMapper.createArrayNode(); - for (var api :ApiConfigProperties.KNOWN_API.values() ) { - APIProperties apiProperties = apiConfigProperties.getAPIProperties(api); - ObjectNode apiNode = objectMapper.valueToTree(apiProperties); - apiNode.put("name",api.name()); - rootNode.add(apiNode); - } - return rootNode; - } - - //analyse a single token to retrieve roles - private static String analyseToken(String token) { - String result; - String[] chunks = token.split("\\."); - if(chunks.length<2){ - return "Token size is incorrect. It should contain at least one dot"; - } - Base64.Decoder decoder = Base64.getUrlDecoder(); - String payload = new String(decoder.decode(chunks[1])); - ObjectMapper objectMapper = new ObjectMapper(); - try { - JsonNode tokenPayloadNode = objectMapper.readTree(payload); - String roles = tokenPayloadNode.path("realm_access").path("roles").toString(); - if(roles==null || roles.isBlank()){ - result="No Role found in token"; - } - else{ - result= roles; - } - } catch (JsonProcessingException e) { - result=payload; - } - return result; - } - - /** - * Hack function to access the requestDescription private filed - * will only work if clientResponse is an instance od DefaultClientResponse which has this field - * this hack is mandatory to know the original call while handling an error - * @param clientResponse the object to treat. - * @return the original call made or an error message if it is not possible - */ - private static String extractClientResponseRequestDescriptionPrivateFiledUsingReflexion(ClientResponse clientResponse){ - try { - Field privateField = clientResponse.getClass().getDeclaredField("requestDescription"); - // Set the accessibility as true - privateField.setAccessible(true); - // Store the value of private field in variable - return (String)privateField.get(clientResponse); - } catch (Exception e) { - log.error("Internal error while trying to extract the requestDescription from ClientResponse"); - return "Initial request cannot be retrieved"; - } - } - - /** - * special version of NestedRuntimeException.contains accepting a list of types : - * Check whether the Ex exception contains an exception of the given list of types: - * either it is of the given class itself or it contains a nested cause of one of these types. - * @param ex : The exception - * @param exTypes : The searched types - * @return true if a matching exception type has been found - */ - @SuppressWarnings("java:S3776") - protected static boolean containsCauseOfType(Exception ex, @Nullable List> exTypes) { - if (exTypes == null || exTypes.isEmpty()) { - return false; - } else { - if (exTypes.stream().anyMatch(exType -> exType.isInstance(ex))) { - return true; - } - - //Current exception is not of the configured types ; check parents - Throwable cause = ex.getCause(); - if (cause == ex) { - return false; - } else { - while (cause != null) { - Throwable finalCause = cause; //to be used in lambda - if (exTypes.stream().anyMatch(exType -> exType.isInstance(finalCause))) { - return true; - } - - if (cause.getCause() == cause) { - break; - } - - cause = cause.getCause(); - } - - return false; - } - } - } -} diff --git a/src/main/resources/application-dev.properties b/src/main/resources/application-dev.properties index 71479ab4..daed1da8 100644 --- a/src/main/resources/application-dev.properties +++ b/src/main/resources/application-dev.properties @@ -21,7 +21,7 @@ springdoc.swagger-ui.oauth.clientId=localhost-frontend fr.insee.sndil.starter.auth.url=${fr.insee.protools.keycloak-interne-auth-url} #URL For nomenclatures service -fr.insee.protools.nomenclature.uri=https://gitlab.insee.fr/enquetes-menages/integration-metallica/-/raw/master/Nomenclatures +fr.insee.protools.nomenclature.uri=https://gitlab.insee.fr/enquetes-menages/integration-metallica/-/raw/master/_Nomenclatures #URL For questionnaire models service fr.insee.protools.questionnaire.model.uri=https://gitlab.insee.fr/enquetes-menages/integration-metallica/-/raw/master/Questionnaire-Models @@ -39,6 +39,7 @@ fr.insee.protools.api.platine-pilotage.auth.client-id=${fr.insee.protools.keyclo fr.insee.protools.api.platine-pilotage.auth.client-secret=${fr.insee.protools.token.provider.dmz-questionnaire-particuliers.client-secret} fr.insee.protools.api.platine-pilotage.auth.realm=questionnaire-particuliers fr.insee.protools.api.platine-pilotage.auth.url=${fr.insee.protools.keycloak-dmz-auth-url} +fr.insee.protools.api.platine-pilotage.interrogation.page.size=4 #platine questionnaire fr.insee.protools.api.platine-questionnaire.enabled=true @@ -74,6 +75,7 @@ fr.insee.protools.api.rem.auth.client-id=${fr.insee.protools.keycloak.client.id} fr.insee.protools.api.rem.auth.client-secret=${fr.insee.protools.token.provider.interne-agents-insee-interne.client-secret} fr.insee.protools.api.rem.auth.realm=agents-insee-interne fr.insee.protools.api.rem.auth.url=${fr.insee.protools.keycloak-interne-auth-url} +fr.insee.protools.api.rem.interrogation.page.size=4 #ERA fr.insee.protools.api.era.enabled=true @@ -93,7 +95,7 @@ fr.insee.protools.api.meshuggah.auth.url=${fr.insee.protools.keycloak-interne-au #SUGOI externe fr.insee.protools.api.sugoi.enabled=true -fr.insee.protools.api.sugoi.url=https://api.comptes-utilisateurs.recette.insee.fr/ +fr.insee.protools.api.sugoi.url=https://api.gestion-comptes-utilisateurs.recette.insee.fr/ fr.insee.protools.api.sugoi.auth.client-id=${fr.insee.protools.keycloak.client.id} fr.insee.protools.api.sugoi.auth.client-secret=${fr.insee.protools.token.provider.interne-agents-insee-interne.client-secret} fr.insee.protools.api.sugoi.auth.realm=agents-insee-interne @@ -101,20 +103,8 @@ fr.insee.protools.api.sugoi.auth.url=${fr.insee.protools.keycloak-interne-auth-u fr.insee.protools.api.sugoi.dmz-account-creation-realm=questionnaire-particuliers ######################### Log des properties ######################### -#fr.insee.properties.log.key.select : NONE ALL ou PREFIX(default) - -#Pour desactviter le log des properties -#fr.insee.properties.log.key.select=NONE - -#Pour afficher toutes les properties sans prendre en compte leur prefixe -#propritete de test qui sera affichee avec des **** (non affichee par defaut avec PREFIX) -#fr.pwd=toto -#Avec ce parametre, la property fr.pwd est affichee (on ignore les prefixes), on a donc toutes les properties -#fr.insee.properties.log.key.select=ALL -#Avec ce parametre, si on est en mode PREFIX, on ne voit que fr.pwd ; si on est en mode ALL aucun effet -#fr.insee.properties.log.key.prefixes=fr.pwd -#Avec ce parametre, si on est en mode PREFIX, va afficher uniquement les properties commencant par fr.insee et fr.pwd -#fr.insee.properties.log.key.prefixes=fr.pwd,fr.insee +properties.logger.prefix-for-properties = fr.insee, debug, info, logging, spring, server,management, keycloak, springdoc + #Log logging.level.fr.insee.protools=INFO diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index a2d213ee..bac29e58 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,3 +1,6 @@ +#Local MongoDB config +spring.data.mongodb.uri=mongodb://${MONGO_USER}:${MONGO_PASSWORD}@${MONGO_URL}:${MONGO_PORT}/${MONGO_COLLECTION}?&authSource=${MONGO_COLLECTION} + #Role administrateur (au sens keycloak, creable et administrable via sugoi) #https://gestion-comptes-utilisateurs.recette.insee.fr/ #ce role protege le endpoint starter/healthcheckadmin @@ -9,7 +12,6 @@ fr.insee.protools.keycloak.client.id=protools-service spring.banner.location=classpath:/banner.txt #Password generation rules -fr.insee.protools.password.create.length=12 fr.insee.protools.password.create.withDigits=true fr.insee.protools.password.create.withUpperCase=true fr.insee.protools.password.create.withLowerCase=true diff --git a/src/main/resources/processes/proto_platine_pagination_v1.bpmn b/src/main/resources/processes/proto_platine_pagination_v1.bpmn new file mode 100644 index 00000000..da43934c --- /dev/null +++ b/src/main/resources/processes/proto_platine_pagination_v1.bpmn @@ -0,0 +1,302 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/schema/contexte-processus.json b/src/main/resources/schema/contexte-processus.json new file mode 100644 index 00000000..1c8f32ad --- /dev/null +++ b/src/main/resources/schema/contexte-processus.json @@ -0,0 +1,1094 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://example.com/product.schema.json", + "title": "Contexte de processus", + "description": "Le contexte d'un processus", + "type": "object", + "properties": { + "id": { + "description": "Identifiant de la campagne", + "type": "string", + "format": "uuid" + }, + "labelCourt": { + "description": "Nom technique de la campagne. Ex: PRO2024X03", + "type": "string" + }, + "label": { + "description": "Intitulé de la campagne", + "type": "string" + }, + "contexte": { + "description": "Indique s'il s'agit d'une campagne ménage ou entreprise", + "type": "string", + "enum": [ + "menage", + "entreprise" + ] + }, + "metadonnees": { + "type": "object", + "properties": { + "serieId": { + "description": "Identifiant métier de la série.", + "type": "string" + }, + "serieLabelCourt": { + "type": "string" + }, + "serieLabelLong": { + "type": "string" + }, + "periodicite": { + "description": "Fréquence de la collecte (code). X: pluriannuelle; A: annuelle ; S: semestrielle ; T: trimestrielle; B: bi-mensuelle; M: mensuelle", + "enum": [ + "X", + "A", + "S", + "T", + "B", + "M" + ], + "type": "string" + }, + "periode": { + "$ref": "#/$defs/periode" + }, + "annee": { + "description": "Année de la campagne", + "$ref": "#/$defs/annee4digit" + }, + "operationId": { + "description": "Identifiant de l'opération statistique", + "type": "string" + }, + "operationLabelCourt": { + "description": "Label court de l'opération", + "type": "string" + }, + "operationLabelLong": { + "description": "Label long de l'opération", + "type": "string" + }, + "objectifsCourts": { + "description": "Objectifs de l'enquête (court)", + "type": "string" + }, + "objectifsLongs": { + "description": "Objectifs de l'enquête (long)", + "type": "string" + }, + "cnisUrl": { + "description": "URL de l'enquête sur le site du CNIS (Conseil national de l'information statistique)", + "type": "string" + }, + "diffusionUrl": { + "description": "URL d'information de diffusion sur l'enquête", + "type": "string" + }, + "noticeUrl": { + "description": "URL de la notice de l'enquête", + "type": "string" + }, + "specimenUrl": { + "description": "URL du specimen de l'enquête", + "type": "string" + }, + "numeroVisa": { + "description": "Numéro de VISA de l'enquête", + "type": "string" + }, + "anneeVisa": { + "description": "Année du VISA", + "type": "string" + }, + "caractereObligatoire": { + "description": "Caractère obligatoire de l'enquête", + "type": "boolean" + }, + "interetGeneral": { + "description": "L'enquête est elle d'intêret général", + "type": "boolean" + }, + "qualiteStatistique": { + "description": "Obtention du caractère de qualité statistique de l'enquête", + "type": "boolean" + }, + "testNonLabellise": { + "description": "Enquête non labellisée", + "type": "boolean" + }, + "parutionJo": { + "description": "Publication du visa Cnis au journal officiel", + "type": "boolean" + }, + "dateParutionJo": { + "description": "Date de publication au journal officiel, apparaissant sur les courriers/mails envoyés aux enquêtés", + "type": "string", + "format": "date" + }, + "portailMesEnquetesOperation": { + "description": "Présence ou non d'un portail Mes enquêtes pour la réponse à une enquête web", + "type": "boolean" + }, + "proprietaireId": { + "description": "Identifiant du propriétaire de l'enquête", + "type": "string" + }, + "proprietaireLabel": { + "description": "Nom du propriétaire de l'enquête", + "type": "string" + }, + "imageLogos": { + "description": "Logo de l'entête des courriers envoyés aux enquêtés", + "type": "string" + }, + "ministereTutelle": { + "description": "Ministère de tutelle pour cette enquête", + "type": "string" + }, + "commanditaire": { + "description": "Le ou les organisme(s) en charge de l’enquête statistique affiché(s) sur les courriers envoyés aux enquêtés.", + "type": "string" + }, + "responsableOperationnel": { + "description": "Responsable opérationnel en charge du traitement pour l’exercice des droits", + "type": "string" + }, + "mailResponsableOperationnel": { + "description": "Mail du responsable opérationnel du traitement pour l’exercice des droits", + "type": "string" + }, + "responsableTraitement": { + "description": "Nom du responsable du traitement", + "type": "string" + }, + "responsableTraitementIdenti": { + "description": "Nom court du responsable du traitement", + "type": "string" + }, + "responsableTraitementIdentiFem": { + "description": "Genre féminin du responsable du traitement", + "type": "boolean" + }, + "urlResponsableTraitement": { + "description": "Url du site du responsable du traitement", + "type": "string" + }, + "prestataire": { + "description": "Présence d'un prestataire pour réaliser l'enquête", + "type": "boolean" + }, + "nomPrestataire": { + "description": "Nom du prestataire", + "type": "string" + }, + "urlPrestataire": { + "description": "URL du prestataire", + "type": "string" + }, + "logoPartenaire": { + "description": "Logo du partenaire de l'Insee participant à l'enquête, affiché dans les mails envoyés aux enquêtés", + "type": "string" + }, + "serviceCollecteurSignataireFonction": { + "description": "Fonction du signataire des communications", + "type": "string" + }, + "serviceCollecteurSignataireNom": { + "description": "Prénom et nom du signataire des communications", + "type": "string" + }, + "imageLogoSignataire": { + "description": "Logo affiché dans les courriers envoyés aux enquêtés, à côté du signataire du courrier", + "type": "string" + }, + "assistanceTel": { + "description": "Numéro de téléphone pour l'assistance, affiché sur les courriers", + "type": "string" + }, + "assistanceMail": { + "description": "Assistance par internet, affiché dans la rubrique Nous contacter des courriers", + "type": "string" + }, + "assistanceAdresseL1": { + "description": "Ligne 1 de l'adresse postale de l'assistance, affiché sur les courriers", + "type": "string" + }, + "assistanceAdresseL2": { + "description": "Ligne 2 de l'adresse postale de l'assistance, affiché sur les courriers", + "type": "string" + }, + "assistanceAdresseL3": { + "description": "Ligne 3 de l'adresse postale de l'assistance, affiché sur les courriers", + "type": "string" + }, + "assistanceAdresseL4": { + "description": "Ligne 4 de l'adresse postale de l'assistance, affiché sur les courriers", + "type": "string" + }, + "assistanceAdresseL5": { + "description": "Ligne 5 de l'adresse postale de l'assistance, affiché sur les courriers", + "type": "string" + }, + "adresseRetourQL1": { + "description": "Adresse du site en charge de la numérisation des questionnaires papier – ligne 1", + "type": "string" + }, + "adresseRetourQL2": { + "description": "Adresse du site en charge de la numérisation des questionnaires papier – ligne 2", + "type": "string" + }, + "adresseRetourQL3": { + "description": "Adresse du site en charge de la numérisation des questionnaires papier – ligne 3", + "type": "string" + }, + "adresseRetourQL4": { + "description": "Adresse du site en charge de la numérisation des questionnaires papier – ligne 4", + "type": "string" + }, + "adresseRetourQL5": { + "description": "XAdresse du site en charge de la numérisation des questionnaires papier – ligne 5", + "type": "string" + }, + "adresseRetourQL6": { + "description": "Adresse du site en charge de la numérisation des questionnaires papier – ligne 6", + "type": "string" + }, + "adresseRetourQL7": { + "description": "Adresse du site en charge de la numérisation des questionnaires papier – ligne 7", + "type": "string" + }, + "representantLegal": { + "description": "Mention des représentants légaux dans les courriers", + "type": "boolean" + }, + "mineur": { + "description": "Présence de mineurs parmi les personnes échantillonnées", + "type": "boolean" + }, + "mineurDroit": { + "description": "Phrase à ajouter dans le cartouche en cas de présence de mineurs parmi les personnes échantillonnées", + "type": "string" + }, + "dpd": { + "description:": "Mention du délégué à la protection des données dans les courriers et mails envoyés aux enquêtés", + "type": "boolean" + }, + "mailDPD": { + "description:": "Mail du délégué à la protection des données du Ministère de tutelle pour l’exercice des droits", + "type": "string" + }, + "appariement": { + "description": "Données obtenues par appariement ou non, et précisés dans les courriers", + "type": "boolean" + }, + "sourceAdmin": { + "description": "Données administratives utilisées pour les appariements, affichées dans les courriers en cas d'appariement", + "type": "string" + }, + "archivage": { + "description": "Archivage ou non des données", + "type": "boolean" + }, + "dureeConservation": { + "description": "Durée de conservation des données indiquée dans le document de conformité RGPD, affichée sur les courriers aux enquêtés ", + "type": "string" + }, + "dureeConservationIdenti": { + "description": "Durée de conservation des données d’identification (affichée sur les courriers)", + "type": "string" + }, + "urlEnquete": { + "description": "Url de l’enquête", + "type": "string" + }, + "incitationARepondre": { + "description": "Phrase sur les courriers pour inciter l’enquêté à répondre à l’enquête", + "type": "string" + }, + "mailBoiteRetour": { + "description": "Boîte fonctionnelle qui accueille les échecs de remise de mail par SPOC", + "type": "string" + }, + "themeMieuxConnaitreMail": { + "description": "Texte affiché dans le bandeau du mail après le Mieux Connaître", + "type": "string" + }, + "ville": { + "description": "Ville de rédaction du courrier", + "type": "string" + }, + "complementOpportunite": { + "description": "Précisions sur l’opportunité de l’enquête dans le cadre légal", + "type": "string" + }, + "paragrapheDonneesPersonnelles": { + "description": "Affichage ou non d’un paragraphe sur les données personnelles dans les courriers", + "type": "boolean" + }, + "messageOffline": { + "description": "Message affiché sur le portail de promotion de l'enquête lorsqu'elle est terminée", + "type": "string" + }, + "messageInfoOffline": { + "description": "Message supplémentaire affiché sur le portail de promotion de l'enquête lorsqu'elle est terminée", + "type": "string" + }, + "configurationVerificationMail": { + "description": "Demande de confirmation du mail de l’enquêté à la connexion", + "type": "boolean" + }, + "imageResultat": { + "description": "Image de la rubrique Quelques résultats du portail de promotion de l’enquête", + "type": "string" + }, + "paragrapheResultat": { + "description": "Texte de la rubrique Quelques résultats du portail de promotion de l’enquête", + "type": "string" + }, + "urlInformationEnquete": { + "description": "Url de la page d’information sur l’enquête", + "type": "string" + }, + "dureeConservationDonneesConnexion": { + "description": "Durée de conservation des données de connexion, mentionné sur le portail de promotion de l'enquête", + "type": "string" + }, + "urlAQuoiServentVosReponses": { + "description": "Url affiché dans la rubrique « a quoi servent vos réponses » du portail de promotion Platine", + "type": "string" + }, + "texteUrlAQuoiServentVosReponses": { + "description": "Texte de l'url affiché dans la rubrique « a quoi servent vos réponses » du portail de promotion Platine", + "type": "string" + }, + "paragrapheAQuoiServentVosReponses": { + "description": "Paragraphe affiché dans la rubrique « a quoi servent vos réponses » du portail de promotion Platine", + "type": "string" + }, + "frequenceExtraction": { + "description": "Fréquence d'extraction des données -- Visiblement une expression de type cron ; préciser le format", + "type": "string" + }, + "cheminLivraisonDonnees": { + "description": "Pour préciser l'endroit où sont transmises les données -- A preciser format", + "type": "string" + }, + "chiffrement": { + "description": "Chiffrement des données -- A préciser le format", + "type": "string" + }, + "livraisonDifferentielle": { + "description": "Livraison différentielle des données", + "type": "boolean" + }, + "formatLivraisonDonnees": { + "description": "Format de livraison des données par le produit traiter", + "type": "string" + }, + "mailBoiteFonctionnelle": { + "description": "Boite fonctionnelle en charge de l’enquête", + "type": "string" + }, + "referents": { + "description": "Référents de l'enquête, affiché dans Sabiane Gestion - peuvent être principaux (sinon considérés comme secondaires)", + "type": "array", + "items": { + "type": "object", + "properties": { + "nom": { + "type": "string" + }, + "prenom": { + "type": "string" + }, + "telephone": { + "type": "string" + }, + "principal": { + "type": "boolean" + } + } + } + }, + "champGeographiqueEnquete": { + "description": "Champ géographique de l'enquête. Ex: France entière", + "type": "string" + }, + "champStatistiqueEnquete": { + "description": "Champ statistique de l'enquête. Ex: Tous les majeurs du ménage", + "type": "string" + }, + "urlLoiStatistique": { + "description": "URL légifrance de la loi relative aux statistiques (loi de 1951)", + "type": "string" + }, + "urlLoiRGPD": { + "description": "URL du règlement européen relatif au RGPD", + "type": "string" + }, + "urlLoiInformatique": { + "description": "URL légifrance de la loi relative à l'informatique, aux fichiers et aux libertés", + "type": "string" + } + } + }, + "lots": { + "type": "array", + "minItems": 1, + "items": { + "type": "object", + "properties": { + "id": { + "description": "Identifiant technique du lot", + "type": "string", + "format": "uuid" + }, + "label": { + "description": "Description courte du lot", + "type": "string" + }, + "lotsEnLien": { + "description": "Lots précédents et suivants pour les remises en collecte", + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "description": "Identifiant technique du lot lié", + "type": "string", + "format": "uuid" + }, + "lien": { + "description": "Lien entre le lot lié et le lot décrit. Ex: precedent ==> le lot en lien precede le lot actuel", + "type": "string", + "enum": [ + "precedent", + "suivant" + ] + }, + "regleRemiseCollecte": { + "description": "Règle de remise en collecte entre le lot décrit et le lot lié -- A PRECISER LE FORMAT", + "type": "string" + } + } + } + }, + "typeEchantillon": { + "description": "Type d'échantillon ", + "enum": [ + "logement", + "individu" + ] + }, + "modesCollecte": { + "description": "Modes de collecte de l'échantillon CAPI=XXX...", + "type": "array", + "uniqueItems": true, + "minItems": 1, + "items": { + "$ref": "#/$defs/modesDeCollecte" + } + }, + "dateDebutVisibiliteGestionnaire": { + "description": "Date de visibilité du lot dans XXX pour XXX", + "type": "string", + "format": "date-time" + }, + "dateDebutVisibiliteEnqueteur": { + "description": "Date de visibilité du lot dans Sabiane pour les enquêteurs XXX", + "type": "string", + "format": "date-time" + }, + "dateDebutReperage": { + "description": "XXX", + "type": "string", + "format": "date-time" + }, + "dateDebutCollecte": { + "description": "Date de début de la collecte", + "type": "string", + "format": "date-time" + }, + "dateFinCollecte": { + "description": "Date de fin de la collecte", + "type": "string", + "format": "date-time" + }, + "dateFinTraitementGestionnaire": { + "description": "XXX", + "type": "string", + "format": "date-time" + }, + "dateFinTraitementReprise": { + "description": "XXX", + "type": "string", + "format": "date-time" + }, + "dateRetour": { + "description": "XXX", + "type": "string", + "format": "date-time" + }, + "questionnairesModeles": { + "description": "XXX Liste des identifiants des modèles de questionnaires possibles pour les interrogations de ce lot. Ils doivent tous être décrits dans questionnairesModeles", + "type": "array", + "minItems": 1, + "items": { + "type": "string" + } + }, + "moduleCommentaire": { + "description": "XXX", + "type": "boolean" + }, + "svi": { + "description": "XXX", + "type": "boolean" + }, + "codeEnquete": { + "description": "XXX", + "type": "string" + }, + "rangInterrogation": { + "description": "XXX", + "type": "string", + "enum": [ + "entrant", + "intermediaire", + "sortant" + ] + }, + "reperage": { + "description": "XXX", + "type": "string", + "enum": [ + "aucun", + "faf_logement", + "faf_individu", + "telephone" + ] + }, + "essaisContact": { + "description": "XXX", + "type": "string" + }, + "bilanContact": { + "description": "XXX", + "type": "string" + }, + "sitesGestion": { + "description": "XXX: Sites de gestion opale XXX. doit on mettre un minItems?? potentiellement oui si sitesGestion n'est pas obligatoire", + "type": "array", + "items": { + "type": "object", + "properties": { + "idSite": { + "description": "XXX: Identifiant du site de gestion opale", + "type": "string" + }, + "assistanceMail": { + "description": "Adresse de contact pour l'assistance", + "type": "string" + }, + "assistanceTel": { + "description": "Numéro de téléphone de contact pour l'assitance", + "type": "string" + }, + "envoiCourrier": { + "description": "XXX", + "type": "boolean" + } + }, + "required": [ + "idSite" + ] + } + }, + "dureeQuestionnaire": { + "description": "Indication sur la durée du questionnaire", + "type": "string" + }, + "pasAccesInternet": { + "description": "XXX", + "type": "boolean" + }, + "numeroSequence": { + "description": "XXX", + "type": "string" + }, + "themeSequence": { + "description": "XXX", + "type": "string" + }, + "documentsPourRepondre": { + "description": "XXX", + "type": "string" + }, + "partieDeroulementEnquete": { + "description": "XXX", + "type": "boolean" + }, + "deroulementEnquete": { + "description": "XXX", + "type": "string" + }, + "imageDeroulementEnquete": { + "description": "XXX", + "type": "string" + }, + "periodePrecedenteInterrogation": { + "description": "XXX", + "type": "string" + }, + "relanceNonRepondantsWeb": { + "description": "XXX", + "type": "string" + }, + "utilisationInfo": { + "description": "XXX", + "type": "string" + }, + "utilisationInfoExemple": { + "description": "XXX", + "type": "string" + }, + "postEnquete": { + "description": "XXX", + "type": "boolean" + }, + "postEnqueteParagraphe": { + "description": "XXX", + "type": "string" + }, + "rapprochement": { + "description": "XXX", + "type": "boolean" + }, + "courrierConsigneWeb1": { + "description": "XXX", + "type": "string" + }, + "courrierConsigneWeb2": { + "description": "XXX", + "type": "string" + }, + "imageCommentRepondre": { + "description": "XXX", + "type": "string" + }, + "imageCommentRepondreSansMDP": { + "description": "XXX", + "type": "string" + }, + "imageRepondreInternet": { + "description": "XXX", + "type": "string" + }, + "papierNombre": { + "description": "XXX", + "type": "string" + }, + "papierConsigne": { + "description": "XXX", + "type": "string" + }, + "papierNombreQuest": { + "description": "XXX", + "type": "string" + }, + "consigne1": { + "description": "XXX", + "type": "string" + }, + "consigne2": { + "description": "XXX", + "type": "string" + }, + "consigne3": { + "description": "XXX", + "type": "string" + }, + "imageQrCode": { + "description": "XXX", + "type": "string" + }, + "repriseManuelle": { + "description": "XXX", + "type": "boolean" + }, + "quiRepondPageDeGarde1": { + "description": "XXX: Qui répond pour sabiane", + "type": "string" + }, + "quiRepondPageDeGarde2": { + "description": "XXX: Qui répond pour sabiane", + "type": "string" + }, + "quiRepondPageDeGarde3": { + "description": "XXX: Qui répond pour sabiane", + "type": "string" + }, + "quiRepondCommunication": { + "description": "XXX: ", + "type": "string" + }, + "quiRepondCommunication1": { + "description": "XXX: ", + "type": "string" + }, + "quiRepondCommunication2": { + "description": "XXX: ", + "type": "string" + }, + "quiRepondCommunication3": { + "description": "XXX: ", + "type": "string" + }, + "relanceQuiSollicite": { + "description": "XXX: ", + "type": "string" + }, + "communications": { + "description": "Configuration des communications du lot", + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "description": "Identifiant technique de la communication", + "type": "string", + "format": "uuid" + }, + "label": { + "description": "Label pour la communication", + "type": "string" + }, + "echeance": { + "description": "Horodatage de l'échéance d'envoi de la communication", + "type": "string", + "format": "date-time" + }, + "moyenCommunication": { + "description": "Moyen de communication à utiliser", + "type": "string", + "enum": [ + "courrier", + "mail" + ] + }, + "typeCommunication": { + "description": "Type de communication. XXX: ya il autre chose qu'ouverture et relance???", + "type": "string", + "enum": [ + "ouverture", + "relance" + ] + }, + "modeleCommunication": { + "description": "XXX:", + "type": "string" + }, + "questionnairePapier": { + "description": "XXX:", + "type": "boolean" + }, + "objetMail": { + "description": "XXX: Pour une communication par mail : Objet du mail", + "type": "string" + }, + "dateEdition": { + "description": "XXX:", + "type": "string" + }, + "moisEditionOuverture": { + "description": "XXX:", + "type": "string" + }, + "moisEditionOuvertureTelephone": { + "description": "XXX:", + "type": "string" + }, + "relanceLibreParagraphe1": { + "description": "XXX:", + "type": "string" + }, + "relanceLibreParagraphe2": { + "description": "XXX:", + "type": "string" + }, + "relanceLibreParagraphe3": { + "description": "XXX:", + "type": "string" + }, + "relanceLibreParagraphe4": { + "description": "XXX:", + "type": "string" + }, + "complementConnexion": { + "description": "XXX:", + "type": "string" + }, + "typeQuestionnaire": { + "description": "XXX: Chaine affichée sur les courriers", + "type": "string" + }, + "idOperationEditique": { + "description": "XXX: (ca semble important ce truc)", + "type": "string" + }, + "partieNomFichierLibreZip": { + "description": "XXX:", + "type": "string" + }, + "bat": { + "description": "XXX:", + "type": "boolean" + }, + "rnvp": { + "description": "XXX: Restructuration, normalisation et validation postale", + "type": "boolean" + }, + "accuseReception": { + "description": "Indique si l'envoi se fait avec accusé de réception", + "type": "boolean" + }, + "introMail": { + "description": "XXX:", + "type": "string" + } + }, + "required": [ + "id", + "moyenCommunication", + "typeCommunication" + ] + } + } + }, + "required": [ + "id", + "typeEchantillon", + "modesCollecte" + ] + } + }, + "questionnairesModeles": { + "description": "Tous les modèles de questionnaires dont les id sont référencés dans les lots de ce contexte sont décrits ici", + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "description": "Identifiant du modèle de questionnaire", + "type": "string" + }, + "modeCollecte": { + "description": "Mode de collecte de l'échantillon CAPI=XXX...", + "$ref": "#/$defs/modesDeCollecte" + }, + "url": { + "description": "URL permettant d'accéder au modèle de questionnaire", + "type": "string" + }, + "label": { + "description": "Un label pour le modèle", + "type": "string" + }, + "nomenclatureReferencees": { + "description": "Liste des identifiants des nomenclatures référencées par le modèle de questionnaire", + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "required": [ + "id", + "modeCollecte", + "url", + "nomenclaturesReferencees" + ] + }, + "nomenclatures": { + "description": "Toutes les nommenclatures référencées par au moins un modèle de questionnaire sont décrites ici", + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "description": "Identifiant de la nomenclature", + "type": "string" + }, + "url": { + "description": "URL permettant d'accéder à la nommenclature", + "type": "string" + }, + "label": { + "description": "Un label pour la nomenclature", + "type": "string" + } + }, + "required": [ + "id", + "url" + ] + } + } + }, + "required": [ + "id", + "labelCourt", + "metadonnees", + "lots" + ], + "$defs": { + "annee4digit": { + "type": "integer", + "minimum": 1000, + "maximum": 9999 + }, + "modesDeCollecte": { + "type": "string", + "enum": [ + "CATI", + "CAPI", + "CAWI", + "PAPI" + ] + }, + "periode": { + "description": "Période de l'enquête. A00: annuelle; X00-X99: pluriannuelle; S01-02: 1er et 2nd semestre; T1-4: 1er-4e trimestre; M01-M12: Mois de l'année; B01-B06: Bimestre dans l'année ", + "type": "string", + "enum": [ + "A00", + "X00", + "X01", + "X02", + "X03", + "X04", + "X05", + "X06", + "X07", + "X08", + "X09", + "X10", + "X11", + "X12", + "X13", + "X14", + "X15", + "X16", + "X17", + "X18", + "X19", + "X20", + "X21", + "X22", + "X23", + "X24", + "X25", + "X26", + "X27", + "X28", + "X29", + "X30", + "X31", + "X32", + "X33", + "X34", + "X35", + "X36", + "X37", + "X38", + "X39", + "X40", + "X41", + "X42", + "X43", + "X44", + "X45", + "X46", + "X47", + "X48", + "X49", + "X50", + "X51", + "X52", + "X53", + "X54", + "X55", + "X56", + "X57", + "X58", + "X59", + "X60", + "X61", + "X62", + "X63", + "X64", + "X65", + "X66", + "X67", + "X68", + "X69", + "X70", + "X71", + "X72", + "X73", + "X74", + "X75", + "X76", + "X77", + "X78", + "X79", + "X80", + "X81", + "X82", + "X83", + "X84", + "X85", + "X86", + "X87", + "X88", + "X89", + "X90", + "X91", + "X92", + "X93", + "X94", + "X95", + "X96", + "X97", + "X98", + "X99", + "S01", + "S02", + "T01", + "T02", + "T03", + "T04", + "M01", + "M02", + "M03", + "M04", + "M05", + "M06", + "M07", + "M08", + "M09", + "M10", + "M11", + "M12", + "B01", + "B02", + "B03", + "B04", + "B05", + "B06" + ] + } + } +} diff --git a/src/test/httpRequests/2_Start_process_context_using_protools_endpoint.http b/src/test/httpRequests/2_Start_process_context_using_protools_endpoint.http index bd1e2743..26f4c034 100644 --- a/src/test/httpRequests/2_Start_process_context_using_protools_endpoint.http +++ b/src/test/httpRequests/2_Start_process_context_using_protools_endpoint.http @@ -1,7 +1,7 @@ ### GET TOKEN --- SET HOST < {% client.global.set("host", "https://api-orchestration-protocole-enquete.developpement.insee.fr/"); - client.global.set("host", "http://localhost:8080/"); + // client.global.set("host", "http://localhost:8080/"); %} POST https://auth.insee.test/auth/realms/{{realm}}/protocol/openid-connect/token Content-Type: application/x-www-form-urlencoded diff --git a/src/test/httpRequests/bpmnAndContext/creation_context_and_su_platine/noCTX_getREMAvecSousProcess.bpmn20.xml b/src/test/httpRequests/bpmnAndContext/creation_context_and_su_platine/noCTX_getREMAvecSousProcess.bpmn20.xml index e77accb4..aa58cac4 100644 --- a/src/test/httpRequests/bpmnAndContext/creation_context_and_su_platine/noCTX_getREMAvecSousProcess.bpmn20.xml +++ b/src/test/httpRequests/bpmnAndContext/creation_context_and_su_platine/noCTX_getREMAvecSousProcess.bpmn20.xml @@ -18,8 +18,8 @@ - contexte_partition_id_list - + contexte_lot_id_list + diff --git a/src/test/java/fr/insee/protools/backend/ProtoolsTestUtils.java b/src/test/java/fr/insee/protools/backend/ProtoolsTestUtils.java index 86f22462..0e7270a5 100644 --- a/src/test/java/fr/insee/protools/backend/ProtoolsTestUtils.java +++ b/src/test/java/fr/insee/protools/backend/ProtoolsTestUtils.java @@ -1,10 +1,8 @@ package fr.insee.protools.backend; -import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; -import fr.insee.protools.backend.service.context.ContextService; import okio.Buffer; import okio.Okio; import org.apache.commons.io.IOUtils; @@ -16,8 +14,6 @@ import java.io.UncheckedIOException; import static java.nio.charset.StandardCharsets.UTF_8; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.when; /** * Utilitary class to load ressource files in String, POJO (using jackson) or JsonNode @@ -76,10 +72,4 @@ public static Buffer fileToBytes(File file) throws IOException { return result; } - - public static JsonNode initContexteMockFromString(ContextService protoolsContext, String contextAsString) throws JsonProcessingException { - JsonNode contextRootNode = new ObjectMapper().readTree(contextAsString); - when(protoolsContext.getContextByProcessInstance(anyString())).thenReturn(contextRootNode); - return contextRootNode; - } } diff --git a/src/test/java/fr/insee/protools/backend/controller/StarterControllerTest.java b/src/test/java/fr/insee/protools/backend/controller/StarterControllerTest.java index f6092ddf..1ab48345 100644 --- a/src/test/java/fr/insee/protools/backend/controller/StarterControllerTest.java +++ b/src/test/java/fr/insee/protools/backend/controller/StarterControllerTest.java @@ -1,10 +1,16 @@ package fr.insee.protools.backend.controller; -import fr.insee.protools.backend.webclient.WebClientHelper; +import com.fasterxml.jackson.databind.ObjectMapper; +import fr.insee.protools.backend.restclient.RestClientHelper; +import fr.insee.protools.backend.restclient.configuration.APIProperties; +import fr.insee.protools.backend.restclient.configuration.ApiConfigProperties; +import fr.insee.protools.backend.restclient.keycloak.KeycloakService; +import fr.insee.protools.backend.service.utils.CustomJWTHelper; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.boot.test.mock.mockito.SpyBean; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.oauth2.core.oidc.StandardClaimNames; import org.springframework.security.oauth2.jwt.JwtDecoder; @@ -13,23 +19,38 @@ import java.util.List; import static org.hamcrest.Matchers.containsString; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.eq; import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.jwt; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + @WebMvcTest(value = StarterController.class) -//@ActiveProfiles(value = "test") class StarterControllerTest { - @MockBean WebClientHelper webClientHelper; + + private static final ObjectMapper objectMapper = new ObjectMapper(); + + + @MockBean + ApiConfigProperties apiConfigProperties; + + @SpyBean + KeycloakService kcService; + @MockBean JwtDecoder jwtDecoder; + @SpyBean + RestClientHelper restClientHelper; @Autowired private MockMvc mockMvc; + @Test - void shouldReturnDefaultMessage() throws Exception { + void gethealthchek_should_returnDefaultMessage() throws Exception { this.mockMvc.perform(get("/starter/healthcheck").with(jwt())) .andDo(print()).andExpect(status().isOk()) .andExpect(content().string(containsString("OK"))); @@ -46,4 +67,26 @@ void shouldReturnDefaultMessage() throws Exception { } + + @Test + void getTokenDetails_should_returnCorrectly() throws Exception { + + //Prepare : Only Platine pilotage is disable ; All other are confired and returns the same token + APIProperties.AuthProperties kcAuth = new APIProperties.AuthProperties("https://test.test","realm", "client","xxx"); + APIProperties apiPropertiesAll = new APIProperties("url-all",kcAuth ,true); + APIProperties apiPropertiesPlatinePil = new APIProperties("url-platine",kcAuth ,false); + + doReturn(apiPropertiesAll).when(apiConfigProperties).getAPIProperties(any()); + doReturn(apiPropertiesPlatinePil).when(apiConfigProperties).getAPIProperties(eq(ApiConfigProperties.KNOWN_API.KNOWN_API_PLATINE_PILOTAGE)); + //Token returned by getToken + doReturn(CustomJWTHelper.getEncodedToken(List.of("ROLE_administrateur_Platine","ROLE_Administrateurs_BEATLES"))).when(kcService).getToken(eq(kcAuth)); + + this.mockMvc.perform( + get("/starter/token_details_by_api").with(jwt())) + .andDo(print()).andExpect(status().isOk()) + .andExpect(content().string(containsString("List of tokens roles "))) + .andExpect(content().string(containsString("KNOWN_API_PLATINE_PILOTAGE : API KNOWN_API_PLATINE_PILOTAGE is disabled in properties"))) + .andExpect(content().string(containsString("KNOWN_API_SABIANE_QUESTIONNAIRE : [\"ROLE_administrateur_Platine\",\"ROLE_Administrateurs_BEATLES\"]"))) + .andExpect(content().string(containsString("KNOWN_API_SABIANE_PILOTAGE : [\"ROLE_administrateur_Platine\",\"ROLE_Administrateurs_BEATLES\"]"))); + } } diff --git a/src/test/java/fr/insee/protools/backend/flowable/engine/SimpleProcessTest.java b/src/test/java/fr/insee/protools/backend/flowable/engine/SimpleProcessTest.java deleted file mode 100644 index fd93fa40..00000000 --- a/src/test/java/fr/insee/protools/backend/flowable/engine/SimpleProcessTest.java +++ /dev/null @@ -1,41 +0,0 @@ -package fr.insee.protools.backend.flowable.engine; - - -import org.flowable.engine.ProcessEngine; -import org.flowable.engine.RuntimeService; -import org.flowable.engine.TaskService; -import org.flowable.engine.test.Deployment; -import org.flowable.engine.test.FlowableTest; -import org.flowable.task.api.Task; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; - -@FlowableTest -class SimpleProcessTest { - - private ProcessEngine processEngine; - private RuntimeService runtimeService; - private TaskService taskService; - - @BeforeEach - void setUp(ProcessEngine processEngine) { - this.processEngine = processEngine; - this.runtimeService = processEngine.getRuntimeService(); - this.taskService = processEngine.getTaskService(); - } - - @Test - @Deployment - void testSimpleProcess() { - runtimeService.startProcessInstanceByKey("simpleProcess"); - - Task task = taskService.createTaskQuery().singleResult(); - assertThat(task.getName()).isEqualTo("My Task"); - - taskService.complete(task.getId()); - assertThat(runtimeService.createProcessInstanceQuery().count()).isZero(); - - } -} \ No newline at end of file diff --git a/src/test/java/fr/insee/protools/backend/integration/EraREMProcessTest.java b/src/test/java/fr/insee/protools/backend/integration/EraREMProcessTest.java deleted file mode 100644 index 76989a46..00000000 --- a/src/test/java/fr/insee/protools/backend/integration/EraREMProcessTest.java +++ /dev/null @@ -1,124 +0,0 @@ -package fr.insee.protools.backend.integration; - - -import fr.insee.protools.backend.service.context.ContextServiceImpl; -import fr.insee.protools.backend.service.era.EraService; -import fr.insee.protools.backend.dto.era.CensusJsonDto; -import fr.insee.protools.backend.dto.era.GenderType; -import fr.insee.protools.backend.service.rem.RemService; -import fr.insee.protools.backend.dto.rem.REMSurveyUnitDto; -import fr.insee.protools.backend.dto.rem.SuIdMappingJson; -import fr.insee.protools.backend.dto.rem.SuIdMappingRecord; -import org.flowable.engine.test.Deployment; -import org.flowable.engine.test.FlowableTest; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mockito; -import org.mockito.junit.jupiter.MockitoExtension; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.mock.web.MockMultipartFile; -import org.springframework.test.context.TestPropertySource; -import org.springframework.util.ClassUtils; - -import java.io.IOException; -import java.io.InputStream; -import java.io.UncheckedIOException; -import java.time.LocalDate; -import java.util.List; -import java.util.concurrent.atomic.AtomicLong; - -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; - -@FlowableTest -@SpringBootTest -@TestPropertySource(locations = "/application-test.properties") -@ExtendWith(MockitoExtension.class) -class EraREMProcessTest { - - @Autowired ContextServiceImpl contextService; - @MockBean EraService eraService; - @MockBean RemService remService; - - final static String ressourceFolder = ClassUtils.convertClassNameToResourcePath(EraREMProcessTest.class.getPackageName()); - final static String ctx_json = ressourceFolder + "/collecte_web_no_com.json"; - - static AtomicLong i=new AtomicLong(0l); - - @Test - @Deployment(resources = { "fr/insee/protools/backend/integration/noCTX_eraREM.bpmn20.xml" }) - void testBPMN_ERA_REM() { - - //ERA SU for 2 Partitions (2 SU for each partition) - //42 : Men - //43 : Females - Long partition1=42l,partition2=43l; - CensusJsonDto eraP1SU1=createCensusJsonDto(1l,partition1); - CensusJsonDto eraP1SU2=createCensusJsonDto(2l,partition1); - CensusJsonDto eraP2SU1=createCensusJsonDto(3l,partition2); - CensusJsonDto eraP2SU2=createCensusJsonDto(4l,partition2); - - List listOfEraSU_P1 = List.of(eraP1SU1,eraP1SU2); - List listOfEraSU_P2 = List.of(eraP2SU1,eraP2SU2); - SuIdMappingJson mapping_P1 = createSuIdMappingJson(partition1,listOfEraSU_P1); - SuIdMappingJson mapping_P2 = createSuIdMappingJson(partition2,listOfEraSU_P2); - LocalDate startDate = LocalDate.now().minusDays(1); - LocalDate endDate = LocalDate.now(); - - Mockito.when(eraService.getSUForPeriodAndSex(startDate,endDate, GenderType.MALE)).thenReturn(listOfEraSU_P1); - Mockito.when(eraService.getSUForPeriodAndSex(startDate,endDate,GenderType.FEMALE)).thenReturn(listOfEraSU_P2); - - Mockito.when(remService.writeERASUList(partition1,listOfEraSU_P1)) - .thenReturn(mapping_P1); - Mockito.when(remService.writeERASUList(partition2,listOfEraSU_P2)) - .thenReturn(mapping_P2); - - REMSurveyUnitDto rem_P1SU1 = createRemSUFromMapping(mapping_P1.getData().get(0)); - REMSurveyUnitDto rem_P1SU2 = createRemSUFromMapping(mapping_P1.getData().get(1)); - REMSurveyUnitDto rem_P2SU1 = createRemSUFromMapping(mapping_P2.getData().get(0)); - REMSurveyUnitDto rem_P2SU2 = createRemSUFromMapping(mapping_P2.getData().get(1)); - - - Mockito.when(remService.getSurveyUnit(mapping_P1.getData().get(0).repositoryId())) - .thenReturn(rem_P1SU1); - Mockito.when(remService.getSurveyUnit(mapping_P1.getData().get(1).repositoryId())) - .thenReturn(rem_P1SU2); - Mockito.when(remService.getSurveyUnit(mapping_P2.getData().get(0).repositoryId())) - .thenReturn(rem_P2SU1); - Mockito.when(remService.getSurveyUnit(mapping_P2.getData().get(1).repositoryId())) - .thenReturn(rem_P2SU2); - - try (InputStream is = EraREMProcessTest.class.getClassLoader().getResourceAsStream(ctx_json)){ - MockMultipartFile multipartFile = new MockMultipartFile("file.json", "file.json", "text/json", is.readAllBytes()); - String processID = contextService.processContextFileAndCreateProcessInstance(multipartFile,"eraREM","toto"); - assertThat(processID).isNotBlank(); - - } catch (IOException e) { - throw new UncheckedIOException(e); - } - } - - private static CensusJsonDto createCensusJsonDto(Long eraId, Long partitionID){ - return CensusJsonDto.builder() - .id(eraId) - .identifiantCompte("SU1_PART_"+partitionID) - .build(); - } - private static SuIdMappingJson createSuIdMappingJson(Long partitionId,List eraSUList){ - List mappingEraREM = eraSUList.stream().map(censusJsonDto -> new SuIdMappingRecord(i.incrementAndGet(),String.valueOf(censusJsonDto.getId()))).toList(); - return SuIdMappingJson.builder() - .count(mappingEraREM.size()) - .partitionId(partitionId) - .data(mappingEraREM) - .build(); - } - - private static REMSurveyUnitDto createRemSUFromMapping(SuIdMappingRecord mapping){ - return REMSurveyUnitDto.builder() - .repositoryId(mapping.repositoryId()) - .externalId(mapping.externalId()) - .build(); - - } -} \ No newline at end of file diff --git a/src/test/java/fr/insee/protools/backend/integration/GetREMProcessTest.java b/src/test/java/fr/insee/protools/backend/integration/GetREMProcessTest.java new file mode 100644 index 00000000..103be1f1 --- /dev/null +++ b/src/test/java/fr/insee/protools/backend/integration/GetREMProcessTest.java @@ -0,0 +1,113 @@ +package fr.insee.protools.backend.integration; + +import com.fasterxml.jackson.databind.JsonNode; +import fr.insee.protools.backend.integration.delegate_and_services_stub.RemServiceStub; +import org.flowable.bpmn.model.*; +import org.flowable.engine.impl.persistence.entity.ExecutionEntityImpl; +import org.flowable.engine.impl.test.AbstractFlowableTestCase; +import org.flowable.engine.repository.Deployment; +import org.flowable.engine.repository.DeploymentBuilder; +import org.flowable.engine.repository.ProcessDefinition; +import org.flowable.spring.impl.test.FlowableSpringExtension; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static fr.insee.protools.backend.service.FlowableVariableNameConstants.*; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; + + +@ContextConfiguration(value = { + "classpath:fr/insee/protools/backend/integration/springTypicalUsageTest-context.xml", + "classpath:fr/insee/protools/backend/integration/springGetREMDelegate-context.xml" +}) +@TestPropertySource(locations = "/application-test.properties") +//@ExtendWith(PluggableFlowableExtension.class) +@ExtendWith(FlowableSpringExtension.class) +@ExtendWith(MockitoExtension.class) +class GetREMProcessTest extends AbstractFlowableTestCase { + + static final String END_EVENT_ID ="endTask"; + + private List autoCleanedUpDeploymentIds = new ArrayList<>(); + + @BeforeEach + protected void setUp() throws Exception { + this.autoCleanedUpDeploymentIds.clear(); + } + + @Test + void test() { + String delegateExpression = "${remGetPartitionListOfInterroPaginatedTask}"; + String taskId = "testedServiceTask"; + String processDefinitionId=deployBPMN("testProcess.bpmn20.xml", + createOneServiceTaskProcess(delegateExpression, taskId)); + + Map variables = new HashMap<>(); + variables.put(VARNAME_CURRENT_PARTITION_ID, "1"); + //Start the process + ExecutionEntityImpl processInstance = (ExecutionEntityImpl) runtimeService.startProcessInstanceById(processDefinitionId,variables); + + //Verify + assertThat(runtimeService.createProcessInstanceQuery().count()).isZero(); + String currentActivityId = ((ExecutionEntityImpl) processInstance).getExecutions().get(0).getCurrentActivityId(); + assertEquals(END_EVENT_ID, currentActivityId,"We expected the process to be on its end event"); + + List interroList=processInstance.getVariable(VARNAME_REM_INTERRO_LIST,List.class); + Integer currentPage=processInstance.getVariable(VARNAME_INTERRO_LIST_PAGEABLE_CURRENT_PAGE,Integer.class); + Boolean isLastPage=processInstance.getVariable(VARNAME_INTERRO_LIST_PAGEABLE_IS_LAST_PAGE,Boolean.class); + assertEquals(RemServiceStub.defaultCurrentPage,currentPage); + assertEquals(RemServiceStub.isLastPage,isLastPage); + assertEquals(RemServiceStub.defaultInterroList,interroList); + + } + + private BpmnModel createOneServiceTaskProcess(String delegateExpression, String taskId) { + BpmnModel model = new BpmnModel(); + org.flowable.bpmn.model.Process process = new org.flowable.bpmn.model.Process(); + model.addProcess(process); + + process.setId("oneTaskProcess"); + process.setName("The one task process"); + + StartEvent startEvent = new StartEvent(); + startEvent.setId("start"); + process.addFlowElement(startEvent); + + ServiceTask serviceTask = new ServiceTask(); + serviceTask.setName("The org.flowable.task.service.Task"); + serviceTask.setId(taskId); + serviceTask.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION); + serviceTask.setImplementation(delegateExpression); + process.addFlowElement(serviceTask); + + EndEvent endEvent = new EndEvent(); + endEvent.setId(END_EVENT_ID); + process.addFlowElement(endEvent); + + process.addFlowElement(new SequenceFlow("start", taskId)); + process.addFlowElement(new SequenceFlow(taskId, END_EVENT_ID)); + + return model; + } + + + private String deployBPMN(String ressourceName,BpmnModel model){ + + DeploymentBuilder deploymentBuilder = repositoryService.createDeployment(); + deploymentBuilder.addBpmnModel(ressourceName,model); + Deployment deployment = deploymentBuilder.deploy(); + ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery() + .deploymentId(deployment.getId()).singleResult(); + return processDefinition.getId(); + } +} diff --git a/src/test/java/fr/insee/protools/backend/integration/SimpleProcessTest.java b/src/test/java/fr/insee/protools/backend/integration/SimpleProcessTest.java new file mode 100644 index 00000000..9a73698a --- /dev/null +++ b/src/test/java/fr/insee/protools/backend/integration/SimpleProcessTest.java @@ -0,0 +1,62 @@ +package fr.insee.protools.backend.integration; + + +import org.flowable.engine.ProcessEngine; +import org.flowable.engine.RuntimeService; +import org.flowable.engine.TaskService; +import org.flowable.engine.test.Deployment; +import org.flowable.spring.impl.test.FlowableSpringExtension; +import org.flowable.task.api.Task; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; + +import static org.assertj.core.api.Assertions.assertThat; + + +@ContextConfiguration(value = { + "classpath:fr/insee/protools/backend/integration/springTypicalUsageTest-context.xml", + "classpath:fr/insee/protools/backend/integration/springTestDelegate-context.xml" +}) +@TestPropertySource(locations = "/application-test.properties") +@ExtendWith(FlowableSpringExtension.class) +class SimpleProcessTest { + + //private ProcessEngine processEngine; + private RuntimeService runtimeService; + private TaskService taskService; + + @BeforeEach + void setUp(ProcessEngine processEngine) { + //this.processEngine = processEngine; + this.runtimeService = processEngine.getRuntimeService(); + this.taskService = processEngine.getTaskService(); + } + + @Test + @Deployment + void testSimpleProcess() { + runtimeService.startProcessInstanceByKey("simpleProcess"); + + Task task = taskService.createTaskQuery().singleResult(); + assertThat(task.getName()).isEqualTo("My User Task"); + + taskService.complete(task.getId()); + assertThat(runtimeService.createProcessInstanceQuery().count()).isZero(); + } + + @Test + @Deployment + void testDelegateProcess() { + runtimeService.startProcessInstanceByKey("delegateProcess"); + + Task task = taskService.createTaskQuery().singleResult(); + assertThat(task.getName()).isEqualTo("My User Task"); + + taskService.complete(task.getId()); + assertThat(runtimeService.createProcessInstanceQuery().count()).isZero(); + + } +} diff --git a/src/test/java/fr/insee/protools/backend/integration/delegate_and_services_stub/RemServiceStub.java b/src/test/java/fr/insee/protools/backend/integration/delegate_and_services_stub/RemServiceStub.java new file mode 100644 index 00000000..cc01e47a --- /dev/null +++ b/src/test/java/fr/insee/protools/backend/integration/delegate_and_services_stub/RemServiceStub.java @@ -0,0 +1,46 @@ +package fr.insee.protools.backend.integration.delegate_and_services_stub; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import fr.insee.protools.backend.restclient.pagination.PageResponse; +import fr.insee.protools.backend.service.rem.IRemService; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Map; + +@Service +public class RemServiceStub implements IRemService { + + private final static ObjectMapper objectMapper=new ObjectMapper(); + + public final static List defaultInterroList = List.of(objectMapper.createObjectNode().put("xx","yyy")); + public final static Integer defaultCurrentPage=0; + public final static Integer defaultPageCount=1; + public final static Boolean isLastPage=Boolean.TRUE; + + @Override + public PageResponse getPartitionAllInterroPaginated(String partitionId, long page) { + return PageResponse.builder().currentPage(defaultCurrentPage).pageCount(defaultPageCount).content(defaultInterroList).build(); + } + + @Override + public List getInterrogationIdsWithoutAccountForPartition(String partitionId) { + return null; + } + + @Override + public void patchInterrogationsSetAccounts(Map userByInterroId) { + return ; + } + + @Override + public void putContactsPlatine(List contactPlatineList) { + return ; + } + + @Override + public void postRemiseEnCollecte(List interroRemiseEnCollecteList) { + return ; + } +} diff --git a/src/test/java/fr/insee/protools/backend/integration/delegate_and_services_stub/TestDelegate.java b/src/test/java/fr/insee/protools/backend/integration/delegate_and_services_stub/TestDelegate.java new file mode 100644 index 00000000..03556bce --- /dev/null +++ b/src/test/java/fr/insee/protools/backend/integration/delegate_and_services_stub/TestDelegate.java @@ -0,0 +1,11 @@ +package fr.insee.protools.backend.integration.delegate_and_services_stub; + +import org.flowable.engine.delegate.DelegateExecution; +import org.flowable.engine.delegate.JavaDelegate; + +public class TestDelegate implements JavaDelegate { + @Override + public void execute(DelegateExecution execution) { + + } +} diff --git a/src/test/java/fr/insee/protools/backend/webclient/KeycloakServiceTest.java b/src/test/java/fr/insee/protools/backend/restclient/KeycloakServiceTest.java similarity index 93% rename from src/test/java/fr/insee/protools/backend/webclient/KeycloakServiceTest.java rename to src/test/java/fr/insee/protools/backend/restclient/KeycloakServiceTest.java index b05f9722..c6f545c4 100644 --- a/src/test/java/fr/insee/protools/backend/webclient/KeycloakServiceTest.java +++ b/src/test/java/fr/insee/protools/backend/restclient/KeycloakServiceTest.java @@ -1,8 +1,10 @@ -package fr.insee.protools.backend.webclient; +package fr.insee.protools.backend.restclient; import com.fasterxml.jackson.databind.ObjectMapper; -import fr.insee.protools.backend.webclient.configuration.APIProperties; -import fr.insee.protools.backend.webclient.exception.KeycloakTokenConfigBPMNError; +import fr.insee.protools.backend.restclient.configuration.APIProperties; +import fr.insee.protools.backend.restclient.exception.KeycloakTokenConfigBPMNError; +import fr.insee.protools.backend.restclient.keycloak.KeycloakResponse; +import fr.insee.protools.backend.restclient.keycloak.KeycloakService; import okhttp3.mockwebserver.MockResponse; import okhttp3.mockwebserver.MockWebServer; import org.junit.jupiter.api.AfterEach; @@ -100,24 +102,19 @@ void getToken_should_throw_when_authIncorrect(){ assertThrows(KeycloakTokenConfigBPMNError.class , () -> keycloakService.getToken(kcAuthBlankSecret)); } - @Test @DisplayName("getToken should check if a token already exists for this AuthProperties and reuse the known token if it is not exipred") void getToken_should_refreshTokenWhenNeeded() throws IOException, KeycloakTokenConfigBPMNError, InterruptedException { APIProperties.AuthProperties kcAuth = new APIProperties.AuthProperties(getDummyUriWithPort(),"realm", "toto","toto"); //Prepare 2 KC responses - KeycloakResponse kcResponse1 = new KeycloakResponse(); - kcResponse1.setAccesToken("MYTOKEN-NB1"); - kcResponse1.setExpiresIn(300); // 5 minutes + KeycloakResponse kcResponse1 = new KeycloakResponse("MYTOKEN-NB1",300 /*5 minutes*/); MockResponse mockResponseKC1 = new MockResponse() .addHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON) .setResponseCode(HttpStatus.OK.value()) .setBody(new ObjectMapper().writeValueAsString(kcResponse1)); - KeycloakResponse kcResponse2 = new KeycloakResponse(); - kcResponse2.setAccesToken("MYTOKEN-NB2"); - kcResponse2.setExpiresIn(300); + KeycloakResponse kcResponse2 = new KeycloakResponse("MYTOKEN-NB2",300 /*5 minutes*/); MockResponse mockResponseKC2 = new MockResponse() .addHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON) .setResponseCode(HttpStatus.OK.value()) diff --git a/src/test/java/fr/insee/protools/backend/restclient/RestClientHelperTest.java b/src/test/java/fr/insee/protools/backend/restclient/RestClientHelperTest.java new file mode 100644 index 00000000..d143b668 --- /dev/null +++ b/src/test/java/fr/insee/protools/backend/restclient/RestClientHelperTest.java @@ -0,0 +1,461 @@ +package fr.insee.protools.backend.restclient; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.JsonNodeType; +import fr.insee.protools.backend.restclient.configuration.APIProperties; +import fr.insee.protools.backend.restclient.configuration.ApiConfigProperties; +import fr.insee.protools.backend.restclient.exception.ApiNotConfiguredBPMNError; +import fr.insee.protools.backend.restclient.exception.KeycloakTokenConfigUncheckedBPMNError; +import fr.insee.protools.backend.restclient.exception.runtime.HttpClient4xxBPMNError; +import fr.insee.protools.backend.restclient.keycloak.KeycloakResponse; +import fr.insee.protools.backend.restclient.keycloak.KeycloakService; +import fr.insee.protools.backend.service.utils.CustomJWTHelper; +import okhttp3.mockwebserver.MockResponse; +import okhttp3.mockwebserver.MockWebServer; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.Spy; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.core.env.Environment; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.web.client.RestClient; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Base64; +import java.util.List; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.*; + + +@ExtendWith(MockitoExtension.class) +class RestClientHelperTest { + + @Spy + private Environment environment; + + private KeycloakService keycloakService; + + @Mock + private ApiConfigProperties apiConfigProperties; + + private RestClientHelper restClientHelper; + + + private MockWebServer mockWebServer; + private static final int port = 80; + private static String getDummyUriWithPort() { return getServerHostPort()+"/api/test"; } + private static String getServerHostPort() { return "http://localhost:"+port; } + + @BeforeEach + public void prepare() { + keycloakService= spy(new KeycloakService(environment)); + restClientHelper = new RestClientHelper(keycloakService,apiConfigProperties); + this.keycloakService.initialize(); + } + + //close the mocked web server if it has been initialized + @AfterEach + void mockServerCleanup() throws Exception { + if(this.mockWebServer!=null){ + this.mockWebServer.close(); + } + } + + private void initMockWebServer() throws IOException { + this.mockWebServer = new MockWebServer(); + mockWebServer.start(port); + } + + @Test + @DisplayName("Test getRestClient method without specifying an API") + void testgetRestClientWithoutApi() { + RestClient client = restClientHelper.getRestClient(); + assertThat(client).isNotNull(); + } + + private void testgetRestClientWithIncompleteKCConfig(APIProperties.AuthProperties kcAuth){ + when(apiConfigProperties.getAPIProperties(any())).thenReturn(new APIProperties(getServerHostPort(), kcAuth, true)); + var client = restClientHelper.getRestClient(ApiConfigProperties.KNOWN_API.KNOWN_API_ERA); + assertThat(client).isNotNull(); + //Should throw an exception as the realm is missing + assertThrows(KeycloakTokenConfigUncheckedBPMNError.class , () -> client.get().uri(getDummyUriWithPort()).retrieve()); + } + @Test + @DisplayName("Test getRestClient method without incomplete keycloak configuration") + void getRestClientWithIncompleteKCConfig() throws IOException { + //Missing realm + APIProperties.AuthProperties kcAuth = new APIProperties.AuthProperties(getDummyUriWithPort(),null, "toto","toto"); + //Should throw an exception as the realm is missing + testgetRestClientWithIncompleteKCConfig(kcAuth); + + //Missing url + kcAuth = new APIProperties.AuthProperties("null","realm", "toto","toto"); + testgetRestClientWithIncompleteKCConfig(kcAuth); + + //Missing clientId + kcAuth = new APIProperties.AuthProperties(getDummyUriWithPort(),"realm", null,"toto"); + testgetRestClientWithIncompleteKCConfig(kcAuth); + + //Missing secret + kcAuth = new APIProperties.AuthProperties(getDummyUriWithPort(),"realm", "toto",null); + testgetRestClientWithIncompleteKCConfig(kcAuth); + } + + @Test + void getRestClient_should_work_when_OK() throws IOException { + + APIProperties.AuthProperties kcAuth = new APIProperties.AuthProperties(); + kcAuth.setClientId("clientId-toto"); + kcAuth.setClientSecret("client-pwd-toto"); + kcAuth.setRealm("realm-toto"); + kcAuth.setUrl(getDummyUriWithPort()); + + + when(apiConfigProperties.getAPIProperties(any())).thenReturn(new APIProperties(getServerHostPort(), kcAuth, true)); + RestClient client = restClientHelper.getRestClient(ApiConfigProperties.KNOWN_API.KNOWN_API_ERA); + assertThat(client).isNotNull(); + + KeycloakResponse kcResponse = new KeycloakResponse("MYTOKEN",5*60*1000); + MockResponse mockResponseKC = new MockResponse() + .addHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON) + .setResponseCode(HttpStatus.OK.value()) + .setBody(new ObjectMapper().writeValueAsString(kcResponse)); + + MockResponse mockResponse = new MockResponse() + .setResponseCode(HttpStatus.NO_CONTENT.value()) + .setBody("XXX"); + + initMockWebServer(); + mockWebServer.enqueue(mockResponseKC); + mockWebServer.enqueue(mockResponse); + + assertThat(client.get().uri(getDummyUriWithPort()).retrieve().toBodilessEntity().getStatusCode()).isEqualTo(HttpStatus.NO_CONTENT); + } + + @Test + void getRestClient_withInvalidApiConfig() { + when(apiConfigProperties.getAPIProperties(any())).thenReturn(null); + assertThatThrownBy(() -> restClientHelper.getRestClient(any())) + .isInstanceOf(ApiNotConfiguredBPMNError.class) + .hasMessageContaining("is not configured in properties"); + } + + @Test + void getRestClient_withDisabledApiConfig() { + when(apiConfigProperties.getAPIProperties(any())).thenReturn(new APIProperties("http://localhost:8080", new APIProperties.AuthProperties(), false )); + assertThatThrownBy(() -> restClientHelper.getRestClient(any())) + .isInstanceOf(ApiNotConfiguredBPMNError.class) + .hasMessageContaining("is disabled in properties"); + } + + @Test + void getTokenDetailsByAPI_should_workForOkNullAndNotConfiguredApi() throws Exception { + //Prepare : + // Platine pilotage is disabled + // Meshuggah is null + // All other are confired and returns the same token + APIProperties.AuthProperties kcAuth = new APIProperties.AuthProperties("https://test.test","realm", "client","xxx"); + APIProperties apiPropertiesAll = new APIProperties("url-all",kcAuth ,true); + APIProperties apiPropertiesPlatinePil = new APIProperties("url-platine",kcAuth ,false); + + doReturn(apiPropertiesAll).when(apiConfigProperties).getAPIProperties(any()); + doReturn(apiPropertiesPlatinePil).when(apiConfigProperties).getAPIProperties(eq(ApiConfigProperties.KNOWN_API.KNOWN_API_PLATINE_PILOTAGE)); + doReturn(null).when(apiConfigProperties).getAPIProperties(eq(ApiConfigProperties.KNOWN_API.KNOWN_API_MESHUGGAH)); + + doReturn(CustomJWTHelper.getEncodedToken(List.of("ROLE_TOTO","ROLE_Administrateurs_BEATLES"))).when(keycloakService).getToken(eq(kcAuth)); + + + Map details = restClientHelper.getTokenDetailsByAPI(); + + assertThat(details).containsEntry("KNOWN_API_PLATINE_PILOTAGE","API KNOWN_API_PLATINE_PILOTAGE is disabled in properties"); + assertThat(details).containsEntry("KNOWN_API_MESHUGGAH","API KNOWN_API_MESHUGGAH is not configured in properties"); + assertThat(details).containsEntry("KNOWN_API_REM","[\"ROLE_TOTO\",\"ROLE_Administrateurs_BEATLES\"]"); + + } + + @Test + void getTokenDetailsByAPI_should_workWhenNoRoleInToken() throws Exception { + //Prepare : + // Platine pilotage is disabled + // Meshuggah is null + // All other are confired and returns the same token + APIProperties.AuthProperties kcAuth = new APIProperties.AuthProperties("https://test.test","realm", "client","xxx"); + APIProperties apiPropertiesAll = new APIProperties("url-all",kcAuth ,true); + APIProperties apiPropertiesPlatinePil = new APIProperties("url-platine",kcAuth ,false); + + doReturn(apiPropertiesAll).when(apiConfigProperties).getAPIProperties(any()); + doReturn(apiPropertiesPlatinePil).when(apiConfigProperties).getAPIProperties(eq(ApiConfigProperties.KNOWN_API.KNOWN_API_PLATINE_PILOTAGE)); + doReturn(null).when(apiConfigProperties).getAPIProperties(eq(ApiConfigProperties.KNOWN_API.KNOWN_API_MESHUGGAH)); + + doReturn(CustomJWTHelper.getEncodedToken(List.of())).when(keycloakService).getToken(eq(kcAuth)); + + + Map details = restClientHelper.getTokenDetailsByAPI(); + + assertThat(details).containsEntry("KNOWN_API_PLATINE_PILOTAGE","API KNOWN_API_PLATINE_PILOTAGE is disabled in properties"); + assertThat(details).containsEntry("KNOWN_API_MESHUGGAH","API KNOWN_API_MESHUGGAH is not configured in properties"); + assertThat(details).containsEntry("KNOWN_API_REM","No Role found in token"); + + } + + + @Test + void getTokenDetailsByAPI_should_workWhenNoDot() throws Exception { + //Prepare : + // Platine pilotage is disabled + // Meshuggah is null + // All other are confired and returns the same token + APIProperties.AuthProperties kcAuth = new APIProperties.AuthProperties("https://test.test","realm", "client","xxx"); + APIProperties apiPropertiesAll = new APIProperties("url-all",kcAuth ,true); + APIProperties apiPropertiesPlatinePil = new APIProperties("url-platine",kcAuth ,false); + + doReturn(apiPropertiesAll).when(apiConfigProperties).getAPIProperties(any()); + doReturn(apiPropertiesPlatinePil).when(apiConfigProperties).getAPIProperties(eq(ApiConfigProperties.KNOWN_API.KNOWN_API_PLATINE_PILOTAGE)); + doReturn(null).when(apiConfigProperties).getAPIProperties(eq(ApiConfigProperties.KNOWN_API.KNOWN_API_MESHUGGAH)); + + doReturn("{THIS TOKEN IS INCORRECT AND THERE IS NO DOT SEPARING HEADER}}}}").when(keycloakService).getToken(eq(kcAuth)); + + + Map details = restClientHelper.getTokenDetailsByAPI(); + + assertThat(details).containsEntry("KNOWN_API_PLATINE_PILOTAGE","API KNOWN_API_PLATINE_PILOTAGE is disabled in properties"); + assertThat(details).containsEntry("KNOWN_API_MESHUGGAH","API KNOWN_API_MESHUGGAH is not configured in properties"); + assertThat(details).containsEntry("KNOWN_API_REM","Token size is incorrect. It should contain at least one dot"); + + } + + + @Test + void getTokenDetailsByAPI_should_workWhenIncorrectJsonContent() throws Exception { + //Prepare : + // Platine pilotage is disabled + // Meshuggah is null + // All other are confired and returns the same token + APIProperties.AuthProperties kcAuth = new APIProperties.AuthProperties("https://test.test","realm", "client","xxx"); + APIProperties apiPropertiesAll = new APIProperties("url-all",kcAuth ,true); + APIProperties apiPropertiesPlatinePil = new APIProperties("url-platine",kcAuth ,false); + + doReturn(apiPropertiesAll).when(apiConfigProperties).getAPIProperties(any()); + doReturn(apiPropertiesPlatinePil).when(apiConfigProperties).getAPIProperties(eq(ApiConfigProperties.KNOWN_API.KNOWN_API_PLATINE_PILOTAGE)); + doReturn(null).when(apiConfigProperties).getAPIProperties(eq(ApiConfigProperties.KNOWN_API.KNOWN_API_MESHUGGAH)); + + String header= Base64.getEncoder().encodeToString("random header".getBytes(StandardCharsets.UTF_8)); + String incorrectPayload= Base64.getEncoder().encodeToString("incorrect json".getBytes(StandardCharsets.UTF_8)); + String signature=CustomJWTHelper.createSignature(header, incorrectPayload); + String signedToken = header + "." + incorrectPayload + "." + signature; + + doReturn(signedToken).when(keycloakService).getToken(eq(kcAuth)); + + + Map details = restClientHelper.getTokenDetailsByAPI(); + + assertThat(details).containsEntry("KNOWN_API_PLATINE_PILOTAGE","API KNOWN_API_PLATINE_PILOTAGE is disabled in properties"); + assertThat(details).containsEntry("KNOWN_API_MESHUGGAH","API KNOWN_API_MESHUGGAH is not configured in properties"); + assertThat(details).containsEntry("KNOWN_API_REM","Exception during json token parsing"); + + } + + + + @Test + void getAPIConfigDetails_shouldNotThrow() { + APIProperties.AuthProperties kcAuth = new APIProperties.AuthProperties("https://test.test","realm", "client","xxx"); + APIProperties apiPropertiesAll = new APIProperties("url-all",kcAuth ,true); + doReturn(apiPropertiesAll).when(apiConfigProperties).getAPIProperties(any()); + + JsonNode result = restClientHelper.getAPIConfigDetails(); + assertEquals(JsonNodeType.ARRAY,result.getNodeType()); + ArrayNode resultArray = (ArrayNode) result; + assertEquals(ApiConfigProperties.KNOWN_API.values().length,resultArray.size()); + } + + @Test + @DisplayName("Test that the retrieval of spring private field still works") + void extractClientResponseRequestDescriptionPrivateFiledUsingReflexion_shouldWork() throws IOException { + RestClient restClient = restClientHelper.getRestClient(); + assertThat(restClient).isNotNull(); + + //Mock an error response + MockResponse mockResponse = new MockResponse() + .setResponseCode(HttpStatus.BAD_REQUEST.value()) + .setBody("XXX"); + + initMockWebServer(); + mockWebServer.enqueue(mockResponse); + + //Call method under test + HttpClient4xxBPMNError exception = assertThrows(HttpClient4xxBPMNError.class , () ->restClient.get().uri(getDummyUriWithPort()).retrieve() + .body(String.class)); + + //Post call conditions (we get more or less the expected message with the original request) + //IF it is not the case, check that the spring private field has not changed or been renamed + String actualMessage = exception.getMessage(); + assertThat(actualMessage) + .contains("GET") + .contains(getDummyUriWithPort()) + .contains(String.valueOf(HttpStatus.BAD_REQUEST.value())); + } + + @Test + @DisplayName("Test that containsCauseOfType find an existing cause") + void containsCauseOfType_shouldFindCauseIfExists() { + //Prepare + String rootMessage="TEST"; + ArithmeticException exRoot=new ArithmeticException(rootMessage); + Exception exLvl1=new Exception("dummy",exRoot ); + Exception ex = new Exception("dummy",exLvl1 ); + + //Call + boolean found = RestClientHelper.containsCauseOfType(ex, List.of(ArithmeticException.class)); + //Check + assertTrue(found,"ArithmeticException should be found"); + + //Call + found = RestClientHelper.containsCauseOfType(exLvl1, List.of(ArithmeticException.class)); + //Check + assertTrue(found,"ArithmeticException should be found"); + + //Call + found = RestClientHelper.containsCauseOfType(exRoot, List.of(ArithmeticException.class)); + //Check + assertTrue(found,"ArithmeticException should be found"); + + //Call + found = RestClientHelper.containsCauseOfType(exRoot, List.of(RuntimeException.class)); + //Check + assertTrue(found,"RuntimeException should be found"); + + //Call + found = RestClientHelper.containsCauseOfType(exRoot, List.of(IOException.class,RuntimeException.class)); + //Check + assertTrue(found,"RuntimeException should be found"); + + //Call + found = RestClientHelper.containsCauseOfType(exRoot, List.of(IOException.class)); + //Check (should not be found) + assertFalse(found,"IOException should not be found"); + } + + /* + + + private MockResponse fileToResponse(String contentType, File file) throws IOException { + return new MockResponse() + .setResponseCode(HttpStatus.OK.value()) + .setBody(ProtoolsTestUtils.fileToBytes(file)) + .addHeader("content-type: " + contentType); + } + + private File createDummyFile(int sizeInByte, String extension) throws IOException { + File file = File.createTempFile("tempFile", ".json"); + file.deleteOnExit(); + RandomAccessFile rafile; + rafile = new RandomAccessFile(file, "rw"); + //In Bytes ==> 1024 = 1Ko ==> 1024X1024 : 1Mo + rafile.setLength(sizeInByte); + return file; + } + + @Test + @DisplayName("Test getRestClientForFile method - get the client and download files of different sizes") + void getRestClientForFile() throws IOException { + RestClient client = restClientHelper.getRestClient(); + assertThat(client).isNotNull(); + + //Create a 1Mo File + File file1mo = createDummyFile(1024 * 1024 * 1,".json"); + File file19mo = createDummyFile(RestClientHelper.getDefaultFileBufferSize()-1024,".json"); + int tooBigSize=RestClientHelper.getDefaultFileBufferSize()+1024; + File fileTooBig = createDummyFile(tooBigSize,".json"); + + MockResponse fileToResponse_1Mo = fileToResponse(MediaType.APPLICATION_JSON_VALUE, file1mo); + MockResponse fileToResponse_19Mo = fileToResponse(MediaType.APPLICATION_JSON_VALUE, file19mo); + MockResponse fileToResponseTooBig = fileToResponse(MediaType.APPLICATION_JSON_VALUE, fileTooBig); + + + + + KeycloakResponse kcResponse = new KeycloakResponse(); + kcResponse.setAccesToken("MYTOKEN"); + kcResponse.setExpiresIn(5*60*1000); + + + MockResponse mockResponseKC = new MockResponse() + .addHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON) + .setResponseCode(HttpStatus.OK.value()) + .setBody(new ObjectMapper().writeValueAsString(kcResponse)); + + final Dispatcher dispatcher = new Dispatcher() { + public MockResponse dispatch(RecordedRequest request) { + switch (request.getPath()) { + case "/users/1": + return new MockResponse().setResponseCode(200); + case "/users/2": + return new MockResponse().setResponseCode(500); + case "/users/3": + return new MockResponse().setResponseCode(200).setBody("{\"id\": 1, \"name\":\"duke\"}"); + } + return new MockResponse().setResponseCode(404); + } + + mockWebServer.enqueue(mockResponseKC); + + + + initMockWebServer(); + mockWebServer.enqueue(fileToResponse_1Mo); + mockWebServer.enqueue(fileToResponse_19Mo); + mockWebServer.enqueue(fileToResponseTooBig); + mockWebServer.enqueue(fileToResponseTooBig); + + //Check for 1Mo file + assertDoesNotThrow(()-> restClientHelper.getRestClientForFile() + .get() + .uri(getDummyUriWithPort()) + .retrieve() + .bodyToMono(String.class) + .block()); + + //Check for 19Mo file + assertDoesNotThrow(()-> restClientHelper.getRestClientForFile() + .get() + .uri(getDummyUriWithPort()) + .retrieve() + .bodyToMono(String.class) + .block()); + + //Check for a too big file : Should throw and exception as default buffer is 20Mo + assertThrows(clientResponseException.class, () -> restClientHelper.getRestClientForFile() + .get() + .uri(getDummyUriWithPort()) + .retrieve() + .bodyToMono(String.class) + .block()); + + //Check for a too big file with a custom buffer ==> Should be ok + assertDoesNotThrow(() -> restClientHelper.getRestClientForFile(tooBigSize) + .get() + .uri(getDummyUriWithPort()) + .retrieve() + .bodyToMono(String.class) + .block()); + } + + };*/ + +} \ No newline at end of file diff --git a/src/test/java/fr/insee/protools/backend/service/common/platine_sabiane/QuestionnaireHelperTest.java b/src/test/java/fr/insee/protools/backend/service/common/platine_sabiane/QuestionnaireHelperTest.java deleted file mode 100644 index 6c0d2896..00000000 --- a/src/test/java/fr/insee/protools/backend/service/common/platine_sabiane/QuestionnaireHelperTest.java +++ /dev/null @@ -1,259 +0,0 @@ -package fr.insee.protools.backend.service.common.platine_sabiane; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import fr.insee.protools.backend.ProtoolsTestUtils; -import fr.insee.protools.backend.dto.platine_sabiane_questionnaire.campaign.MetadataValue; -import fr.insee.protools.backend.dto.platine_sabiane_questionnaire.campaign.MetadataValueItem; -import fr.insee.protools.backend.dto.platine_sabiane_questionnaire.campaign.MetadataVariables; -import fr.insee.protools.backend.service.context.ContextConstants; -import fr.insee.protools.backend.service.nomenclature.NomenclatureService; -import fr.insee.protools.backend.service.platine.delegate.PlatineQuestionnaireCreateContextTaskTest; -import fr.insee.protools.backend.service.questionnaire_model.QuestionnaireModelService; -import fr.insee.protools.backend.service.sabiane.delegate.SabianeQuestionnaireCreateContextTaskTest; -import org.apache.commons.lang3.tuple.ImmutablePair; -import org.apache.commons.lang3.tuple.Pair; -import org.assertj.core.groups.Tuple; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.Spy; -import org.mockito.junit.jupiter.MockitoExtension; -import org.springframework.util.ClassUtils; - -import java.io.IOException; -import java.util.*; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import static fr.insee.protools.backend.service.context.ContextConstants.*; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.*; - -@ExtendWith(MockitoExtension.class) -class QuestionnaireHelperTest { - - final static String platineRessourceFolder = ClassUtils.convertClassNameToResourcePath(PlatineQuestionnaireCreateContextTaskTest.class.getPackageName()); - final static String platine_context_json = platineRessourceFolder + "/protools-contexte-platine-individu.json"; - - final static String sabianeRessourceFolder = ClassUtils.convertClassNameToResourcePath(SabianeQuestionnaireCreateContextTaskTest.class.getPackageName()); - final static String sabiane_context_json = sabianeRessourceFolder + "/protools-contexte-sabiane.json"; - - - @Mock QuestionnaireModelService questionnaireModelService; - @Mock NomenclatureService nomenclatureService; - @Mock QuestionnairePlatineSabianeService questionnairePlatineSabianeService; - @Spy ObjectMapper objectMapper; - - private final String nomenclatureContent1 = "{\"content\":\"content1\"}"; - private final String nomenclatureContent2 = "{\"content\":\"content2\"}"; - private final String nomenclatureID1 = "ID1"; - private final String nomenclatureID2 = "ID2"; - private final String nomenclatureLabel1 = "label1"; - private final String nomenclatureLabel2 = "label2"; - private final String questionnaireContent1 = "{\"id\":\"TOTO\"}"; - - private JsonNode initNomenclatureTest() { - // preconditions - List> nomenclatures = new ArrayList<>(2); - Map nomenclature1 = Map.of("id", nomenclatureID1, "cheminRepertoire", "path", "label", nomenclatureLabel1); - Map nomenclature2 = Map.of("id", nomenclatureID2, "cheminRepertoire", "path", "label", nomenclatureLabel2); - nomenclatures.add(nomenclature1); - nomenclatures.add(nomenclature2); - //For some tests where the nomenclature already exists in platine, this mock will never be used - //To avoid mockito exception warning about unused mock, we can mark it as lenient - lenient().when(nomenclatureService.getNomenclatureContent(nomenclatureID2, "path")).thenReturn(nomenclatureContent2); - lenient().when(nomenclatureService.getNomenclatureContent(nomenclatureID1, "path")).thenReturn(nomenclatureContent1); - return objectMapper.valueToTree(nomenclatures); - } - - @Test - void initRequiredNomenclatures_should_work_when_no_nomenclature_not_exists_in_remote_plateform() throws IOException { - // preconditions (2 nomenclatures - None already exists in platine/sabiane) - JsonNode nomenclaturesNode = initNomenclatureTest(); - when(questionnairePlatineSabianeService.getNomenclaturesId()).thenReturn(new HashSet<>()); - var iter = nomenclaturesNode.elements(); - - //Execute the unit under test - QuestionnaireHelper.initRequiredNomenclatures(questionnairePlatineSabianeService, nomenclatureService, "1", iter); - - // postconditions : Both nomenclatures are created - verify(questionnairePlatineSabianeService).postNomenclature( - nomenclatureID1, - nomenclatureLabel1, - objectMapper.readTree(nomenclatureContent1)); - verify(questionnairePlatineSabianeService).postNomenclature( - nomenclatureID2, - nomenclatureLabel2, - objectMapper.readTree(nomenclatureContent2)); - } - - @Test - void initRequiredNomenclatures_should_work_when_one_nomenclature_exists_in_remote_plateform() throws IOException { - // preconditions (2 nomenclatures - One already exists in platine/sabiane) - JsonNode nomenclaturesNode = initNomenclatureTest(); - when(questionnairePlatineSabianeService.getNomenclaturesId()).thenReturn(Set.of("XXX", nomenclatureID1, "TOTO", "TATA")); - var iter = nomenclaturesNode.elements(); - - //Execute the unit under test - QuestionnaireHelper.initRequiredNomenclatures(questionnairePlatineSabianeService, nomenclatureService, "1", iter); - - // postconditions - //Existing nomenclature is not created - verify(questionnairePlatineSabianeService, never()).postNomenclature( - nomenclatureID1, - nomenclatureLabel1, - objectMapper.readTree(nomenclatureContent1)); - //New nomenclature is created - verify(questionnairePlatineSabianeService).postNomenclature( - nomenclatureID2, - nomenclatureLabel2, - objectMapper.readTree(nomenclatureContent2)); - } - - private Set runInitQuestionnaireModels(JsonNode contextRootNode) { - // preconditions - when(questionnaireModelService.getQuestionnaireModel(anyString(), anyString())).thenReturn(questionnaireContent1); - - //Execute the unit under test - return QuestionnaireHelper.initQuestionnaireModels(questionnairePlatineSabianeService, questionnaireModelService, "1", contextRootNode); - } - - @Test - void initQuestionnaireModels_should_return_list_of_modelsId_with_platine_context() { - JsonNode contextRootNode = ProtoolsTestUtils.asJsonNode(platine_context_json); - assertEquals(1, contextRootNode.path(ContextConstants.CTX_QUESTIONNAIRE_MODELS).size(), "Context error : expected exactly one questionnaire model"); - - Set questionnaireModels = runInitQuestionnaireModels(contextRootNode); - - // postconditions : we expect to find exactly one questionnaire Model - String idQuestionnaireModel = contextRootNode.path(ContextConstants.CTX_QUESTIONNAIRE_MODELS).get(0).path(CTX_QUESTIONNAIRE_MODEL_ID).asText(); - assertEquals(Set.of(idQuestionnaireModel), questionnaireModels); - verify(questionnaireModelService,times(1)).getQuestionnaireModel( - contextRootNode.path(CTX_QUESTIONNAIRE_MODELS).get(0).path(CTX_QUESTIONNAIRE_MODEL_ID).asText() - , contextRootNode.path(CTX_QUESTIONNAIRE_MODELS).get(0).path(CTX_QUESTIONNAIRE_MODEL_CHEMIN_REPERTOIRE).asText()); - - final ArgumentCaptor > nomenclaturesCaptor - = ArgumentCaptor.forClass((Class) Set.class); - ArgumentCaptor acModelID = ArgumentCaptor.forClass(String.class); - ArgumentCaptor acLabel = ArgumentCaptor.forClass(String.class); - - verify(questionnairePlatineSabianeService,times(1)).postQuestionnaireModel( - acModelID.capture(), - acLabel.capture(), - any(), nomenclaturesCaptor.capture()); - assertEquals(contextRootNode.path(CTX_QUESTIONNAIRE_MODELS).get(0).path(CTX_QUESTIONNAIRE_MODEL_ID).asText(),acModelID.getValue()); - assertEquals(contextRootNode.path(CTX_QUESTIONNAIRE_MODELS).get(0).path(CTX_QUESTIONNAIRE_MODEL_LABEL).asText(),acLabel.getValue()); - - List> captured = nomenclaturesCaptor.getAllValues(); - assertEquals(1,captured.size(),"We are supposed to call the method only one"); - Set actualNomenclatures = captured.get(0); - Set expectedNomenclatures = Set.of( - "L_DEPNAIS-1-1-0", - "L_PAYSNAIS-1-1-0", - "L_NATIONETR-1-1-0"); - assertTrue(expectedNomenclatures.size()==actualNomenclatures.size() - &&expectedNomenclatures.containsAll(actualNomenclatures) - && actualNomenclatures.containsAll(expectedNomenclatures) - ,"The set of nomenclature is incorrect"); - } - - @Test - void initQuestionnaireModels_should_return_list_of_modelsId_with_sabiane_context() { - JsonNode contextRootNode = ProtoolsTestUtils.asJsonNode(sabiane_context_json); - assertEquals(2, contextRootNode.path(ContextConstants.CTX_QUESTIONNAIRE_MODELS).size(), "Context error : expected exactly one questionnaire model"); - - Set questionnaireModels = runInitQuestionnaireModels(contextRootNode); - - // postconditions : we expect to find 2 Questionnaire Models - assertEquals(Stream.of("FAM2022X01", "tic2023a00_webMBG").collect(Collectors.toCollection(HashSet::new)), questionnaireModels); - } - - /** - * BIG integration test - */ - @Test - void createQuestionnaire_should_work_with_sabiane_context() { - JsonNode contextRootNode = ProtoolsTestUtils.asJsonNode(sabiane_context_json); - when(questionnairePlatineSabianeService.getNomenclaturesId()).thenReturn(new HashSet<>()); - when(nomenclatureService.getNomenclatureContent(any(), any())).thenReturn(nomenclatureContent1); - when(questionnaireModelService.getQuestionnaireModel(anyString(), anyString())).thenReturn(questionnaireContent1); - - MetadataValueItem medatadataItem = new MetadataValueItem("TOTO", "VALUE"); - MetadataValue metadataValue = MetadataValue - .builder() - .value(MetadataVariables.builder() - .variables(List.of(medatadataItem)) - .inseeContext("INSEE_CONTEXT") - .build() - ) - .build(); - //Execute the unit under test - QuestionnaireHelper.createQuestionnaire( - contextRootNode, questionnairePlatineSabianeService, nomenclatureService, questionnaireModelService, "1", metadataValue); - - - //Post Conditions on nomenclature part - ArgumentCaptor acNomenclatureId = ArgumentCaptor.forClass(String.class); - ArgumentCaptor acNomenclatureLabel = ArgumentCaptor.forClass(String.class); - ArgumentCaptor acNomenclatureValue = ArgumentCaptor.forClass(JsonNode.class); - //Context has 4 nomenclatures - verify(questionnairePlatineSabianeService, times(4)).postNomenclature(acNomenclatureId.capture(), acNomenclatureLabel.capture(), acNomenclatureValue.capture()); - //Verify arguments - Pair nomenclature1 = new ImmutablePair<>("L_DEPNAIS-1-1-0", "Liste des départements"); - Pair nomenclature2 = new ImmutablePair("L_PAYSNAIS-1-1-0", "liste des pays"); - Pair nomenclature3 = new ImmutablePair("L_NATIONETR-1-1-0", "liste des nationalités"); - Pair nomenclature4 = new ImmutablePair("L_COMMUNEPASSEE-1-1-0", "liste des communes"); - List> listOfNomenclatures = List.of(nomenclature1, nomenclature2, nomenclature3, nomenclature4); - //Creation of each nomenclature - assertTrue( - acNomenclatureId.getAllValues() - .containsAll( - List.of(nomenclature1.getKey(), nomenclature2.getKey(), nomenclature3.getKey(), nomenclature4.getKey()) - )); - //With correct parameters - for (int i = 0; i < 4; i++) { - String argId = acNomenclatureId.getAllValues().get(i); - Pair nomenclature = listOfNomenclatures.stream() - .filter(item -> argId.equals(item.getKey())) - .findAny() - .orElse(null); - assertNotNull(nomenclature, "Internal error in test : nomenclature should not be null here"); - assertEquals( nomenclature.getValue(),acNomenclatureLabel.getAllValues().get(i)); - assertEquals(nomenclatureContent1,acNomenclatureValue.getAllValues().get(i).toString().trim()); - } - - - //Post Conditions on questionnaire model part - ArgumentCaptor acQuestionnaireId = ArgumentCaptor.forClass(String.class); - ArgumentCaptor acQuestionnaireLabel = ArgumentCaptor.forClass(String.class); - ArgumentCaptor acQuestionnaireValue = ArgumentCaptor.forClass(JsonNode.class); - ArgumentCaptor> acRequiredNomenclatures = ArgumentCaptor.forClass( Set.class); - //Creation of each model - verify(questionnairePlatineSabianeService, times(2)) - .postQuestionnaireModel( - acQuestionnaireId.capture(),acQuestionnaireLabel.capture(),acQuestionnaireValue.capture(),acRequiredNomenclatures.capture() - ); - //With correct parameters - Tuple q1 = new Tuple("tic2023a00_webMBG","Super modèle 1",Set.of("L_DEPNAIS-1-1-0", "L_PAYSNAIS-1-1-0","L_NATIONETR-1-1-0")); - Tuple q2 = new Tuple("FAM2022X01","Super modèle 2",Set.of("L_COMMUNEPASSEE-1-1-0")); - List listOfModels = List.of(q1,q2); - - for (int i = 0; i < 2; i++) { - String argId = acQuestionnaireId.getAllValues().get(i); - Tuple modele = listOfModels.stream() - .filter(item -> argId.equals(item.toList().get(0))) - .findAny() - .orElse(null); - assertNotNull(modele, "Internal error in test : modele should not be null here"); - assertEquals( modele.toList().get(1),acQuestionnaireLabel.getAllValues().get(i)); - assertEquals( modele.toList().get(2),acRequiredNomenclatures.getAllValues().get(i)); - assertEquals(questionnaireContent1,acQuestionnaireValue.getAllValues().get(i).toString()); - - } - - } - -} \ No newline at end of file diff --git a/src/test/java/fr/insee/protools/backend/service/context/ContextServiceImplTest.java b/src/test/java/fr/insee/protools/backend/service/context/ContextServiceImplTest.java new file mode 100644 index 00000000..a8417228 --- /dev/null +++ b/src/test/java/fr/insee/protools/backend/service/context/ContextServiceImplTest.java @@ -0,0 +1,307 @@ +package fr.insee.protools.backend.service.context; + + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.ObjectReader; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import fr.insee.protools.backend.dto.ContexteProcessus; +import fr.insee.protools.backend.service.context.exception.BadContextIOException; +import fr.insee.protools.backend.service.context.exception.BadContextNotJSONBPMNError; +import fr.insee.protools.backend.service.exception.ProcessDefinitionNotFoundException; +import fr.insee.protools.backend.service.exception.TaskNotFoundException; +import org.flowable.common.engine.api.FlowableObjectNotFoundException; +import org.flowable.engine.RepositoryService; +import org.flowable.engine.RuntimeService; +import org.flowable.engine.TaskService; +import org.flowable.engine.impl.RepositoryServiceImpl; +import org.flowable.engine.impl.persistence.entity.ExecutionEntityImpl; +import org.flowable.engine.runtime.ProcessInstance; +import org.flowable.engine.runtime.ProcessInstanceQuery; +import org.flowable.engine.test.FlowableTest; +import org.flowable.task.service.impl.TaskQueryImpl; +import org.flowable.task.service.impl.persistence.entity.TaskEntityImpl; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import org.mockito.ArgumentCaptor; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Spy; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.mock.web.MockMultipartFile; +import org.springframework.util.ClassUtils; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.Map; +import java.util.Set; + +import static fr.insee.protools.backend.service.FlowableVariableNameConstants.VARNAME_CONTEXT; +import static org.assertj.core.api.AssertionsForClassTypes.assertThatCode; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +@FlowableTest +class ContextServiceImplTest { + + static final String ressourceFolder = ClassUtils.convertClassNameToResourcePath(ContextServiceImplTest.class.getPackageName()); + static final ObjectReader objectReader = new ObjectMapper().registerModule(new JavaTimeModule()).reader(); // maybe with configs + + @Spy + @InjectMocks + ContextServiceImpl contextService; + //ne marche pas avec FlowbaleTest ; il faut @ExtendWith(SpringExtension.class) + // @Value("classpath:fr/insee/protools/backend/service/context/minimal_valid_context.json") + // private Resource minimalValidCtx; + @Spy + private RuntimeService runtimeService; + @Spy + private RepositoryService repositoryService = new RepositoryServiceImpl(); + @Mock + private TaskService taskService; + private String dummyId = "ID"; + + static String[] businessKeyProvided() { + return new String[]{"myBusinessKeyForTest", null, " ", ""}; + } + + private void initTaskServiceMock() { + TaskEntityImpl task = new TaskEntityImpl(); + task.setProcessInstanceId(dummyId); + TaskQueryImpl tq = mock(TaskQueryImpl.class); + lenient().when(tq.taskId(any())).thenReturn(tq); + lenient().when(tq.singleResult()).thenReturn(task); + lenient().when(taskService.createTaskQuery()).thenReturn(tq); + } + + private void initRuntimeServiceMock() { + ProcessInstanceQuery piq = mock(ProcessInstanceQuery.class); + ProcessInstance pi = new ExecutionEntityImpl(); + + lenient().when(piq.processInstanceId(any())).thenReturn(piq); + lenient().when(piq.singleResult()).thenReturn(pi); + lenient().when(runtimeService.createProcessInstanceQuery()).thenReturn(piq); + } + + @Test + void processContextFileAndCompleteTask_should_throw_when_fileNotJson() { + //Preconditions + MockMultipartFile multipartFile = new MockMultipartFile("file.xlk", "file.xlk", "text/xml", "some json".getBytes()); + initTaskServiceMock(); + + //Call method under test + assertThrows(BadContextNotJSONBPMNError.class, () -> contextService.processContextFileAndCompleteTask(multipartFile, dummyId)); + } + + @Test + void processContextFileAndCompleteTask_should_throw_when_taskBlank() { + //Preconditions + MockMultipartFile multipartFile = new MockMultipartFile("file.json", "file.json", "text/json", "some json".getBytes()); + initTaskServiceMock(); + + //Call method under test + assertThrows(TaskNotFoundException.class, () -> contextService.processContextFileAndCompleteTask(multipartFile, null)); + assertThrows(TaskNotFoundException.class, () -> contextService.processContextFileAndCompleteTask(multipartFile, "")); + assertThrows(TaskNotFoundException.class, () -> contextService.processContextFileAndCompleteTask(multipartFile, " ")); + assertThrows(TaskNotFoundException.class, () -> contextService.processContextFileAndCompleteTask(multipartFile, " ")); + } + + @Test + void processContextFileAndCompleteTask_should_throw_when_taskNotFound() { + //Preconditions + MockMultipartFile multipartFile = new MockMultipartFile("file.json", "file.json", "text/json", "some json".getBytes()); + + TaskQueryImpl tq = mock(TaskQueryImpl.class); + when(tq.taskId(any())).thenReturn(tq); + when(tq.singleResult()).thenReturn(null); //Return null task + when(taskService.createTaskQuery()).thenReturn(tq); + //Call method under test + assertThrows(TaskNotFoundException.class, () -> contextService.processContextFileAndCompleteTask(multipartFile, dummyId)); + } + + @Test + void processContextFileAndCompleteTask_should_throw_when_taskNoProcessInstanceId() { + //Preconditions + MockMultipartFile multipartFile = new MockMultipartFile("file.json", "file.json", "text/json", "some json".getBytes()); + + TaskEntityImpl task = new TaskEntityImpl(); + task.setProcessInstanceId(null); //null process Instance ID + TaskQueryImpl tq = mock(TaskQueryImpl.class); + when(tq.taskId(any())).thenReturn(tq); + when(tq.singleResult()).thenReturn(task); + when(taskService.createTaskQuery()).thenReturn(tq); + //Call method under test + assertThrows(TaskNotFoundException.class, () -> contextService.processContextFileAndCompleteTask(multipartFile, dummyId)); + } + + @Test + void processContextFileAndCompleteTask_should_throw_when_incorectJson() { + //Preconditions + MockMultipartFile multipartFile = new MockMultipartFile("file.json", "file.json", "text/json", "{toto}".getBytes()); + initTaskServiceMock(); + + //Call method under test + assertThrows(BadContextIOException.class, () -> contextService.processContextFileAndCompleteTask(multipartFile, dummyId)); + } + + @Test + void processContextFileAndCompleteTask_should_throw_when_taskNotExists() { + //Preconditions + MockMultipartFile multipartFile = new MockMultipartFile("file.json", "file.json", "text/json", "{}".getBytes()); + TaskQueryImpl tq = mock(TaskQueryImpl.class); + when(tq.taskId(any())).thenReturn(tq); + when(tq.singleResult()).thenReturn(null); + when(taskService.createTaskQuery()).thenReturn(tq); + + + //Call method under test + assertThrows(TaskNotFoundException.class, () -> contextService.processContextFileAndCompleteTask(multipartFile, dummyId)); + } + + @Test + void processContextFileAndCompleteTask_should_work_when_ContextOk() throws IOException { + //Preconditions + InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream(ressourceFolder + "/minimal_valid_context.json"); + MockMultipartFile multipartFile = new MockMultipartFile("file.json", "file.json", "text/json", resourceAsStream); + initTaskServiceMock(); + //we skip context verification by returning no error + doReturn(Set.of()).when(contextService).isContextOKForBPMN(any(), any()); + //Do not try to continue in a BPMN + doNothing().when(taskService).complete(any(), anyMap()); + //Call method under test + assertThatCode(() -> contextService.processContextFileAndCompleteTask(multipartFile, dummyId)).doesNotThrowAnyException(); + } + + @Test + void getContextByProcessInstance_should_work_when_exists_and_AlreadyLoaded() throws IOException { + //Preconditions + initRuntimeServiceMock(); + processContextFileAndCompleteTask_should_work_when_ContextOk(); + //Call method under test + JsonNode contextRootNode = contextService.getContextJsonNodeByProcessInstance(dummyId); + + //Post conditions : We've got a valid context object + assertNotNull(contextRootNode); + assertNotNull(contextRootNode.get("metadonnees")); + assertNotNull(contextRootNode.get("labelCourt")); + assertEquals("006aa47d-1574-424b-a67f-40705bec81f6", contextRootNode.get("id").asText()); + } + + @ParameterizedTest + @MethodSource("businessKeyProvided") + void processContextFileAndCreateProcessInstance_should_work_when_ContextOk(String businessKey) throws IOException { + //Preconditions + InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream(ressourceFolder + "/minimal_valid_context.json"); + byte[] inputCtxAsByteArray = resourceAsStream.readAllBytes(); + MockMultipartFile multipartFile = new MockMultipartFile("file.json", "file.json", "text/json", inputCtxAsByteArray); + + String mockedPid = "CUSTOM_PID"; + ProcessInstance pi = mock(ExecutionEntityImpl.class); + when(pi.getProcessInstanceId()).thenReturn(mockedPid); + if (businessKey == null || businessKey.isBlank()) { + when(runtimeService.startProcessInstanceByKey(any(), anyMap())).thenReturn(pi); + } else { + when(runtimeService.startProcessInstanceByKey(any(), any(), any())).thenReturn(pi); + } + initRuntimeServiceMock(); + //we skip context verification by returning no error + doReturn(Set.of()).when(contextService).isContextOKForBPMN(any(), any()); + + //Call method under test + String processId = contextService.processContextFileAndCreateProcessInstance(multipartFile, "simpleProcess", businessKey); + + //Post conditions : We've got a valid Process Instance + assertEquals(mockedPid, processId); + // We've got a valid context object + JsonNode contextRootNode = contextService.getContextJsonNodeByProcessInstance(mockedPid); + //Post conditions : We've got a valid context object + assertNotNull(contextRootNode); + assertNotNull(contextRootNode.get("metadonnees")); + assertNotNull(contextRootNode.get("labelCourt")); + assertEquals("006aa47d-1574-424b-a67f-40705bec81f6", contextRootNode.get("id").asText()); + + //We should have called the correct startProcessInstanceByKey + ArgumentCaptor> variablesMapCaptor = ArgumentCaptor.forClass(Map.class); + if (businessKey == null || businessKey.isBlank()) { + verify(runtimeService, times(1)).startProcessInstanceByKey(eq("simpleProcess"), variablesMapCaptor.capture()); + } else { + verify(runtimeService, times(1)).startProcessInstanceByKey(eq("simpleProcess"), eq(businessKey), variablesMapCaptor.capture()); + } + //and stored the correct context in process variables + Map variableMap = variablesMapCaptor.getValue(); + String ctxAsString = (String) variableMap.get(VARNAME_CONTEXT); + String inputAsString = new String(inputCtxAsByteArray, StandardCharsets.UTF_8); + assertEquals(inputAsString, ctxAsString, "The stored contexte is incorrect"); + } + + + @Test + void processContextFileAndCreateProcessInstance_should_throw_when_processDefinitionId_is_null_or_blank() throws IOException { + //Preconditions + InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream(ressourceFolder + "/minimal_valid_context.json"); + MockMultipartFile multipartFile = new MockMultipartFile("file.json", "file.json", "text/json", resourceAsStream.readAllBytes()); + + //Call method under test + assertThrows(ProcessDefinitionNotFoundException.class, () -> contextService.processContextFileAndCreateProcessInstance(multipartFile, " ", dummyId)); + assertThrows(ProcessDefinitionNotFoundException.class, () -> contextService.processContextFileAndCreateProcessInstance(multipartFile, "", dummyId)); + assertThrows(ProcessDefinitionNotFoundException.class, () -> contextService.processContextFileAndCreateProcessInstance(multipartFile, null, dummyId)); + } + + @Test + void processContextFileAndCreateProcessInstance_should_throw_when_processDefinitionId_is_not_Found() throws IOException { + //Preconditions + InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream(ressourceFolder + "/minimal_valid_context.json"); + MockMultipartFile multipartFile = new MockMultipartFile("file.json", "file.json", "text/json", resourceAsStream.readAllBytes()); + initRuntimeServiceMock(); + doThrow(new FlowableObjectNotFoundException("msg")).when(runtimeService).startProcessInstanceByKey(any(),any(),anyMap()); + doReturn(new ContextServiceImpl.ContextPair("{}",null)).when(contextService).processContextFile(any(),any()); + //Call method under test + assertThrows(ProcessDefinitionNotFoundException.class, () -> contextService.processContextFileAndCreateProcessInstance(multipartFile, "throwingId", dummyId)); + } + + @Test + void processContextFile_should_throw_when_notJsonExtension(){ + //Prepare + MockMultipartFile multipartFile1 = new MockMultipartFile("file.xlk", "file.xlk", "text/xml", "some content".getBytes()); + MockMultipartFile multipartFile2 = new MockMultipartFile("file.", "file.", "text/xml", "some content".getBytes()); + MockMultipartFile multipartFile3 = new MockMultipartFile("file", "file", "text/xml", "some content".getBytes()); + + //Call method under test + assertThrows(BadContextNotJSONBPMNError.class, () -> contextService.processContextFile(multipartFile1, dummyId)); + assertThrows(BadContextNotJSONBPMNError.class, () -> contextService.processContextFile(multipartFile2, dummyId)); + assertThrows(BadContextNotJSONBPMNError.class, () -> contextService.processContextFile(multipartFile3, dummyId)); + } + + @Test + void jsonReadAndSchemaValidation_should_work_when_validJson() throws IOException { + // Prepare + InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream(ressourceFolder + "/minimal_valid_context.json"); + JsonNode rootContext = objectReader.readTree(resourceAsStream); + + // Call method under test + ContexteProcessus result = contextService.jsonReadAndSchemaValidation(rootContext); + + // Verify + assertNotNull(result); + } + + @Test + void jsonReadAndSchemaValidation_should_throw_when_invalidJson() throws JsonProcessingException { + // Prepare + String jsonString = "{\"key\": \"value\"}"; // Replace with valid JSON + JsonNode rootContext = objectReader.readTree(jsonString); + + // Act & Assert + BadContextNotJSONBPMNError exception = assertThrows( + BadContextNotJSONBPMNError.class, + () -> contextService.jsonReadAndSchemaValidation(rootContext) + ); + assertTrue(exception.getMessage().contains("Uploaded context is not correct according to the json-schema")); + } +} diff --git a/src/test/java/fr/insee/protools/backend/service/context/ContextServiceTest.java b/src/test/java/fr/insee/protools/backend/service/context/ContextServiceTest.java deleted file mode 100644 index 99796d2c..00000000 --- a/src/test/java/fr/insee/protools/backend/service/context/ContextServiceTest.java +++ /dev/null @@ -1,171 +0,0 @@ -package fr.insee.protools.backend.service.context; - -import com.fasterxml.jackson.databind.JsonNode; -import fr.insee.protools.backend.service.context.exception.BadContextIOException; -import fr.insee.protools.backend.service.context.exception.BadContextNotJSONBPMNError; -import fr.insee.protools.backend.service.exception.TaskNotFoundException; -import org.flowable.engine.RepositoryService; -import org.flowable.engine.RuntimeService; -import org.flowable.engine.TaskService; -import org.flowable.engine.impl.RepositoryServiceImpl; -import org.flowable.engine.impl.persistence.entity.ExecutionEntityImpl; -import org.flowable.engine.runtime.ProcessInstance; -import org.flowable.engine.runtime.ProcessInstanceQuery; -import org.flowable.engine.test.FlowableTest; -import org.flowable.task.service.impl.TaskQueryImpl; -import org.flowable.task.service.impl.persistence.entity.TaskEntityImpl; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.Spy; -import org.mockito.junit.jupiter.MockitoExtension; -import org.springframework.mock.web.MockMultipartFile; -import org.springframework.util.ClassUtils; - -import java.io.IOException; -import java.io.InputStream; -import java.util.Set; - -import static org.assertj.core.api.AssertionsForClassTypes.assertThatCode; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.*; - - -@ExtendWith(MockitoExtension.class) -@FlowableTest -class ContextServiceTest { - final static String ressourceFolder = ClassUtils.convertClassNameToResourcePath(ContextServiceTest.class.getPackageName()); - - @Spy - private RuntimeService runtimeService; - @Spy - private RepositoryService repositoryService = new RepositoryServiceImpl(); - @Mock - private TaskService taskService; - - @Spy - @InjectMocks - ContextServiceImpl contextService; - - private String dummyId="ID"; - - private void initTaskServiceMock(){ - TaskEntityImpl task = new TaskEntityImpl(); - task.setProcessInstanceId(dummyId); - TaskQueryImpl tq = mock(TaskQueryImpl.class); - when(tq.taskId(any())).thenReturn(tq); - when(tq.singleResult()).thenReturn(task); - when(taskService.createTaskQuery()).thenReturn(tq); - } - - - private void initRuntimeSericeMock(){ - ProcessInstanceQuery piq = mock(ProcessInstanceQuery.class); - ProcessInstance pi = new ExecutionEntityImpl(); - - when(piq.processInstanceId(any())).thenReturn(piq); - when(piq.singleResult()).thenReturn(pi); - when(runtimeService.createProcessInstanceQuery()).thenReturn(piq); - } - - @Test - void processContextFileAndCompleteTask_should_throw_when_fileNotJson() { - //Preconditions - MockMultipartFile multipartFile = new MockMultipartFile("file.xml", "file.xml", "text/xml", "some xml".getBytes()); - initTaskServiceMock(); - - //Call method under test - assertThrows(BadContextNotJSONBPMNError.class, () -> contextService.processContextFileAndCompleteTask(multipartFile,dummyId)); - } - - - @Test - void processContextFileAndCompleteTask_should_throw_when_incorectJson() { - //Preconditions - MockMultipartFile multipartFile = new MockMultipartFile("file.json", "file.json", "text/json", "{toto}".getBytes()); - initTaskServiceMock(); - - //Call method under test - assertThrows(BadContextIOException.class, () -> contextService.processContextFileAndCompleteTask(multipartFile,dummyId)); - } - - - @Test - void processContextFileAndCompleteTask_should_throw_when_taskNotExists() { - //Preconditions - MockMultipartFile multipartFile = new MockMultipartFile("file.json", "file.json", "text/json", "{}".getBytes()); - TaskQueryImpl tq = mock(TaskQueryImpl.class); - when(tq.taskId(any())).thenReturn(tq); - when(tq.singleResult()).thenReturn(null); - when(taskService.createTaskQuery()).thenReturn(tq); - - - //Call method under test - assertThrows(TaskNotFoundException.class, () -> contextService.processContextFileAndCompleteTask(multipartFile,dummyId)); - } - - - @Test - void processContextFileAndCompleteTask_should_work_when_ContextOk() throws IOException { - //Preconditions - InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream(ressourceFolder+"/protools-contexte-platine.json"); - MockMultipartFile multipartFile = new MockMultipartFile("file.json", "file.json", "text/json", resourceAsStream.readAllBytes()); - initTaskServiceMock(); - //we skip context verification by returning no error - doReturn(Set.of()).when(contextService).isContextOKForBPMN(any(),any()); - //Do not try to continue in a BPMN - doNothing().when(taskService).complete(any(),anyMap()); - //Call method under test - assertThatCode(() -> contextService.processContextFileAndCompleteTask(multipartFile,dummyId)).doesNotThrowAnyException(); - } - - @Test - void getContextByProcessInstance_should_work_when_exists_and_AlreadyLoaded() throws IOException { - //Preconditions - initRuntimeSericeMock(); - processContextFileAndCompleteTask_should_work_when_ContextOk(); - //Call method under test - JsonNode contextRootNode = contextService.getContextByProcessInstance(dummyId); - - //Post conditions : We've got a valid context object - assertNotNull(contextRootNode); - assertNotNull(contextRootNode.get(ContextConstants.CTX_METADONNEES)); - assertNotNull(contextRootNode.get(ContextConstants.CTX_CAMPAGNE_ID)); - assertNotNull(contextRootNode.get(ContextConstants.CTX_CAMPAGNE_LABEL)); - assertEquals("DEM2022X00",contextRootNode.get(ContextConstants.CTX_CAMPAGNE_ID).asText()); - } - - @Test - void processContextFileAndCreateProcessInstance_should_work_when_ContextOk() throws IOException { - //Preconditions - InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream(ressourceFolder+"/protools-contexte-platine.json"); - MockMultipartFile multipartFile = new MockMultipartFile("file.json", "file.json", "text/json", resourceAsStream.readAllBytes()); - - ProcessInstance pi = mock(ExecutionEntityImpl.class); - when(pi.getProcessInstanceId()).thenReturn(dummyId); - when(runtimeService.startProcessInstanceByKey(any(),any(),any())).thenReturn(pi); - initRuntimeSericeMock(); - //we skip context verification by returning no error - doReturn(Set.of()).when(contextService).isContextOKForBPMN(any(),any()); - - //Call method under test - String processId=contextService.processContextFileAndCreateProcessInstance(multipartFile,"simpleProcess",dummyId); - - //Post conditions : We've got a valid Process Instance - assertEquals(dummyId,processId); - //Process instance creation has been called once - verify(runtimeService).startProcessInstanceByKey(any(),any(),any()); - // We've got a valid context object - JsonNode contextRootNode = contextService.getContextByProcessInstance(dummyId); - //Post conditions : We've got a valid context object - assertNotNull(contextRootNode); - assertNotNull(contextRootNode.get(ContextConstants.CTX_METADONNEES)); - assertNotNull(contextRootNode.get(ContextConstants.CTX_CAMPAGNE_ID)); - assertNotNull(contextRootNode.get(ContextConstants.CTX_CAMPAGNE_LABEL)); - assertEquals("DEM2022X00",contextRootNode.get(ContextConstants.CTX_CAMPAGNE_ID).asText()); - - } - -} diff --git a/src/test/java/fr/insee/protools/backend/service/era/EraGetSUForPeriodAndGenderTaskTest.java b/src/test/java/fr/insee/protools/backend/service/era/EraGetSUForPeriodAndGenderTaskTest.java deleted file mode 100644 index 2a0d3f21..00000000 --- a/src/test/java/fr/insee/protools/backend/service/era/EraGetSUForPeriodAndGenderTaskTest.java +++ /dev/null @@ -1,145 +0,0 @@ -package fr.insee.protools.backend.service.era; - -import com.fasterxml.jackson.core.JsonProcessingException; -import fr.insee.protools.backend.ProtoolsTestUtils; -import fr.insee.protools.backend.dto.era.CensusJsonDto; -import fr.insee.protools.backend.dto.era.GenderType; -import fr.insee.protools.backend.service.context.exception.BadContextIncorrectBPMNError; -import fr.insee.protools.backend.service.utils.TestWithContext; -import org.flowable.common.engine.api.FlowableIllegalArgumentException; -import org.flowable.engine.delegate.DelegateExecution; -import org.flowable.engine.test.FlowableTest; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.junit.jupiter.MockitoExtension; - -import java.time.LocalDate; -import java.util.List; - -import static fr.insee.protools.backend.service.FlowableVariableNameConstants.*; -import static fr.insee.protools.backend.service.utils.FlowableVariableUtils.getMissingVariableMessage; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.*; - -@ExtendWith(MockitoExtension.class) -@FlowableTest -class EraGetSUForPeriodAndGenderTaskTest extends TestWithContext { - - @Mock EraService eraService; - @InjectMocks EraGetSUForPeriodAndGenderTask eraGetSUForPeriodAndGenderTask; - - String dumyId = "ID999"; - final static String era_context_2partition = "{ \"partitions\": [{ \"id\": 1 , \"sexe\": \"hommes\" }, { \"id\": 2 , \"sexe\": \"femmes\" }] }"; - - @Test - void execute_should_throwError_when_null_context(){ - assertThat_delegate_throwError_when_null_context(eraGetSUForPeriodAndGenderTask); - } - - @Test - @DisplayName("Test execute method - should throw if VARNAME_ERA_QUERY_START_DATE or VARNAME_ERA_QUERY_END_DATE or VARNAME_CURRENT_PARTITION_ID not initialized") - void execute_should_throw_FlowableIllegalArgumentException_when_variables_notDefined() { - //Precondition - DelegateExecution execution = mock(DelegateExecution.class); - lenient().when(execution.getProcessInstanceId()).thenReturn(dumyId); - initContexteMockWithString(era_context_2partition); - - //Execute the unit under test - FlowableIllegalArgumentException exception = assertThrows(FlowableIllegalArgumentException.class, () -> eraGetSUForPeriodAndGenderTask.execute(execution)); - //Post conditions - assertThat(exception.getMessage()).isEqualTo(getMissingVariableMessage(VARNAME_ERA_QUERY_START_DATE)); - - //Create First variable - when(execution.getVariable(VARNAME_ERA_QUERY_START_DATE, LocalDate.class)).thenReturn(LocalDate.now().minusDays(1)); - //Execute again - exception = assertThrows(FlowableIllegalArgumentException.class, () -> eraGetSUForPeriodAndGenderTask.execute(execution)); - //Check the error - assertThat(exception.getMessage()).isEqualTo(getMissingVariableMessage(VARNAME_ERA_QUERY_END_DATE)); - - //Create 2nd variable - when(execution.getVariable(VARNAME_ERA_QUERY_END_DATE, LocalDate.class)).thenReturn(LocalDate.now()); - //Execute again - exception = assertThrows(FlowableIllegalArgumentException.class, () -> eraGetSUForPeriodAndGenderTask.execute(execution)); - //Check the error - assertThat(exception.getMessage()).isEqualTo(getMissingVariableMessage(VARNAME_CURRENT_PARTITION_ID)); - - //Create 3rd variable - when(execution.getVariable(VARNAME_CURRENT_PARTITION_ID, Long.class)).thenReturn(1l); - //Execute again - assertDoesNotThrow(() -> eraGetSUForPeriodAndGenderTask.execute(execution)); - } - - @Test - @DisplayName("Test execute method - should throw if Context is not correct") - void execute_should_throw_BadContext_when_contextIncorrect() throws JsonProcessingException { - //Precondition - DelegateExecution execution = mock(DelegateExecution.class); - lenient().when(execution.getProcessInstanceId()).thenReturn(dumyId); - - LocalDate startDate = LocalDate.now().minusDays(1), endDate = LocalDate.now(); - when(execution.getVariable(VARNAME_ERA_QUERY_START_DATE, LocalDate.class)).thenReturn(startDate); - when(execution.getVariable(VARNAME_ERA_QUERY_END_DATE, LocalDate.class)).thenReturn(endDate); - when(execution.getVariable(VARNAME_CURRENT_PARTITION_ID, Long.class)).thenReturn(1l); - - final String context1 = - "{ \"partitions\": [{ \"id\": 1 }] }"; - final String context2 = - "{ \"partitions\": [{ \"id\": 1 , \"sexe\": \"3\" }] }"; - final String context3 = - "{ \"partitions\": [{ \"id\": 1 , \"sexe\": \"1\" }] }"; - final String context4 = - "{ \"partitions\": [{ \"id\": 1 , \"sexe\": 3 }] }"; - List contextErrorTestList=List.of(context1,context2,context3,context4); - for(String context : contextErrorTestList){ - //Precondition - ProtoolsTestUtils.initContexteMockFromString(protoolsContext, context); - //Run test - assertThrows(BadContextIncorrectBPMNError.class, () -> eraGetSUForPeriodAndGenderTask.execute(execution)); - Mockito.reset(protoolsContext); - } - //TEST OK - //Precondition - ProtoolsTestUtils.initContexteMockFromString(protoolsContext, era_context_2partition); - //Run test - assertDoesNotThrow(() -> eraGetSUForPeriodAndGenderTask.execute(execution)); - Mockito.reset(protoolsContext); - } - - @Test - @DisplayName("Test execute method - should work and make correct call to service and store result in correct variable") - void execute_should_work_when_variables_OK() { - //Precondition - DelegateExecution execution = mock(DelegateExecution.class); - lenient().when(execution.getProcessInstanceId()).thenReturn(dumyId); - LocalDate startDate = LocalDate.now().minusDays(1), endDate = LocalDate.now(); - initContexteMockWithString(era_context_2partition); - - when(execution.getVariable(VARNAME_ERA_QUERY_START_DATE, LocalDate.class)).thenReturn(startDate); - when(execution.getVariable(VARNAME_ERA_QUERY_END_DATE, LocalDate.class)).thenReturn(endDate); - when(execution.getVariable(VARNAME_CURRENT_PARTITION_ID, Long.class)).thenReturn(1l); - - GenderType gender = GenderType.MALE; - Long eraId1 = 500l, eraId2 = 1000l; - CensusJsonDto eraSU1 = CensusJsonDto.builder() - .id(eraId1) - .build(); - CensusJsonDto eraSU2 = CensusJsonDto.builder() - .id(eraId2) - .build(); - List listOfEraSU = List.of(eraSU1, eraSU2); - when(eraService.getSUForPeriodAndSex(startDate, endDate, gender)).thenReturn(listOfEraSU); - - //Run method under test - assertDoesNotThrow(() -> eraGetSUForPeriodAndGenderTask.execute(execution)); - - //Post conditions - verify(eraService, times(1)).getSUForPeriodAndSex(startDate, endDate, gender); - verify(execution, times(1)).setVariableLocal(VARNAME_ERA_RESPONSE, listOfEraSU); - } -} \ No newline at end of file diff --git a/src/test/java/fr/insee/protools/backend/service/meshuggah/MeshuggahCreateCommunicationsContextTaskTest.java b/src/test/java/fr/insee/protools/backend/service/meshuggah/MeshuggahCreateCommunicationsContextTaskTest.java deleted file mode 100644 index e52eab39..00000000 --- a/src/test/java/fr/insee/protools/backend/service/meshuggah/MeshuggahCreateCommunicationsContextTaskTest.java +++ /dev/null @@ -1,230 +0,0 @@ -package fr.insee.protools.backend.service.meshuggah; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonNode; -import fr.insee.protools.backend.ProtoolsTestUtils; -import fr.insee.protools.backend.service.context.exception.BadContextIncorrectBPMNError; -import fr.insee.protools.backend.dto.meshuggah.MeshuggahComDetails; -import fr.insee.protools.backend.service.utils.TestWithContext; -import org.flowable.engine.delegate.DelegateExecution; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; -import org.mockito.ArgumentCaptor; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.Mockito; - -import java.util.List; -import java.util.stream.Stream; - -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.*; -import static org.mockito.Mockito.times; - - -class MeshuggahCreateCommunicationsContextTaskTest extends TestWithContext { - - @Mock MeshuggahService meshuggahService; - @InjectMocks MeshuggahCreateCommunicationsContextTask meshuggahTask; - - //To be able to run tests with differents protools contexts - private static Stream contextErrorArguments() { - return Stream.of( - Arguments.of(MeshuggahCtxExamples.ctx_ERROR_2partitions_2com_1_typo_phase), - Arguments.of(MeshuggahCtxExamples.ctx_ERROR_no_part), - Arguments.of(MeshuggahCtxExamples.ctx_ERROR_no_com), - Arguments.of(MeshuggahCtxExamples.ctx_ERROR_no_moyen), - Arguments.of(MeshuggahCtxExamples.ctx_ERROR_typo_phase), - Arguments.of(MeshuggahCtxExamples.ctx_ERROR_1partitions_2com_1_typo_moyen), - Arguments.of(MeshuggahCtxExamples.ctx_ERROR_typo_moyen)); - } - - @Test - void execute_should_throwError_when_null_context(){ - assertThat_delegate_throwError_when_null_context(meshuggahTask); - } - - @ParameterizedTest - @MethodSource("contextErrorArguments") - @DisplayName("Test execute method - should throw if Context is not correct") - void execute_should_throw_BadContext_when_contextIncorrect(String context_json) throws JsonProcessingException { - //Precondition - DelegateExecution execution = mock(DelegateExecution.class); - lenient().when(execution.getProcessInstanceId()).thenReturn(dumyId); - - //Precondition - ProtoolsTestUtils.initContexteMockFromString(protoolsContext, context_json); - //Run test - assertThrows(BadContextIncorrectBPMNError.class, () -> meshuggahTask.execute(execution)); - Mockito.reset(protoolsContext); - } - - - @Test - @DisplayName("Test execute method - should work and make correct call to service when context has one partition") - void execute_should_work_when_ctx_1_part_ouverture_courrier() { - //Precondition - DelegateExecution execution = mock(DelegateExecution.class); - lenient().when(execution.getProcessInstanceId()).thenReturn(dumyId); - initContexteMockWithString(MeshuggahCtxExamples.ctx_OK_1part_ouverture_courrier); - - //Run method under test - assertDoesNotThrow(() -> meshuggahTask.execute(execution)); - - //Post conditions - MeshuggahComDetails expectedDetails = MeshuggahComDetails.builder() - .campaignId("AAC2023A00") - .phase("OUVERTURE") - .medium("COURRIER") - .mode("WEB") - .partitioningId(MeshuggahCtxExamples.ctx_partition1.toString()) - .avecQuestionnaire(false) - .protocol("DEFAULT") - .operation("RELANCE_LIBRE") - .build(); - ArgumentCaptor acDetails = ArgumentCaptor.forClass(MeshuggahComDetails.class); - ArgumentCaptor acBody = ArgumentCaptor.forClass(JsonNode.class); - verify(meshuggahService,times(1)).postCreateCommunication(acDetails.capture(),acBody.capture()); - MeshuggahComDetails details = acDetails.getValue(); - assertEquals(expectedDetails,details); - - - JsonNode actualBody = acBody.getValue(); - assertEquals(MeshuggahCtxExamples.ctx_complementConnexion,actualBody.path("Enq_ComplementConnexion").asText()); - assertEquals(MeshuggahCtxExamples.ctx_logoPrestataire,actualBody.path("Enq_LogoPrestataire").asText()); - assertEquals(MeshuggahCtxExamples.ctx_mailResponsableOperationnel,actualBody.path("Enq_MailRespOperationnel").asText()); - assertEquals(MeshuggahCtxExamples.ctx_prestataire,actualBody.path("Enq_Prestataire").asBoolean()); - assertEquals(MeshuggahCtxExamples.ctx_relanceLibreMailParagraphe1,actualBody.path("Enq_RelanceLibreMailParagraphe1").asText()); - assertEquals(MeshuggahCtxExamples.ctx_relanceLibreMailParagraphe2,actualBody.path("Enq_RelanceLibreMailParagraphe2").asText()); - assertEquals(MeshuggahCtxExamples.ctx_relanceLibreMailParagraphe3,actualBody.path("Enq_RelanceLibreMailParagraphe3").asText()); - assertEquals(MeshuggahCtxExamples.ctx_relanceLibreMailParagraphe4,actualBody.path("Enq_RelanceLibreMailParagraphe4").asText()); - assertEquals(MeshuggahCtxExamples.ctx_responsableOperationnel,actualBody.path("Enq_RespOperationnel").asText()); - assertEquals(MeshuggahCtxExamples.ctx_responsableTraitement,actualBody.path("Enq_RespTraitement").asText()); - assertEquals(MeshuggahCtxExamples.ctx_serviceCollecteurSignataireFonction,actualBody.path("Enq_ServiceCollecteurSignataireFonction").asText()); - assertEquals(MeshuggahCtxExamples.ctx_serviceCollecteurSignataireNom,actualBody.path("Enq_ServiceCollecteurSignataireNom").asText()); - assertEquals(MeshuggahCtxExamples.ctx_themeMieuxConnaitreMail,actualBody.path("Enq_ThemeMieuxConnaitreMail").asText()); - assertEquals(MeshuggahCtxExamples.ctx_urlEnquete,actualBody.path("Enq_UrlEnquete").asText()); - assertEquals(MeshuggahCtxExamples.ctx_boiteRetour,actualBody.path("Mail_BoiteRetour").asText()); - assertEquals(MeshuggahCtxExamples.ctx_objetMail,actualBody.path("Mail_Objet").asText()); - } - - - @Test - @DisplayName("Test execute method - should work and make correct call to service when context has one partition") - void execute_should_work_when_ctx_2_part_ouverture_courrier_relance_mail() { - //Precondition - DelegateExecution execution = mock(DelegateExecution.class); - lenient().when(execution.getProcessInstanceId()).thenReturn(dumyId); - initContexteMockWithString(MeshuggahCtxExamples.ctx_OK_2partitions_2com_ouverture_relance_ok); - - //Run method under test - assertDoesNotThrow(() -> meshuggahTask.execute(execution)); - - //Post conditions - MeshuggahComDetails expectedDetailsOuverture = MeshuggahComDetails.builder() - .campaignId("AAC2023A00") - .phase("OUVERTURE") - .medium("COURRIER") - .mode("WEB") - .partitioningId("to be set") - .avecQuestionnaire(false) - .protocol("DEFAULT") - .operation("RELANCE_LIBRE") - .build(); - MeshuggahComDetails expectedDetailsRelance = MeshuggahComDetails.builder() - .campaignId("AAC2023A00") - .phase("RELANCE") - .medium("EMAIL") - .mode("WEB") - .partitioningId("to be set") - .avecQuestionnaire(false) - .protocol("DEFAULT") - .operation("RELANCE_LIBRE") - .build(); - ArgumentCaptor acDetails = ArgumentCaptor.forClass(MeshuggahComDetails.class); - ArgumentCaptor acBody = ArgumentCaptor.forClass(JsonNode.class); - verify(meshuggahService,times(4)).postCreateCommunication(acDetails.capture(),acBody.capture()); - - List actualDetailsList = acDetails.getAllValues(); - List actualBodiesList = acBody.getAllValues(); - - int nbOuverturePart1=0; - int nbOuverturePart2=0; - int nbRelancePart1=0; - int nbRelancePart2=0; - for(int i=0; i<4;i++){ - MeshuggahComDetails actualDetails = actualDetailsList.get(i); - - if(actualDetails.getPartitioningId().equals(MeshuggahCtxExamples.ctx_partition1.toString())){ - if(actualDetails.getPhase().equals("OUVERTURE")){ - expectedDetailsOuverture.setPartitioningId(MeshuggahCtxExamples.ctx_partition1.toString()); - assertEquals(expectedDetailsOuverture,actualDetails); - nbOuverturePart1++; - } - else if(actualDetails.getPhase().equals("RELANCE")){ - expectedDetailsRelance.setPartitioningId(MeshuggahCtxExamples.ctx_partition1.toString()); - assertEquals(expectedDetailsRelance,actualDetails); - nbRelancePart1++; - } - } - else if(actualDetails.getPartitioningId().equals(MeshuggahCtxExamples.ctx_partition2.toString())){ - if(actualDetails.getPhase().equals("OUVERTURE")){ - expectedDetailsOuverture.setPartitioningId(MeshuggahCtxExamples.ctx_partition2.toString()); - assertEquals(expectedDetailsOuverture,actualDetails); - nbOuverturePart2++; - } - else if(actualDetails.getPhase().equals("RELANCE")){ - expectedDetailsRelance.setPartitioningId(MeshuggahCtxExamples.ctx_partition2.toString()); - assertEquals(expectedDetailsRelance,actualDetails); - nbRelancePart2++; - } - } - else { - fail("Incorect test definition (nb partition)"); - } - - - JsonNode actualBody = actualBodiesList.get(i); - assertEquals(MeshuggahCtxExamples.ctx_complementConnexion,actualBody.path("Enq_ComplementConnexion").asText()); - assertEquals(MeshuggahCtxExamples.ctx_logoPrestataire,actualBody.path("Enq_LogoPrestataire").asText()); - assertEquals(MeshuggahCtxExamples.ctx_mailResponsableOperationnel,actualBody.path("Enq_MailRespOperationnel").asText()); - assertEquals(MeshuggahCtxExamples.ctx_prestataire,actualBody.path("Enq_Prestataire").asBoolean()); - - //we have various values for this fiels - if(actualDetails.getPartitioningId().equals(MeshuggahCtxExamples.ctx_partition2.toString())){ - if(actualDetails.getPhase().equals("OUVERTURE")) { - assertEquals(MeshuggahCtxExamples.ctx_relanceLibreMailParagraphe1_partition2_com1, actualBody.path("Enq_RelanceLibreMailParagraphe1").asText()); - } - else if(actualDetails.getPhase().equals("RELANCE")) { - assertEquals(MeshuggahCtxExamples.ctx_relanceLibreMailParagraphe1_partition2_com2, actualBody.path("Enq_RelanceLibreMailParagraphe1").asText()); - } - else{ - fail("Incorect test definition"); - } - } - else { - assertEquals(MeshuggahCtxExamples.ctx_relanceLibreMailParagraphe1, actualBody.path("Enq_RelanceLibreMailParagraphe1").asText()); - } - assertEquals(MeshuggahCtxExamples.ctx_relanceLibreMailParagraphe2,actualBody.path("Enq_RelanceLibreMailParagraphe2").asText()); - assertEquals(MeshuggahCtxExamples.ctx_relanceLibreMailParagraphe3,actualBody.path("Enq_RelanceLibreMailParagraphe3").asText()); - assertEquals(MeshuggahCtxExamples.ctx_relanceLibreMailParagraphe4,actualBody.path("Enq_RelanceLibreMailParagraphe4").asText()); - assertEquals(MeshuggahCtxExamples.ctx_responsableOperationnel,actualBody.path("Enq_RespOperationnel").asText()); - assertEquals(MeshuggahCtxExamples.ctx_responsableTraitement,actualBody.path("Enq_RespTraitement").asText()); - assertEquals(MeshuggahCtxExamples.ctx_serviceCollecteurSignataireFonction,actualBody.path("Enq_ServiceCollecteurSignataireFonction").asText()); - assertEquals(MeshuggahCtxExamples.ctx_serviceCollecteurSignataireNom,actualBody.path("Enq_ServiceCollecteurSignataireNom").asText()); - assertEquals(MeshuggahCtxExamples.ctx_themeMieuxConnaitreMail,actualBody.path("Enq_ThemeMieuxConnaitreMail").asText()); - assertEquals(MeshuggahCtxExamples.ctx_urlEnquete,actualBody.path("Enq_UrlEnquete").asText()); - assertEquals(MeshuggahCtxExamples.ctx_boiteRetour,actualBody.path("Mail_BoiteRetour").asText()); - assertEquals(MeshuggahCtxExamples.ctx_objetMail,actualBody.path("Mail_Objet").asText()); - } - assertEquals(1,nbOuverturePart1,"Wrong number of opening for partition 1"); - assertEquals(1,nbOuverturePart2,"Wrong number of opening for partition 2"); - assertEquals(1,nbRelancePart1,"Wrong number of relance for partition 1"); - assertEquals(1,nbRelancePart2,"Wrong number of relance for partition 2"); - - } - -} \ No newline at end of file diff --git a/src/test/java/fr/insee/protools/backend/service/meshuggah/MeshuggahCtxExamples.java b/src/test/java/fr/insee/protools/backend/service/meshuggah/MeshuggahCtxExamples.java deleted file mode 100644 index 6551dec4..00000000 --- a/src/test/java/fr/insee/protools/backend/service/meshuggah/MeshuggahCtxExamples.java +++ /dev/null @@ -1,330 +0,0 @@ -package fr.insee.protools.backend.service.meshuggah; - -import fr.insee.protools.backend.service.utils.data.CtxExamples; - -public class MeshuggahCtxExamples { - - static final Long ctx_partition1 = 99L; - static final Long ctx_partition2 = 100L; - //Values - //static final String ctx_minTutelle = "MIN_TUT"; - static final String ctx_complementConnexion = "COMP_CONNEXION"; - static final String ctx_logoPrestataire = "LOGO_PRESTA"; - static final String ctx_mailResponsableOperationnel = "contact@insee.fr"; - static final Boolean ctx_prestataire = Boolean.FALSE; - - static final String ctx_relanceLibreMailParagraphe1 ="ligne1"; - static final String ctx_relanceLibreMailParagraphe1_partition2_com1 ="ligne1_partition2_com1"; - static final String ctx_relanceLibreMailParagraphe1_partition2_com2 ="ligne1_partition2_com2"; - - static final String ctx_relanceLibreMailParagraphe2 ="ligne2"; - static final String ctx_relanceLibreMailParagraphe3 ="ligne3"; - static final String ctx_relanceLibreMailParagraphe4 ="ligne4"; - static final String ctx_responsableOperationnel="Mr X"; - static final String ctx_responsableTraitement="l'Insee"; - static final String ctx_themeMieuxConnaitreMail="les familles"; - static final String ctx_serviceCollecteurSignataireFonction="La directrice des statistiques démographiques et sociales de l’Insee"; - static final String ctx_serviceCollecteurSignataireNom="Mme XXX"; - static final String ctx_urlEnquete="https://toto.insee.fr/"; - static final String ctx_boiteRetour="toto.toto@insee.fr"; - static final String ctx_objetMail="Insee - enquêtes XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; - - static final String ctx_OK_1part_ouverture_courrier= - """ - { - "id": "AAC2023A00", - "metadonnees": { - "ministereTutelle": "MIN_TUT", - "responsableOperationnel": "Mr X", - "responsableTraitement": "l'Insee", - "mailBoiteRetour": "toto.toto@insee.fr", - "urlEnquete": "https://toto.insee.fr/", - "themeMieuxConnaitreMail": "les familles", - "serviceCollecteurSignataireFonction": "La directrice des statistiques démographiques et sociales de l’Insee", - "serviceCollecteurSignataireNom": "Mme XXX", - "prestataire": false, - "mailResponsableOperationnel": "contact@insee.fr", - "logoPrestataire": "LOGO_PRESTA" - }, - "partitions": [{ - "id": 99, - "communications" :[ - { - "moyenCommunication" : "courrier", - "phaseCommunication" : "ouverture", - "avecQuestionnairePapier" : false, - "protocole" : null, - "mode" : "web", - "typeModele" : "relance_libre", - "objetMail" : "Insee - enquêtes XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", - "relanceLibreMailParagraphe1" : "ligne1", - "relanceLibreMailParagraphe2" : "ligne2", - "relanceLibreMailParagraphe3" : "ligne3", - "relanceLibreMailParagraphe4" : "ligne4", - "complementConnexion" : "COMP_CONNEXION", - "echeances" : ["J+0"] - } - ] - }] - } - """; - - - static final String ctx_OK_2partitions_2com_ouverture_relance_ok= - """ - { - "id": "AAC2023A00", - "metadonnees": { - "ministereTutelle": "MIN_TUT", - "responsableOperationnel": "Mr X", - "responsableTraitement": "l'Insee", - "mailBoiteRetour": "toto.toto@insee.fr", - "urlEnquete": "https://toto.insee.fr/", - "themeMieuxConnaitreMail": "les familles", - "serviceCollecteurSignataireFonction": "La directrice des statistiques démographiques et sociales de l’Insee", - "serviceCollecteurSignataireNom": "Mme XXX", - "prestataire": false, - "mailResponsableOperationnel": "contact@insee.fr", - "logoPrestataire": "LOGO_PRESTA" - }, - "partitions": [{ - "id": 99, - "communications" :[ - { - "moyenCommunication" : "courrier", - "phaseCommunication" : "ouverture", - "avecQuestionnairePapier" : false, - "protocole" : null, - "mode" : "web", - "typeModele" : "relance_libre", - "objetMail" : "Insee - enquêtes XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", - "relanceLibreMailParagraphe1" : "ligne1", - "relanceLibreMailParagraphe2" : "ligne2", - "relanceLibreMailParagraphe3" : "ligne3", - "relanceLibreMailParagraphe4" : "ligne4", - "complementConnexion" : "COMP_CONNEXION", - "echeances" : ["J+0"] - }, - { - "moyenCommunication" : "mail", - "phaseCommunication" : "relance", - "avecQuestionnairePapier" : false, - "protocole" : null, - "mode" : "web", - "typeModele" : "relance_libre", - "objetMail" : "Insee - enquêtes XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", - "relanceLibreMailParagraphe1" : "ligne1", - "relanceLibreMailParagraphe2" : "ligne2", - "relanceLibreMailParagraphe3" : "ligne3", - "relanceLibreMailParagraphe4" : "ligne4", - "complementConnexion" : "COMP_CONNEXION", - "echeances" : ["J+15"] - } - ] - }, - { - "id": 100, - "communications" :[ - { - "moyenCommunication" : "courrier", - "phaseCommunication" : "ouverture", - "avecQuestionnairePapier" : false, - "protocole" : null, - "mode" : "web", - "typeModele" : "relance_libre", - "objetMail" : "Insee - enquêtes XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", - "relanceLibreMailParagraphe1" : "ligne1_partition2_com1", - "relanceLibreMailParagraphe2" : "ligne2", - "relanceLibreMailParagraphe3" : "ligne3", - "relanceLibreMailParagraphe4" : "ligne4", - "complementConnexion" : "COMP_CONNEXION", - "echeances" : ["J+0"] - }, - { - "moyenCommunication" : "mail", - "phaseCommunication" : "relance", - "avecQuestionnairePapier" : false, - "protocole" : null, - "mode" : "web", - "typeModele" : "relance_libre", - "objetMail" : "Insee - enquêtes XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", - "relanceLibreMailParagraphe1" : "ligne1_partition2_com2", - "relanceLibreMailParagraphe2" : "ligne2", - "relanceLibreMailParagraphe3" : "ligne3", - "relanceLibreMailParagraphe4" : "ligne4", - "complementConnexion" : "COMP_CONNEXION", - "echeances" : ["J+15"] - } - ] - } - ] - } - """; - - static final String ctx_OK_envoi_mail_1part_ouverture_mail= - """ - { - "id": "AAC2023A00", - "partitions": [{ - "id": 99, - "communications" :[ - { - "moyenCommunication" : "mail", - "phaseCommunication" : "ouverture", - "avecQuestionnairePapier" : false, - "protocole" : null, - "mode" : "web", - "typeModele" : "relance_libre" - } - ] - }] - } - """; - - - //CTX ERROR - static final String ctx_ERROR_no_part = CtxExamples.ctx_no_part; - - static final String ctx_ERROR_no_com = CtxExamples.ctx_idCampagne_idPartition; - - static final String ctx_ERROR_no_moyen = - """ - { - "id": "AAC2023A00", - "partitions": [{ - "id": 99, - "communications" :[ - { - "phaseCommunication" : "ouverture", - "avecQuestionnairePapier" : false, - "protocole" : null, - "mode" : "web", - "typeModele" : "relance_libre" - } - ] - }] - } - """; - - static final String ctx_ERROR_typo_phase= - """ - { - "id": "AAC2023A00", - "partitions": [{ - "id": 99, - "communications" :[ - { - "moyenCommunication" : "mail", - "phaseCommunication" : "ouvertureeee", - "avecQuestionnairePapier" : false, - "protocole" : null, - "mode" : "web", - "typeModele" : "relance_libre" - } - ] - }] - } - """; - - static final String ctx_ERROR_typo_moyen= - """ - { - "id": "AAC2023A00", - "partitions": [{ - "id": 99, - "communications" :[ - { - "moyenCommunication" : "email", - "phaseCommunication" : "ouverture", - "avecQuestionnairePapier" : false, - "protocole" : null, - "mode" : "web", - "typeModele" : "relance_libre" - } - ] - }] - } - """; - - static final String ctx_ERROR_1partitions_2com_1_typo_moyen= - """ - { - "id": "AAC2023A00", - "partitions": [{ - "id": 99, - "communications" :[ - { - "moyenCommunication" : "mail", - "phaseCommunication" : "relance", - "avecQuestionnairePapier" : false, - "protocole" : null, - "mode" : "web", - "typeModele" : "relance_libre" - }, - { - "moyenCommunication" : "xxxxxxxx", - "phaseCommunication" : "ouverture", - "avecQuestionnairePapier" : false, - "protocole" : null, - "mode" : "web", - "typeModele" : "relance_libre" - } - ] - }] - } - """; - - - static final String ctx_ERROR_2partitions_2com_1_typo_phase= - """ - { - "id": "AAC2023A00", - "partitions": [{ - "id": 99, - "communications" :[ - { - "moyenCommunication" : "mail", - "phaseCommunication" : "relance", - "avecQuestionnairePapier" : false, - "protocole" : null, - "mode" : "web", - "typeModele" : "relance_libre" - }, - { - "moyenCommunication" : "courrier", - "phaseCommunication" : "relance", - "avecQuestionnairePapier" : false, - "protocole" : null, - "mode" : "web", - "typeModele" : "relance_libre" - } - ] - }, - { - "id": 100, - "communications" :[ - { - "moyenCommunication" : "mail", - "phaseCommunication" : "relance", - "avecQuestionnairePapier" : false, - "protocole" : null, - "mode" : "web", - "typeModele" : "relance_libre" - }, - { - "moyenCommunication" : "courrier", - "phaseCommunication" : "xxxxxxxxxx", - "avecQuestionnairePapier" : false, - "protocole" : null, - "mode" : "web", - "typeModele" : "relance_libre" - } - ] - } - ] - } - """; - - private MeshuggahCtxExamples(){} - -} diff --git a/src/test/java/fr/insee/protools/backend/service/meshuggah/MeshuggahSendOpeningMailCommunicationForSUTaskTest.java b/src/test/java/fr/insee/protools/backend/service/meshuggah/MeshuggahSendOpeningMailCommunicationForSUTaskTest.java deleted file mode 100644 index c8558443..00000000 --- a/src/test/java/fr/insee/protools/backend/service/meshuggah/MeshuggahSendOpeningMailCommunicationForSUTaskTest.java +++ /dev/null @@ -1,148 +0,0 @@ -package fr.insee.protools.backend.service.meshuggah; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ObjectNode; -import fr.insee.protools.backend.ProtoolsTestUtils; -import fr.insee.protools.backend.service.context.exception.BadContextIncorrectBPMNError; -import fr.insee.protools.backend.dto.meshuggah.MeshuggahComDetails; -import fr.insee.protools.backend.service.utils.TestWithContext; -import org.flowable.common.engine.api.FlowableIllegalArgumentException; -import org.flowable.engine.delegate.DelegateExecution; -import org.flowable.engine.test.FlowableTest; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; -import org.mockito.ArgumentCaptor; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.Mockito; - -import java.util.stream.Stream; - -import static fr.insee.protools.backend.service.FlowableVariableNameConstants.VARNAME_CURRENT_PARTITION_ID; -import static fr.insee.protools.backend.service.FlowableVariableNameConstants.VARNAME_PLATINE_CONTACT; -import static fr.insee.protools.backend.service.utils.FlowableVariableUtils.getMissingVariableMessage; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.*; - -@FlowableTest -class MeshuggahSendOpeningMailCommunicationForSUTaskTest extends TestWithContext { - static ObjectMapper objectMapper = new ObjectMapper(); - - private final String platineContactContent = """ - { - "email": "toto@insee.fr", - "identifier": "id" - } - """; - - private static Stream contextErrorArguments() { - return Stream.of( - Arguments.of(MeshuggahCtxExamples.ctx_ERROR_no_part), - Arguments.of(MeshuggahCtxExamples.ctx_ERROR_no_com), - Arguments.of(MeshuggahCtxExamples.ctx_ERROR_no_moyen), - Arguments.of(MeshuggahCtxExamples.ctx_ERROR_typo_phase), - Arguments.of(MeshuggahCtxExamples.ctx_ERROR_typo_moyen)); - } - - @Test - void execute_should_throwError_when_null_context(){ - assertThat_delegate_throwError_when_null_context(meshuggahTask); - } - - @Mock MeshuggahService meshuggahService; - @InjectMocks MeshuggahSendOpeningMailCommunicationForSUTask meshuggahTask; - - @Test - @DisplayName("Test execute method - should throw if VARNAME_CURRENT_PARTITION_ID or VARNAME_PLATINE_CONTACT not initialized") - void execute_should_throw_FlowableIllegalArgumentException_when_variables_notDefined() throws JsonProcessingException { - - //Precondition - DelegateExecution execution = mock(DelegateExecution.class); - lenient().when(execution.getProcessInstanceId()).thenReturn(dumyId); - initContexteMockWithString(MeshuggahCtxExamples.ctx_OK_envoi_mail_1part_ouverture_mail); - - //Execute the unit under test - FlowableIllegalArgumentException exception = assertThrows(FlowableIllegalArgumentException.class, () -> meshuggahTask.execute(execution)); - //Post conditions - assertThat(exception.getMessage()).isEqualTo(getMissingVariableMessage(VARNAME_CURRENT_PARTITION_ID)); - - //Create First variable - when(execution.getVariable(VARNAME_CURRENT_PARTITION_ID, Long.class)).thenReturn(99L); - //Execute again - exception = assertThrows(FlowableIllegalArgumentException.class, () -> meshuggahTask.execute(execution)); - //Check the error - assertThat(exception.getMessage()).isEqualTo(getMissingVariableMessage(VARNAME_PLATINE_CONTACT)); - - //Create 2nd variable - when(execution.getVariable(VARNAME_PLATINE_CONTACT, JsonNode.class)).thenReturn(objectMapper.readTree(platineContactContent)); - //Execute again - assertDoesNotThrow(() -> meshuggahTask.execute(execution)); - } - - @ParameterizedTest - @MethodSource("contextErrorArguments") - @DisplayName("Test execute method - should throw if Context is not correct") - void execute_should_throw_BadContext_when_contextIncorrect(String context_json) throws JsonProcessingException { - //Precondition - DelegateExecution execution = mock(DelegateExecution.class); - lenient().when(execution.getProcessInstanceId()).thenReturn(dumyId); - //Variables - lenient().when(execution.getVariable(VARNAME_CURRENT_PARTITION_ID, Long.class)).thenReturn(MeshuggahCtxExamples.ctx_partition1); - lenient().when(execution.getVariable(VARNAME_PLATINE_CONTACT, JsonNode.class)).thenReturn(objectMapper.readTree(platineContactContent)); - //Ctx - ProtoolsTestUtils.initContexteMockFromString(protoolsContext, context_json); - - - //Run test - assertThrows(BadContextIncorrectBPMNError.class, () -> meshuggahTask.execute(execution)); - Mockito.reset(protoolsContext); - } - - @Test - @DisplayName("Test execute method - should work and make correct call to service") - void execute_should_work_when_variables_OK() throws JsonProcessingException { - //Precondition - DelegateExecution execution = mock(DelegateExecution.class); - lenient().when(execution.getProcessInstanceId()).thenReturn(dumyId); - initContexteMockWithString(MeshuggahCtxExamples.ctx_OK_envoi_mail_1part_ouverture_mail); - - when(execution.getVariable(VARNAME_CURRENT_PARTITION_ID, Long.class)).thenReturn(MeshuggahCtxExamples.ctx_partition1); - JsonNode platineContact = objectMapper.readTree(platineContactContent); - when(execution.getVariable(VARNAME_PLATINE_CONTACT, JsonNode.class)).thenReturn(platineContact); - //Run method under test - assertDoesNotThrow(() -> meshuggahTask.execute(execution)); - - //Post conditions - MeshuggahComDetails expectedDetails = MeshuggahComDetails.builder() - .campaignId("AAC2023A00") - .phase("OUVERTURE") - .medium("EMAIL") - .mode("WEB") - .partitioningId(MeshuggahCtxExamples.ctx_partition1.toString()) - .avecQuestionnaire(false) - .protocol("DEFAULT") - .operation("RELANCE_LIBRE") - .build(); - - ObjectNode expectedBody = objectMapper.createObjectNode(); - expectedBody.put("email", platineContact.path("email")); - expectedBody.put("Ue_CalcIdentifiant", platineContact.path("identifier")); - - - ArgumentCaptor acDetails = ArgumentCaptor.forClass(MeshuggahComDetails.class); - ArgumentCaptor acBody = ArgumentCaptor.forClass(JsonNode.class); - verify(meshuggahService,times(1)).postSendCommunication(acDetails.capture(),acBody.capture()); - MeshuggahComDetails details = acDetails.getValue(); - assertEquals(expectedDetails,details); - - JsonNode resultBody = acBody.getValue(); - assertEquals(expectedBody,resultBody); - - } -} \ No newline at end of file diff --git a/src/test/java/fr/insee/protools/backend/service/platine/delegate/PlatinePilotageCreateContextTaskTest.java b/src/test/java/fr/insee/protools/backend/service/platine/delegate/PlatinePilotageCreateContextTaskTest.java deleted file mode 100644 index 07605cce..00000000 --- a/src/test/java/fr/insee/protools/backend/service/platine/delegate/PlatinePilotageCreateContextTaskTest.java +++ /dev/null @@ -1,77 +0,0 @@ -package fr.insee.protools.backend.service.platine.delegate; - -import fr.insee.protools.backend.service.context.exception.BadContextIncorrectBPMNError; -import fr.insee.protools.backend.service.platine.pilotage.PlatinePilotageService; -import fr.insee.protools.backend.service.platine.pilotage.metadata.MetadataDto; -import fr.insee.protools.backend.service.utils.TestWithContext; -import org.flowable.engine.delegate.DelegateExecution; -import org.flowable.engine.test.FlowableTest; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.ArgumentCaptor; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; -import org.springframework.util.ClassUtils; - -import java.util.List; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.*; - -@ExtendWith(MockitoExtension.class) -@FlowableTest -class PlatinePilotageCreateContextTaskTest extends TestWithContext { - final static String ressourceFolder = ClassUtils.convertClassNameToResourcePath(PlatineQuestionnaireCreateContextTaskTest.class.getPackageName()); - final static String platine_context_json = ressourceFolder+"/protools-contexte-platine-individu.json"; - - - @Mock PlatinePilotageService platinePilotageService; - @InjectMocks PlatinePilotageCreateContextTask platinePilotageTask; - - - @Test - void execute_should_throwError_when_null_context(){ - assertThat_delegate_throwError_when_null_context(platinePilotageTask); - } - - @Test - void execute_should_throw_BadContextIncorrectException_when_noContext() { - DelegateExecution execution = createMockedExecution(); - - //Execute the unit under test - assertThrows(BadContextIncorrectBPMNError.class,() -> platinePilotageTask.execute(execution)); - } - - @Test - void execute_should_work_when_contextOK() { - DelegateExecution execution = createMockedExecution(); - initContexteMockWithFile(platine_context_json); - String partitionId="1"; - String campaignId="DEM2022X00"; - - //Execute the unit under test - platinePilotageTask.execute(execution); - - //Post conditions : Exactly one call to post platinePilotageService.putMetadata - // it is one call per partition defined in context -// verify(platinePilotageService,times(1)).putMetadata(eq(partitionId), notNull()); - - - //Verify postCampaign - ArgumentCaptor acMetadataDto = ArgumentCaptor.forClass(MetadataDto.class); - verify(platinePilotageService,times(1)).putMetadata(eq(campaignId+partitionId),acMetadataDto.capture()); - List allValues = acMetadataDto.getAllValues(); - assertEquals(1, allValues.size(),"We should have exactly one partition"); -//TODO - // MetadataDto expectedMetadataNode = ProtoolsTestUtils.asObject(ressourceFolder + "/expected_post_questionnaire_metadata.json", MetadataDto.class); - // assertEquals(expectedMetadataNode,allValues.get(0).getMetadata(),"Erreur with generated Metadata"); - assertEquals("DEM2022X00",allValues.get(0).getCampaignDto().getId(),"Erreur with generated Metadata campaign id"); - assertEquals("DEM2022X001",allValues.get(0).getPartitioningDto().getId(),"Erreur with generated Metadata partition id"); - assertEquals("DEM2022",allValues.get(0).getSurveyDto().getId(),"Erreur with generated Metadata partition id"); - assertEquals("proprietaireId",allValues.get(0).getOwnerDto().getId(),"Erreur with generated Metadata owner id"); - assertEquals("assistanceNiveau2Id",allValues.get(0).getSupportDto().getId(),"Erreur with generated Metadata support id"); - } - -} diff --git a/src/test/java/fr/insee/protools/backend/service/platine/delegate/PlatinePilotageCreateSurveyUnitTaskTest.java b/src/test/java/fr/insee/protools/backend/service/platine/delegate/PlatinePilotageCreateSurveyUnitTaskTest.java deleted file mode 100644 index 7824c22b..00000000 --- a/src/test/java/fr/insee/protools/backend/service/platine/delegate/PlatinePilotageCreateSurveyUnitTaskTest.java +++ /dev/null @@ -1,174 +0,0 @@ -package fr.insee.protools.backend.service.platine.delegate; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.ObjectNode; -import fr.insee.protools.backend.ProtoolsTestUtils; -import fr.insee.protools.backend.service.context.ContextConstants; -import fr.insee.protools.backend.service.context.exception.BadContextIncorrectBPMNError; -import fr.insee.protools.backend.service.exception.IncorrectSUBPMNError; -import fr.insee.protools.backend.service.platine.pilotage.PlatinePilotageService; -import fr.insee.protools.backend.dto.platine.pilotage.PlatinePilotageGenderType; -import fr.insee.protools.backend.dto.platine.pilotage.query.QuestioningWebclientDto; -import fr.insee.protools.backend.service.rem.RemDtoUtils; -import fr.insee.protools.backend.dto.rem.PersonDto; -import fr.insee.protools.backend.dto.rem.REMSurveyUnitDto; -import fr.insee.protools.backend.service.utils.TestWithContext; -import fr.insee.protools.backend.service.utils.data.RemSUData; -import org.flowable.engine.delegate.DelegateExecution; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; -import org.mockito.ArgumentCaptor; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.springframework.util.ClassUtils; - -import java.util.stream.Stream; - -import static fr.insee.protools.backend.service.FlowableVariableNameConstants.*; -import static fr.insee.protools.backend.service.platine.utils.PlatineHelper.computePilotagePartitionID; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.*; - -class PlatinePilotageCreateSurveyUnitTaskTest extends TestWithContext { - - final static String ressourceFolder = ClassUtils.convertClassNameToResourcePath(PlatinePilotageCreateSurveyUnitTaskTest.class.getPackageName()); - - @Mock - PlatinePilotageService platinePilotageService; - - @InjectMocks - PlatinePilotageCreateSurveyUnitTask platinePilotageTask; - - - final static String platine_context_json = ressourceFolder+"/protools-contexte-platine-individu.json"; - final static String platine_context_logement_json = ressourceFolder+"/protools-contexte-platine-individu.json"; - - @Test - void execute_should_throwError_when_null_context(){ - assertThat_delegate_throwError_when_null_context(platinePilotageTask); - } - - //To be able to run tests with differents protools contexts - private static Stream protoolsContextArguments() { - return Stream.of( - Arguments.of(platine_context_json), - Arguments.of(platine_context_logement_json) - ); - } - - - @Test - void execute_should_throw_BadContextIncorrectException_when_noContext() { - DelegateExecution execution=createMockedExecution(); - //Execute the unit under test - assertThrows(BadContextIncorrectBPMNError.class,() -> platinePilotageTask.execute(execution)); - } - - @ParameterizedTest - @MethodSource("protoolsContextArguments") - void execute_should_work_when_ContextOK(String context_json) { - //Prepare - DelegateExecution execution=createMockedExecution(); - JsonNode contextRootNode = initContexteMockWithFile(context_json); - JsonNode remSU = ProtoolsTestUtils.asJsonNode(RemSUData.rem_su_3personnes); - Long idPArtition=1l; - lenient().doReturn(idPArtition).when(execution).getVariable(VARNAME_CURRENT_PARTITION_ID,Long.class); - lenient().doReturn(remSU).when(execution).getVariable(VARNAME_REM_SURVEY_UNIT,JsonNode.class); - lenient().doReturn("TOTO").when(execution).getVariable(VARNAME_DIRECTORYACCESS_ID_CONTACT,String.class); - - //Execute the unit under test - platinePilotageTask.execute(execution); - - //Post Conditions - ArgumentCaptor acQuestionningDto = ArgumentCaptor.forClass(QuestioningWebclientDto.class); - verify(platinePilotageService,times(1)).putQuestionings(acQuestionningDto.capture()); - QuestioningWebclientDto valueParam = acQuestionningDto.getValue(); - assertEquals("tic2023a00_web", valueParam.getModelName(),"Bad Questionnaire model"); - assertEquals(1, valueParam.getContacts().size(),"Expected exactly one contact"); - assertEquals("TOBEFOUND", valueParam.getContacts().get(0).getFirstName(),"Wrong contact found"); - - String campagneId=contextRootNode.path(ContextConstants.CTX_CAMPAGNE_ID).asText(); - assertEquals(computePilotagePartitionID(campagneId,idPArtition), valueParam.getIdPartitioning(),"Wrong Partition ID"); - assertEquals("3043280", valueParam.getSurveyUnit().getIdSu(),"Wrong ID SU (repository id)"); - } - - void findContact_should_return_CorrectContact(String suTestFilePath, boolean isLogement, boolean shouldThrow){ - //Prepare - JsonNode remSU = ProtoolsTestUtils.asJsonNode(suTestFilePath); - REMSurveyUnitDto dto = ProtoolsTestUtils.asObject(suTestFilePath,REMSurveyUnitDto.class); - - if(!shouldThrow) { - //Execute - PersonDto contact = RemDtoUtils.findContact(remSU,dto,isLogement); - //Found the right contact - assertEquals("TOBEFOUND", contact.getFirstName()); - } - else{ - //Execute the unit under test - assertThrows(IncorrectSUBPMNError.class,() -> RemDtoUtils.findContact(remSU,dto,isLogement)); - } - } - - @Test - void findContact_should_return_CorrectContactForLogement() { - findContact_should_return_CorrectContact(RemSUData.rem_su_1personne,true,false); - findContact_should_return_CorrectContact(RemSUData.rem_su_1personne,false,false); - findContact_should_return_CorrectContact(RemSUData.rem_su_3personnes,true,false); - findContact_should_return_CorrectContact(RemSUData.rem_su_3personnes,false,false); - findContact_should_return_CorrectContact(RemSUData.getRem_su_1personne_noContact,false,true); - findContact_should_return_CorrectContact(RemSUData.getRem_su_1personne_noContact,true,true); - } - - - @Test - @DisplayName("convertREMGenderToPlatineCivility should return Female when param '2' ; 'Male' when param is '1' and Undefined in other cases") - void convertREMGenderToPlatineCivility_should_ReturnCorrectValues() { - assertThat(PlatinePilotageCreateSurveyUnitTask.convertREMGenderToPlatineCivility("2")).isEqualTo(PlatinePilotageGenderType.Female); - assertThat(PlatinePilotageCreateSurveyUnitTask.convertREMGenderToPlatineCivility("1")).isEqualTo(PlatinePilotageGenderType.Male); - assertThat(PlatinePilotageCreateSurveyUnitTask.convertREMGenderToPlatineCivility("22")).isEqualTo(PlatinePilotageGenderType.Undefined); - assertThat(PlatinePilotageCreateSurveyUnitTask.convertREMGenderToPlatineCivility(" 2")).isEqualTo(PlatinePilotageGenderType.Undefined); - assertThat(PlatinePilotageCreateSurveyUnitTask.convertREMGenderToPlatineCivility(" 2 ")).isEqualTo(PlatinePilotageGenderType.Undefined); - assertThat(PlatinePilotageCreateSurveyUnitTask.convertREMGenderToPlatineCivility("3")).isEqualTo(PlatinePilotageGenderType.Undefined); - assertThat(PlatinePilotageCreateSurveyUnitTask.convertREMGenderToPlatineCivility("23JZKEOSJF")).isEqualTo(PlatinePilotageGenderType.Undefined); - assertThat(PlatinePilotageCreateSurveyUnitTask.convertREMGenderToPlatineCivility("0")).isEqualTo(PlatinePilotageGenderType.Undefined); - assertThat(PlatinePilotageCreateSurveyUnitTask.convertREMGenderToPlatineCivility("-1")).isEqualTo(PlatinePilotageGenderType.Undefined); - assertThat(PlatinePilotageCreateSurveyUnitTask.convertREMGenderToPlatineCivility("-2")).isEqualTo(PlatinePilotageGenderType.Undefined); - assertThat(PlatinePilotageCreateSurveyUnitTask.convertREMGenderToPlatineCivility("& ukdslw,kvlk,l")).isEqualTo(PlatinePilotageGenderType.Undefined); - } - - @Test - @DisplayName("getPlatineLastname should return lastname if not null else return birthname if not null else return empty string") - void getPlatineLastname_should_work(){ - String lastname="lastname"; - String birthname="birthname"; - assertThat(PlatinePilotageCreateSurveyUnitTask.getPlatineLastname(lastname,birthname)).isEqualTo(lastname); - assertThat(PlatinePilotageCreateSurveyUnitTask.getPlatineLastname(null,birthname)).isEqualTo(birthname); - assertThat(PlatinePilotageCreateSurveyUnitTask.getPlatineLastname(lastname,null)).isEqualTo(lastname); - assertThat(PlatinePilotageCreateSurveyUnitTask.getPlatineLastname(null,null)).isEmpty(); - - } - - - @Test - @DisplayName("Should throw if REM SU Json is invalid") - void execute_should_throw_IncorrectSUException_when_wrongSU() { - DelegateExecution execution=createMockedExecution(); - initContexteMockWithFile(platine_context_json); - JsonNode remSU = ProtoolsTestUtils.asJsonNode(RemSUData.rem_su_3personnes); - //Break this node - ((ObjectNode) remSU).remove("repositoryId"); - Long idPartition=1l; - lenient().doReturn(idPartition).when(execution).getVariable(VARNAME_CURRENT_PARTITION_ID,Long.class); - lenient().doReturn(remSU).when(execution).getVariable(VARNAME_REM_SURVEY_UNIT,JsonNode.class); - lenient().doReturn("TOTO").when(execution).getVariable(VARNAME_DIRECTORYACCESS_ID_CONTACT,String.class); - - - //Execute the unit under test - assertThrows(IncorrectSUBPMNError.class,() -> platinePilotageTask.execute(execution)); - } -} \ No newline at end of file diff --git a/src/test/java/fr/insee/protools/backend/service/platine/delegate/PlatinePilotageGetSUContactTaskTest.java b/src/test/java/fr/insee/protools/backend/service/platine/delegate/PlatinePilotageGetSUContactTaskTest.java deleted file mode 100644 index 43ab2858..00000000 --- a/src/test/java/fr/insee/protools/backend/service/platine/delegate/PlatinePilotageGetSUContactTaskTest.java +++ /dev/null @@ -1,147 +0,0 @@ -package fr.insee.protools.backend.service.platine.delegate; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import fr.insee.protools.backend.service.context.exception.BadContextIncorrectBPMNError; -import fr.insee.protools.backend.service.platine.pilotage.PlatinePilotageService; -import fr.insee.protools.backend.dto.platine.pilotage.contact.PlatineContactDto; -import fr.insee.protools.backend.service.platine.utils.PlatineHelper; -import fr.insee.protools.backend.service.rem.delegate.ExtractContactIdentifierFromREMSUTask; -import fr.insee.protools.backend.service.utils.TestWithContext; -import org.flowable.common.engine.api.FlowableIllegalArgumentException; -import org.flowable.engine.delegate.DelegateExecution; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.springframework.util.ClassUtils; - -import static fr.insee.protools.backend.service.FlowableVariableNameConstants.*; -import static fr.insee.protools.backend.service.context.ContextConstants.CTX_CAMPAGNE_ID; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.*; - -class PlatinePilotageGetSUContactTaskTest extends TestWithContext { - final static String ressourceFolder = ClassUtils.convertClassNameToResourcePath(PlatinePilotageGetSUContactTaskTest.class.getPackageName()); - final static String platine_context_json = ressourceFolder + "/protools-contexte-platine-individu.json"; - final static String platine_context_incorrect_json = ressourceFolder + "/protools-contexte-platine-incorrect-no-campaign-id.json"; - - @Mock PlatinePilotageService platinePilotageService; - @InjectMocks PlatinePilotageGetSUContactTask platinePilotageTask; - - @Test - void execute_should_throwError_when_null_context(){ - assertThat_delegate_throwError_when_null_context(platinePilotageTask); - } - - @Test - void execute_should_throw_BadContextIncorrectException_when_noContext() { - DelegateExecution execution = createMockedExecution(); - //Execute the unit under test - assertThrows(BadContextIncorrectBPMNError.class, () -> platinePilotageTask.execute(execution)); - } - - @Test - void execute_should_throw_BadContextIncorrectException_when_CampaignId_missing() { - DelegateExecution execution = createMockedExecution(); - initContexteMockWithFile(platine_context_incorrect_json); - - //Execute the unit under test - assertThrows(BadContextIncorrectBPMNError.class, () -> platinePilotageTask.execute(execution)); - } - - @Test - @DisplayName("PlatinePilotageGetSUContactTaskTest should throw an exception when the VARNAME_REM_SURVEY_UNIT_IDENTIFIER variable is missing or has wrong type") - void execute_should_throw_when_variable1_missing() { - //Prepare - DelegateExecution execution = createMockedExecution(); - ExtractContactIdentifierFromREMSUTask extractTask = new ExtractContactIdentifierFromREMSUTask(); - //set the 2nd variable correctly - lenient().doReturn(999L).when(execution).getVariable(VARNAME_CURRENT_PARTITION_ID, Long.class); - - - //No variable set ==> Error - assertThrows(FlowableIllegalArgumentException.class, () -> extractTask.execute(execution)); - - //Wrong Type ==> Error - lenient().doReturn(Boolean.FALSE).when(execution).getVariable(VARNAME_REM_SURVEY_UNIT_IDENTIFIER, Boolean.class); - assertThrows(FlowableIllegalArgumentException.class, () -> extractTask.execute(execution)); - } - - @Test - @DisplayName("PlatinePilotageGetSUContactTaskTest should throw an exception when the VARNAME_CURRENT_PARTITION_ID variable is missing or has wrong type") - void execute_should_throw_when_variable2_missing() { - //Prepare - DelegateExecution execution = createMockedExecution(); - ExtractContactIdentifierFromREMSUTask extractTask = new ExtractContactIdentifierFromREMSUTask(); - //set the 2nd variable correctly - lenient().doReturn(12L).when(execution).getVariable(VARNAME_REM_SURVEY_UNIT_IDENTIFIER, Long.class); - - - //No variable set ==> Error - assertThrows(FlowableIllegalArgumentException.class, () -> extractTask.execute(execution)); - - //Wrong Type ==> Error - lenient().doReturn(Boolean.FALSE).when(execution).getVariable(VARNAME_CURRENT_PARTITION_ID, Boolean.class); - assertThrows(FlowableIllegalArgumentException.class, () -> extractTask.execute(execution)); - } - - @Test - @DisplayName("PlatinePilotageGetSUContactTaskTest should throw an exception when the VARNAME_CURRENT_PARTITION_ID and VARNAME_CURRENT_PARTITION_ID variable are missing or have wrong type") - void execute_should_throw_when_variable1and2_missing() { - //Prepare - DelegateExecution execution = createMockedExecution(); - ExtractContactIdentifierFromREMSUTask extractTask = new ExtractContactIdentifierFromREMSUTask(); - - //No variable set ==> Error - assertThrows(FlowableIllegalArgumentException.class, () -> extractTask.execute(execution)); - - //Wrong Type ==> Error - lenient().doReturn(Boolean.FALSE).when(execution).getVariable(VARNAME_CURRENT_PARTITION_ID, Boolean.class); - lenient().doReturn(Boolean.TRUE).when(execution).getVariable(VARNAME_REM_SURVEY_UNIT_IDENTIFIER, Boolean.class); - - - assertThrows(FlowableIllegalArgumentException.class, () -> extractTask.execute(execution)); - } - - - @Test - void execute_should_work_when_context_and_variables_OK() throws JsonProcessingException { - DelegateExecution execution = createMockedExecution(); - JsonNode contextRootNode = initContexteMockWithFile(platine_context_json); - //Prepare parent - DelegateExecution executionParent = mock(DelegateExecution.class); - doReturn(executionParent).when(execution).getParent(); - //Process variables - Long suId = 20231110L; - Long currentPartitionID = 120883L; - lenient().doReturn(currentPartitionID).when(execution).getVariable(VARNAME_CURRENT_PARTITION_ID, Long.class); - lenient().doReturn(suId).when(execution).getVariable(VARNAME_REM_SURVEY_UNIT_IDENTIFIER, Long.class); - - //Prepare service response from platine - PlatineContactDto contactDto = PlatineContactDto.builder().identifier("55").build(); - doReturn(contactDto).when(platinePilotageService).getSUMainContact(any(),any()); - - - //Execute the unit under test - assertDoesNotThrow(() -> platinePilotageTask.execute(execution)); - - //Post conditions : - // 1 : Exactly one call to post platinePilotageService.getSUMainContact with correct parameters - String platinePartitionId = PlatineHelper.computePilotagePartitionID(contextRootNode.path(CTX_CAMPAGNE_ID).asText(), currentPartitionID); - verify(platinePilotageService, times(1)).getSUMainContact(suId, platinePartitionId); - //2 : VARNAME_PLATINE_CONTACT has been set to correct value - ArgumentCaptor acVariableValue = ArgumentCaptor.forClass(JsonNode.class); - ArgumentCaptor acVariableKey = ArgumentCaptor.forClass(String.class); - - verify(executionParent, times(1)).setVariableLocal(acVariableKey.capture(),acVariableValue.capture()); - assertEquals(VARNAME_PLATINE_CONTACT, acVariableKey.getValue(),"variable VARNAME_PLATINE_CONTACT not set"); - PlatineContactDto argumentDto = (new ObjectMapper()).treeToValue(acVariableValue.getValue(),PlatineContactDto.class); - assertEquals("55", argumentDto.getIdentifier(),"Bad Object retrieved"); - - } - -} \ No newline at end of file diff --git a/src/test/java/fr/insee/protools/backend/service/platine/delegate/PlatineQuestionnaireCreateContextTaskTest.java b/src/test/java/fr/insee/protools/backend/service/platine/delegate/PlatineQuestionnaireCreateContextTaskTest.java deleted file mode 100644 index a0f8ccc9..00000000 --- a/src/test/java/fr/insee/protools/backend/service/platine/delegate/PlatineQuestionnaireCreateContextTaskTest.java +++ /dev/null @@ -1,129 +0,0 @@ -package fr.insee.protools.backend.service.platine.delegate; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import fr.insee.protools.backend.ProtoolsTestUtils; -import fr.insee.protools.backend.dto.platine_sabiane_questionnaire.campaign.CampaignDto; -import fr.insee.protools.backend.dto.platine_sabiane_questionnaire.campaign.MetadataValue; -import fr.insee.protools.backend.service.context.ContextConstants; -import fr.insee.protools.backend.service.context.ContextService; -import fr.insee.protools.backend.service.context.exception.BadContextIncorrectBPMNError; -import fr.insee.protools.backend.service.nomenclature.NomenclatureService; -import fr.insee.protools.backend.service.platine.questionnaire.PlatineQuestionnaireService; -import fr.insee.protools.backend.service.questionnaire_model.QuestionnaireModelService; -import org.flowable.engine.delegate.DelegateExecution; -import org.flowable.engine.test.FlowableTest; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.ArgumentCaptor; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.Spy; -import org.mockito.junit.jupiter.MockitoExtension; -import org.springframework.util.ClassUtils; - -import java.io.IOException; -import java.util.List; -import java.util.Set; - -import static fr.insee.protools.backend.service.context.ContextConstants.*; -import static org.assertj.core.api.AssertionsForClassTypes.assertThatCode; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.*; - - -@ExtendWith(MockitoExtension.class) -@FlowableTest -public -class PlatineQuestionnaireCreateContextTaskTest { - - final static String ressourceFolder = ClassUtils.convertClassNameToResourcePath(PlatineQuestionnaireCreateContextTaskTest.class.getPackageName()); - final static String platine_context_json = ressourceFolder+"/protools-contexte-platine-individu.json"; - final static String platine_context_incorrect_json = ressourceFolder+"/protools-contexte-platine-incorrect.json"; - - @Mock PlatineQuestionnaireService platineQuestionnaireService; - @Mock QuestionnaireModelService questionnaireModelService; - @Mock NomenclatureService nomenclatureService; - @Mock ContextService protoolsContext; - @Spy ObjectMapper objectMapper; - - @InjectMocks - PlatineQuestionnaireCreateContextTask platineQuestTask; - - private final String questionnaireContent1 ="{\"id\": \"TOTO\" , \"toto\": 55 }"; - - - private JsonNode initContexteMock(String contexteToLoad){ - JsonNode contextRootNode = ProtoolsTestUtils.asJsonNode(contexteToLoad); - when(protoolsContext.getContextByProcessInstance(anyString())).thenReturn(contextRootNode); - return contextRootNode; - } - - @Test - void execute_should_throwBadContextIncorrect_when_contextIsKO() { - // preconditions - DelegateExecution execution = mock(DelegateExecution.class); - when(execution.getProcessInstanceId()).thenReturn("1"); - initContexteMock(platine_context_incorrect_json); - - //Execute the unit under test - assertThrows(BadContextIncorrectBPMNError.class, () -> platineQuestTask.execute(execution)); - - // postconditions - //assertThat(execution.getVariable("myVariable")).isEqualTo("myValue"); - - } - - /*@Test - void initQuestionnaireModels_should_produce_correct_json(){ - platineQuestTask.² - }*/ - - @Test - void execute_should_work_and_make_correct_calls() throws IOException { - DelegateExecution execution = mock(DelegateExecution.class); - when(execution.getProcessInstanceId()).thenReturn("1"); - JsonNode contextRootNode = initContexteMock(platine_context_json); - assertEquals(1,contextRootNode.path(ContextConstants.CTX_QUESTIONNAIRE_MODELS).size(), "Context error : expected exactly one questionnaire model"); - String idQuestionnaireModel = contextRootNode.path(ContextConstants.CTX_QUESTIONNAIRE_MODELS).get(0).path(CTX_QUESTIONNAIRE_MODEL_ID).asText(); - String labelQuestionnaireModel = contextRootNode.path(ContextConstants.CTX_QUESTIONNAIRE_MODELS).get(0).path(CTX_QUESTIONNAIRE_MODEL_LABEL).asText(); - String repertoireQuestionnaireModel = contextRootNode.path(ContextConstants.CTX_QUESTIONNAIRE_MODELS).get(0).path(CTX_QUESTIONNAIRE_MODEL_CHEMIN_REPERTOIRE).asText(); - - //Prepare the list of existing nomenclatures ("L_NATIONETR-1-1-0" does not exists yet) - when(platineQuestionnaireService.getNomenclaturesId()).thenReturn(Set.of("L_DEPNAIS-1-1-0","L_PAYSNAIS-1-1-0")); - //Mock the read nomenclature - String nomenclatureContent="{\"id\": \"nomenclatureContent\"}"; - when(nomenclatureService.getNomenclatureContent("L_NATIONETR-1-1-0","NATIONETR")).thenReturn(nomenclatureContent); - //Mock questionnaire - when(platineQuestionnaireService.questionnaireModelExists(anyString())).thenReturn(false); - when(questionnaireModelService.getQuestionnaireModel(anyString(), anyString())).thenReturn(questionnaireContent1); - - - //Execute the unit under test - assertThatCode(() -> platineQuestTask.execute(execution)).doesNotThrowAnyException(); - - //Verifications on nomenclatures - verify(platineQuestionnaireService,atLeastOnce()).getNomenclaturesId(); - verify(platineQuestionnaireService).postNomenclature( - "L_NATIONETR-1-1-0", - "liste des nationalités", - objectMapper.readTree(nomenclatureContent)); - - //Verifications on questionnaires - verify(platineQuestionnaireService,times(1)).questionnaireModelExists(idQuestionnaireModel); - verify(questionnaireModelService,times(1)).getQuestionnaireModel(idQuestionnaireModel,repertoireQuestionnaireModel); - verify(platineQuestionnaireService).postQuestionnaireModel(idQuestionnaireModel,labelQuestionnaireModel, - objectMapper.readTree(questionnaireContent1), - Set.of("L_DEPNAIS-1-1-0","L_PAYSNAIS-1-1-0","L_NATIONETR-1-1-0")); - - //Verify postCampaign - ArgumentCaptor acCampaignDto = ArgumentCaptor.forClass(CampaignDto.class); - verify(platineQuestionnaireService,times(1)).postCampaign(acCampaignDto.capture()); - List allValues = acCampaignDto.getAllValues(); - assertEquals(1, allValues.size(),"We should have exactly one campaign"); - MetadataValue expectedMetadataNode = ProtoolsTestUtils.asObject(ressourceFolder + "/expected_post_questionnaire_metadata.json", MetadataValue.class); - assertEquals(expectedMetadataNode,allValues.get(0).getMetadata(),"Erreur with generated Metadata"); - } -} diff --git a/src/test/java/fr/insee/protools/backend/service/platine/delegate/PlatineQuestionnaireCreateSurveyUnitTaskTest.java b/src/test/java/fr/insee/protools/backend/service/platine/delegate/PlatineQuestionnaireCreateSurveyUnitTaskTest.java deleted file mode 100644 index 22afcdeb..00000000 --- a/src/test/java/fr/insee/protools/backend/service/platine/delegate/PlatineQuestionnaireCreateSurveyUnitTaskTest.java +++ /dev/null @@ -1,114 +0,0 @@ -package fr.insee.protools.backend.service.platine.delegate; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ObjectNode; -import fr.insee.protools.backend.ProtoolsTestUtils; -import fr.insee.protools.backend.dto.platine_sabiane_questionnaire.surveyunit.SurveyUnitResponseDto; -import fr.insee.protools.backend.service.context.exception.BadContextIncorrectBPMNError; -import fr.insee.protools.backend.service.exception.IncorrectSUBPMNError; -import fr.insee.protools.backend.service.platine.questionnaire.PlatineQuestionnaireService; -import fr.insee.protools.backend.service.utils.TestWithContext; -import fr.insee.protools.backend.service.utils.data.RemSUData; -import org.flowable.engine.delegate.DelegateExecution; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; -import org.mockito.ArgumentCaptor; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.springframework.util.ClassUtils; - -import java.util.stream.Stream; - -import static fr.insee.protools.backend.service.FlowableVariableNameConstants.*; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.*; - -class PlatineQuestionnaireCreateSurveyUnitTaskTest extends TestWithContext { - - @Mock - PlatineQuestionnaireService platineQuestionnaireService; - - @InjectMocks - PlatineQuestionnaireCreateSurveyUnitTask platineQuestionnaireCreateSurveyUnitTask; - - - - final static String ressourceFolder = ClassUtils.convertClassNameToResourcePath(PlatineQuestionnaireCreateSurveyUnitTask.class.getPackageName()); - final static String platine_context_json = ressourceFolder+"/protools-contexte-platine-individu.json"; - final static String platine_context_logement_json = ressourceFolder+"/protools-contexte-platine-individu.json"; - - //To be able to run tests with differents protools contexts - private static Stream protoolsContextArguments() { - return Stream.of( - Arguments.of(platine_context_json), - Arguments.of(platine_context_logement_json) - ); - } - - @Test - void execute_should_throwError_when_null_context(){ - assertThat_delegate_throwError_when_null_context(platineQuestionnaireCreateSurveyUnitTask); - } - @Test - void execute_should_throw_BadContextIncorrectException_when_noContext() { - DelegateExecution execution=createMockedExecution(); - //Execute the unit under test - assertThrows(BadContextIncorrectBPMNError.class,() -> platineQuestionnaireCreateSurveyUnitTask.execute(execution)); - } - @ParameterizedTest - @MethodSource("protoolsContextArguments") - void execute_should_work_when_ContextOK(String context_json) throws JsonProcessingException { - //Prepare - DelegateExecution execution=createMockedExecution(); - JsonNode contextRootNode = initContexteMockWithFile(context_json); - JsonNode remSU = ProtoolsTestUtils.asJsonNode(RemSUData.rem_su_3personnes); - Long idPartition=1l; - lenient().doReturn(idPartition).when(execution).getVariable(VARNAME_CURRENT_PARTITION_ID,Long.class); - lenient().doReturn(remSU).when(execution).getVariable(VARNAME_REM_SURVEY_UNIT,JsonNode.class); - lenient().doReturn("TOTO").when(execution).getVariable(VARNAME_DIRECTORYACCESS_ID_CONTACT,String.class); - - //Execute the unit under test - platineQuestionnaireCreateSurveyUnitTask.execute(execution); - - //Post Conditions - ObjectMapper objectMapper = new ObjectMapper(); - ArgumentCaptor acSUResDTO = ArgumentCaptor.forClass(SurveyUnitResponseDto.class); - verify(platineQuestionnaireService,times(1)).postSurveyUnit(acSUResDTO.capture(),any()); - SurveyUnitResponseDto valueParam = acSUResDTO.getValue(); - assertEquals("3043280", valueParam.getId(),"Wrong ID SU (repository id)"); - assertEquals("tic2023a00_web", valueParam.getQuestionnaireId(),"Wrong questionnaireId"); - assertEquals(objectMapper.readTree("[{\"name\":\"whoAnswers1\",\"value\":\"Qui doit répondre paragraphe 1\"}," + - "{\"name\":\"whoAnswers2\",\"value\":\"Qui doit répondre paragraphe 2\"}," + - "{\"name\":\"whoAnswers3\",\"value\":\"Qui doit répondre paragraphe 3\"}]") - , valueParam.getPersonalization(),"Wrong questionnaireId"); - assertEquals(objectMapper.readTree("{\"EXTERNAL\":{\"ADMINISTRATION1\":\"Insee\",\"ADMINISTRATION2\":\"Patate\"}}"), - valueParam.getData(),"Wrong data (external)"); - assertEquals(objectMapper.createObjectNode(), valueParam.getComment(),"No comment expected"); - //assertEquals(objectMapper.createObjectNode(), valueParam.getStateData(),"No stateData expected"); - } - - @Test - void execute_should_throw_IncorrectSUException_when_wrongSU() { - DelegateExecution execution=createMockedExecution(); - initContexteMockWithFile(platine_context_json); - JsonNode remSU = ProtoolsTestUtils.asJsonNode(RemSUData.rem_su_3personnes); - //Break this node - ((ObjectNode) remSU).remove("repositoryId"); - Long idPartition=1l; - lenient().doReturn(idPartition).when(execution).getVariable(VARNAME_CURRENT_PARTITION_ID,Long.class); - lenient().doReturn(remSU).when(execution).getVariable(VARNAME_REM_SURVEY_UNIT,JsonNode.class); - lenient().doReturn("TOTO").when(execution).getVariable(VARNAME_DIRECTORYACCESS_ID_CONTACT,String.class); - - - //Execute the unit under test - assertThrows(IncorrectSUBPMNError.class,() -> platineQuestionnaireCreateSurveyUnitTask.execute(execution)); - } - - - -} \ No newline at end of file diff --git a/src/test/java/fr/insee/protools/backend/service/platine/delegate/pilotatage/PlatinePilotageCreateCommunicationEventTaskRESTTestDelegate.java b/src/test/java/fr/insee/protools/backend/service/platine/delegate/pilotatage/PlatinePilotageCreateCommunicationEventTaskRESTTestDelegate.java new file mode 100644 index 00000000..2737678f --- /dev/null +++ b/src/test/java/fr/insee/protools/backend/service/platine/delegate/pilotatage/PlatinePilotageCreateCommunicationEventTaskRESTTestDelegate.java @@ -0,0 +1,163 @@ +package fr.insee.protools.backend.service.platine.delegate.pilotatage; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.read.ListAppender; +import ch.qos.logback.classic.Logger; + +import fr.insee.protools.backend.dto.platine.pilotage.PlatinePilotageCommunicationEventDto; +import fr.insee.protools.backend.exception.ProtoolsProcessFlowBPMNError; +import fr.insee.protools.backend.service.platine.service.PlatinePilotageServiceImpl; +import fr.insee.protools.backend.service.utils.delegate.IDelegateWithVariables; +import lombok.extern.slf4j.Slf4j; +import org.flowable.engine.delegate.DelegateExecution; +import org.flowable.engine.delegate.JavaDelegate; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.mockito.ArgumentCaptor; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.slf4j.LoggerFactory; + +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Stream; + +import static fr.insee.protools.backend.service.FlowableVariableNameConstants.*; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +@Slf4j +public class PlatinePilotageCreateCommunicationEventTaskRESTTestDelegate implements IDelegateWithVariables { + + @Mock + PlatinePilotageServiceImpl platinePilotageService; + + @InjectMocks + PlatinePilotageCreateCommunicationEventTaskREST task; + + @Override + public JavaDelegate getTaskUnderTest() { + return task; + } + + @Override + public Map getVariablesAndTypes() { + return Map.of( + VARNAME_CURRENT_COMMUNICATION_ID, String.class, + VARNAME_CURRENT_PARTITION_ID, String.class, + VARNAME_COMMUNICATION_REQUEST_ID_FOR_INTERRO_ID_MAP, Map.class + ); + } + + static Stream initExecuteParametersOK() { + return Stream.of( + Arguments.of(Map.of(), "comId", Boolean.FALSE), + Arguments.of(Map.of("interroId1", "commReqId1"), "xxx", Boolean.TRUE), + Arguments.of(Map.of("interroId1", "commReqId1", "interroId2", "commReqId2", "interroId3", "commReqId3"), "xxx", Boolean.TRUE) + ); + } + + @ParameterizedTest + @MethodSource("initExecuteParametersOK") + @DisplayName("Test execute method - should work and make correct call to service") + void execute_should_work_whenEverythingOk(Map commIdByInterro, String communcationId, Boolean expectedCallToService) { + //Prepare + DelegateExecution execution = createMockedExecution(); + doReturn(communcationId).when(execution).getVariable(VARNAME_CURRENT_COMMUNICATION_ID, String.class); + doReturn(dumyId).when(execution).getVariable(VARNAME_CURRENT_PARTITION_ID, String.class); + doReturn(commIdByInterro).when(execution).getVariable(VARNAME_COMMUNICATION_REQUEST_ID_FOR_INTERRO_ID_MAP, Map.class); + + //Execute method under test + task.execute(execution); + + //verify + + //Case where the service is not supposed to be called + if (!expectedCallToService) { + verify(platinePilotageService, never()).postCommunicationEvents(any()); + return; + } + + + final ArgumentCaptor> listCaptor + = ArgumentCaptor.forClass((Class) List.class); + + verify(platinePilotageService, times(1)).postCommunicationEvents(listCaptor.capture()); + List> allValues = listCaptor.getAllValues(); + assertEquals(1, allValues.size(), "We should have exactly one value"); + + List actualArgument = listCaptor.getValue(); + assertEquals(commIdByInterro.size(), actualArgument.size(), "The passed list of events has an incorrect size"); + + //check that we passed the correct items + Set requiredInterroIds = new HashSet<>(commIdByInterro.keySet()); + for (var comEventDto : actualArgument) { + String idInterro = comEventDto.interrogationId(); + if (requiredInterroIds.contains(idInterro)) { + //ComRequestId is correct + String expectedCommId = commIdByInterro.get(idInterro); + String actualCommReqId = comEventDto.communicationRequestId(); + assertEquals(expectedCommId, actualCommReqId, + "Communcation Request ID is not the one expected for idInterro=" + idInterro + " - "); + + assertEquals(communcationId,comEventDto.communicationId()); + //CommId is + requiredInterroIds.remove(idInterro); //this id has correctly been sent + } + } + } + + @Test + @DisplayName("Test execute method - should throw ProtoolsProcessFlowBPMNError when communication Id is null") + public void execute_should_throw_when_varCommId_is_blank() { + String commId=""; + //Prepare + DelegateExecution execution = createMockedExecution(); + doReturn(commId).when(execution).getVariable(VARNAME_CURRENT_COMMUNICATION_ID, String.class); + doReturn(dumyId).when(execution).getVariable(VARNAME_CURRENT_PARTITION_ID, String.class); + doReturn(Map.of("interroId1", "commReqId1")).when(execution).getVariable(VARNAME_COMMUNICATION_REQUEST_ID_FOR_INTERRO_ID_MAP, Map.class); + + //Execute method under test + assertThrows(ProtoolsProcessFlowBPMNError.class, () -> task.execute(execution)); + } + + @Test + @DisplayName("Test execute method - should write a log and not call service when the communication Request Map is empty ") + public void execute_should_writeLog_and_notCallService_when_comReqByIdMapIsEmpty() { + //Prepare + DelegateExecution execution = createMockedExecution(); + initDefaultVariables(execution); + + // create and start a ListAppender to capture logs + Logger fooLogger = (Logger) LoggerFactory.getLogger(task.getClass()); + ListAppender listAppender = new ListAppender<>(); + fooLogger.addAppender(listAppender); + listAppender.start(); + + //Execute method under test + task.execute(execution); + + //Verify + List logsList = listAppender.list; + assertThat(logsList.get(0).getFormattedMessage()) + .contains("begin",execution.getProcessInstanceId()); + + assertEquals(Level.INFO, logsList.get(1) + .getLevel()); + assertThat(logsList.get(1).getFormattedMessage()) + .contains("end",execution.getProcessInstanceId(),"Nothing to do"); + + verify(platinePilotageService,never()).postCommunicationEvents(any()); + } +} \ No newline at end of file diff --git a/src/test/java/fr/insee/protools/backend/service/platine/delegate/pilotatage/PlatinePilotageCreateContextTaskRESTTestDelegate.java b/src/test/java/fr/insee/protools/backend/service/platine/delegate/pilotatage/PlatinePilotageCreateContextTaskRESTTestDelegate.java new file mode 100644 index 00000000..64d6057e --- /dev/null +++ b/src/test/java/fr/insee/protools/backend/service/platine/delegate/pilotatage/PlatinePilotageCreateContextTaskRESTTestDelegate.java @@ -0,0 +1,68 @@ +package fr.insee.protools.backend.service.platine.delegate.pilotatage; + +import com.fasterxml.jackson.databind.JsonNode; +import fr.insee.protools.backend.service.platine.service.PlatinePilotageServiceImpl; +import fr.insee.protools.backend.service.utils.delegate.TestDelegateWithContext; +import org.flowable.engine.delegate.DelegateExecution; +import org.flowable.engine.delegate.JavaDelegate; +import org.flowable.engine.test.FlowableTest; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.List; +import java.util.Map; + +import static fr.insee.protools.backend.utils.data.CtxExamples.CTX_EMPTY; +import static fr.insee.protools.backend.utils.data.CtxExamples.CTX_EMPTY_ID; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +@ExtendWith(MockitoExtension.class) +@FlowableTest +class PlatinePilotageCreateContextTaskRESTTestDelegate extends TestDelegateWithContext { + + @Mock + PlatinePilotageServiceImpl platinePilotageService; + + @InjectMocks + PlatinePilotageCreateContextTaskREST platinePilotageTask; + + @Test + void execute_should_work_when_contextOK() { + DelegateExecution execution = createMockedExecution(); + JsonNode expectedContext = initContexteMockWithString(CTX_EMPTY); + + //Execute the unit under test + platinePilotageTask.execute(execution); + + //Verify postContext + ArgumentCaptor acCtx = ArgumentCaptor.forClass(JsonNode.class); + verify(platinePilotageService,times(1)).postContext(eq(CTX_EMPTY_ID),acCtx.capture()); + List allValues = acCtx.getAllValues(); + assertEquals(1, allValues.size(),"We should have exactly one value"); + + assertEquals(expectedContext,allValues.get(0),"Wrong context passed"); + + } + + @Override + public JavaDelegate getTaskUnderTest() { + return platinePilotageTask; + } + + @Override + public Map getVariablesAndTypes() { + return Map.of(); + } + + @Override + protected String minimalValidCtxt() { + return CTX_EMPTY; + } +} \ No newline at end of file diff --git a/src/test/java/fr/insee/protools/backend/service/platine/delegate/pilotatage/PlatinePilotageCreateInterrogationListTaskRESTTestDelegate.java b/src/test/java/fr/insee/protools/backend/service/platine/delegate/pilotatage/PlatinePilotageCreateInterrogationListTaskRESTTestDelegate.java new file mode 100644 index 00000000..b9f0876d --- /dev/null +++ b/src/test/java/fr/insee/protools/backend/service/platine/delegate/pilotatage/PlatinePilotageCreateInterrogationListTaskRESTTestDelegate.java @@ -0,0 +1,79 @@ +package fr.insee.protools.backend.service.platine.delegate.pilotatage; + +import com.fasterxml.jackson.databind.JsonNode; +import fr.insee.protools.backend.service.platine.service.PlatinePilotageServiceImpl; +import fr.insee.protools.backend.service.utils.delegate.TestDelegateWithContext; +import org.flowable.engine.delegate.DelegateExecution; +import org.flowable.engine.delegate.JavaDelegate; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.InjectMocks; +import org.mockito.Mock; + +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import static fr.insee.protools.backend.service.FlowableVariableNameConstants.VARNAME_CURRENT_PARTITION_ID; +import static fr.insee.protools.backend.service.FlowableVariableNameConstants.VARNAME_REM_INTERRO_LIST; +import static fr.insee.protools.backend.utils.data.CtxExamples.CTX_EMPTY; +import static fr.insee.protools.backend.utils.data.CtxExamples.CTX_EMPTY_ID; +import static fr.insee.protools.backend.utils.data.InterroExamples.generateEmptyInterro; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.*; + +class PlatinePilotageCreateInterrogationListTaskRESTTestDelegate extends TestDelegateWithContext { + + @Mock + PlatinePilotageServiceImpl platinePilotageService; + + @InjectMocks + PlatinePilotageCreateInterrogationListTaskREST task; + + @Test + void execute_should_work_when_contextOKVarOK() { + DelegateExecution execution = createMockedExecution(); + JsonNode expectedContext = initContexteMockWithString(CTX_EMPTY); + + //Process variables + lenient().doReturn(String.valueOf(UUID.randomUUID())).when(execution).getVariable(VARNAME_CURRENT_PARTITION_ID, String.class); + + List interroList = IntStream.range(0, 100) + .mapToObj(i -> generateEmptyInterro().interro()) // Call your function and get the JsonNode + .collect(Collectors.toList()); + lenient().doReturn(interroList).when(execution).getVariable(VARNAME_REM_INTERRO_LIST, List.class); + + //Execute the unit under test + task.execute(execution); + + //Verify postContext + final ArgumentCaptor > listCaptor + = ArgumentCaptor.forClass((Class) List.class); + + verify(platinePilotageService,times(1)).postInterrogations(eq(CTX_EMPTY_ID),listCaptor.capture()); + List> allValues = listCaptor.getAllValues(); + assertEquals(1, allValues.size(),"We should have exactly one value"); + + assertEquals(interroList,allValues.get(0),"Wrong list of interro passed"); + } + + @Override + public JavaDelegate getTaskUnderTest() { + return task; + } + + @Override + public Map getVariablesAndTypes() { + return Map.of( + VARNAME_CURRENT_PARTITION_ID,String.class, + VARNAME_REM_INTERRO_LIST,List.class); + } + + @Override + protected String minimalValidCtxt() { + return CTX_EMPTY; + } +} \ No newline at end of file diff --git a/src/test/java/fr/insee/protools/backend/service/platine/delegate/pilotatage/PlatinePilotageGetListOfInterroToFollowUpPaginatedTaskRESTTest.java b/src/test/java/fr/insee/protools/backend/service/platine/delegate/pilotatage/PlatinePilotageGetListOfInterroToFollowUpPaginatedTaskRESTTest.java new file mode 100644 index 00000000..9342ce3f --- /dev/null +++ b/src/test/java/fr/insee/protools/backend/service/platine/delegate/pilotatage/PlatinePilotageGetListOfInterroToFollowUpPaginatedTaskRESTTest.java @@ -0,0 +1,50 @@ +package fr.insee.protools.backend.service.platine.delegate.pilotatage; + +import fr.insee.protools.backend.restclient.pagination.PageResponse; +import fr.insee.protools.backend.service.platine.service.PlatinePilotageServiceImpl; +import fr.insee.protools.backend.service.utils.delegate.IDelegateWithVariableGetPaginated; +import org.flowable.engine.delegate.JavaDelegate; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.Map; + +import static fr.insee.protools.backend.service.FlowableVariableNameConstants.VARNAME_CURRENT_PARTITION_ID; +import static fr.insee.protools.backend.service.FlowableVariableNameConstants.VARNAME_REM_INTERRO_LIST; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +class PlatinePilotageGetListOfInterroToFollowUpPaginatedTaskRESTTest + implements IDelegateWithVariableGetPaginated { + + + @Mock + PlatinePilotageServiceImpl platinePilotageService; + @InjectMocks + PlatinePilotageGetListOfInterroToFollowUpPaginatedTaskREST task; + + @Override + public JavaDelegate getTaskUnderTest() { + return task; + } + + @Override + public void initReadValueMock(PageResponse expectedPageResponse) { + lenient().doReturn(expectedPageResponse).when(platinePilotageService).getInterrogationToFollowUpPaginated(anyString(), anyLong(),any()); + } + + @Override + public Map getVariablesAndTypes() { + return Map.of( + VARNAME_CURRENT_PARTITION_ID, String.class + ); + } + + @Override + public String getOutListVariableName() { + return VARNAME_REM_INTERRO_LIST; + } + +} \ No newline at end of file diff --git a/src/test/java/fr/insee/protools/backend/service/platine/delegate/questionnaire/PlatineQuestionnaireCreateContextTaskRESTTestDelegate.java b/src/test/java/fr/insee/protools/backend/service/platine/delegate/questionnaire/PlatineQuestionnaireCreateContextTaskRESTTestDelegate.java new file mode 100644 index 00000000..1cd9e3da --- /dev/null +++ b/src/test/java/fr/insee/protools/backend/service/platine/delegate/questionnaire/PlatineQuestionnaireCreateContextTaskRESTTestDelegate.java @@ -0,0 +1,64 @@ +package fr.insee.protools.backend.service.platine.delegate.questionnaire; + +import com.fasterxml.jackson.databind.JsonNode; +import fr.insee.protools.backend.service.platine.service.PlatineQuestionnaireServiceImpl; +import fr.insee.protools.backend.service.utils.delegate.TestDelegateWithContext; +import org.flowable.engine.delegate.DelegateExecution; +import org.flowable.engine.delegate.JavaDelegate; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.InjectMocks; +import org.mockito.Mock; + +import java.util.List; +import java.util.Map; + +import static fr.insee.protools.backend.utils.data.CtxExamples.CTX_EMPTY; +import static fr.insee.protools.backend.utils.data.CtxExamples.CTX_EMPTY_ID; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +class PlatineQuestionnaireCreateContextTaskRESTTestDelegate extends TestDelegateWithContext { + + @Mock + PlatineQuestionnaireServiceImpl platineQuestionnaireService; + + @InjectMocks + PlatineQuestionnaireCreateContextTaskREST platineQuestionnaireTask; + + + @Override + public JavaDelegate getTaskUnderTest() { + return platineQuestionnaireTask; + } + + @Override + public Map getVariablesAndTypes() { + return Map.of(); + } + + @Test + void execute_should_work_when_contextOK() { + DelegateExecution execution = createMockedExecution(); + JsonNode expectedContext = initContexteMockWithString(CTX_EMPTY); + + //Execute the unit under test + platineQuestionnaireTask.execute(execution); + + //Verify postContext + ArgumentCaptor acCtx = ArgumentCaptor.forClass(JsonNode.class); + verify(platineQuestionnaireService,times(1)).postContext(eq(CTX_EMPTY_ID),acCtx.capture()); + List allValues = acCtx.getAllValues(); + assertEquals(1, allValues.size(),"We should have exactly one value"); + + assertEquals(expectedContext,allValues.get(0),"Wrong context passed"); + + } + + @Override + protected String minimalValidCtxt() { + return CTX_EMPTY; + } +} \ No newline at end of file diff --git a/src/test/java/fr/insee/protools/backend/service/platine/delegate/questionnaire/PlatineQuestionnaireCreateInterrogationListTaskRESTTestDelegate.java b/src/test/java/fr/insee/protools/backend/service/platine/delegate/questionnaire/PlatineQuestionnaireCreateInterrogationListTaskRESTTestDelegate.java new file mode 100644 index 00000000..0a3b7564 --- /dev/null +++ b/src/test/java/fr/insee/protools/backend/service/platine/delegate/questionnaire/PlatineQuestionnaireCreateInterrogationListTaskRESTTestDelegate.java @@ -0,0 +1,79 @@ +package fr.insee.protools.backend.service.platine.delegate.questionnaire; + +import com.fasterxml.jackson.databind.JsonNode; +import fr.insee.protools.backend.service.platine.service.PlatineQuestionnaireServiceImpl; +import fr.insee.protools.backend.service.utils.delegate.TestDelegateWithContext; +import org.flowable.engine.delegate.DelegateExecution; +import org.flowable.engine.delegate.JavaDelegate; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.InjectMocks; +import org.mockito.Mock; + +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import static fr.insee.protools.backend.service.FlowableVariableNameConstants.VARNAME_CURRENT_PARTITION_ID; +import static fr.insee.protools.backend.service.FlowableVariableNameConstants.VARNAME_REM_INTERRO_LIST; +import static fr.insee.protools.backend.utils.data.CtxExamples.CTX_EMPTY; +import static fr.insee.protools.backend.utils.data.CtxExamples.CTX_EMPTY_ID; +import static fr.insee.protools.backend.utils.data.InterroExamples.generateEmptyInterro; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.*; + +class PlatineQuestionnaireCreateInterrogationListTaskRESTTestDelegate extends TestDelegateWithContext { + + @Mock + PlatineQuestionnaireServiceImpl platineQuestionnaireService; + + @InjectMocks + PlatineQuestionnaireCreateInterrogationListTaskREST task; + + @Test + void execute_should_work_when_contextOKVarOK() { + DelegateExecution execution = createMockedExecution(); + JsonNode expectedContext = initContexteMockWithString(CTX_EMPTY); + + //Process variables + lenient().doReturn(String.valueOf(UUID.randomUUID())).when(execution).getVariable(VARNAME_CURRENT_PARTITION_ID, String.class); + + List interroList = IntStream.range(0, 100) + .mapToObj(i -> generateEmptyInterro().interro()) // Call your function and get the JsonNode + .collect(Collectors.toList()); + lenient().doReturn(interroList).when(execution).getVariable(VARNAME_REM_INTERRO_LIST, List.class); + + //Execute the unit under test + task.execute(execution); + + //Verify postContext + final ArgumentCaptor > listCaptor + = ArgumentCaptor.forClass((Class) List.class); + + verify(platineQuestionnaireService,times(1)).postInterrogations(eq(CTX_EMPTY_ID),listCaptor.capture()); + List> allValues = listCaptor.getAllValues(); + assertEquals(1, allValues.size(),"We should have exactly one value"); + + assertEquals(interroList,allValues.get(0),"Wrong list of interro passed"); + } + + @Override + public JavaDelegate getTaskUnderTest() { + return task; + } + + @Override + public Map getVariablesAndTypes() { + return Map.of( + VARNAME_CURRENT_PARTITION_ID,String.class, + VARNAME_REM_INTERRO_LIST,List.class); + } + + @Override + protected String minimalValidCtxt() { + return CTX_EMPTY; + } +} \ No newline at end of file diff --git a/src/test/java/fr/insee/protools/backend/service/platine/service/PlatinePilotageServiceTest.java b/src/test/java/fr/insee/protools/backend/service/platine/service/PlatinePilotageServiceTest.java new file mode 100644 index 00000000..89ef0d3d --- /dev/null +++ b/src/test/java/fr/insee/protools/backend/service/platine/service/PlatinePilotageServiceTest.java @@ -0,0 +1,168 @@ +package fr.insee.protools.backend.service.platine.service; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.JsonNodeFactory; +import fr.insee.protools.backend.dto.platine.pilotage.PlatinePilotageCommunicationEventDto; +import fr.insee.protools.backend.dto.platine.pilotage.PlatinePilotageCommunicationEventType; +import fr.insee.protools.backend.restclient.exception.runtime.HttpClient4xxBPMNError; +import fr.insee.protools.backend.restclient.pagination.PageResponse; +import fr.insee.protools.backend.service.utils.TestServiceWithRestClient; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; +import org.springframework.web.util.UriBuilder; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import static fr.insee.protools.backend.restclient.configuration.ApiConfigProperties.KNOWN_API.KNOWN_API_PLATINE_PILOTAGE; +import static fr.insee.protools.backend.utils.data.InterroExamples.generateEmptyInterro; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.eq; +import static org.mockito.Mockito.verify; + +@ExtendWith(MockitoExtension.class) +class PlatinePilotageServiceTest extends TestServiceWithRestClient { + + private static ObjectMapper objectMapper = new ObjectMapper(); + + @InjectMocks + PlatinePilotageServiceImpl service; + @Value("${fr.insee.protools.api.platine-pilotage.interrogation.page.size:5000}") + private int pageSizeGetInterro; + + @Test + void postContext_should_call_correctURIAndBody() { + //Prepare + JsonNode contextNode = JsonNodeFactory.instance.objectNode(); + + //Call method under test + service.postContext("TOTO", contextNode); + + //Verifications + // Then - Verify that the uri method was called with "/context" + verify(restClientHelper).getRestClient(KNOWN_API_PLATINE_PILOTAGE); + verify(restClient).post(); + verify(requestBodyUriSpec).uri("/context"); + // and with expected body + verify(requestBodyUriSpec).body(contextNode); + } + + + @Test + void postInterrogations_should_makeCorrectCall() { + //Prepare + List interroList = IntStream.range(0, 100) + .mapToObj(i -> generateEmptyInterro().interro()) // Call your function and get the JsonNode + .collect(Collectors.toList()); + + //Call method under tests + service.postInterrogations("TOTO", interroList); + + //Verify + verify(restClientHelper).getRestClient(KNOWN_API_PLATINE_PILOTAGE); + verify(restClient).post(); + verify(requestBodyUriSpec).uri("/interrogations"); + // and with expected body + verify(requestBodyUriSpec).body(interroList); + } + + @Test + void postCommunicationEvents_should_makeCorrectCall() { + //Prepare + List eventList = IntStream.range(0, 10) + .mapToObj(i -> + new PlatinePilotageCommunicationEventDto(UUID.randomUUID().toString(),UUID.randomUUID().toString(),"comRequestId-xxx",PlatinePilotageCommunicationEventType.COMMUNICATION_STATE_SENT) + ) // Call your function and get the JsonNode + .collect(Collectors.toList()); + + //Call method under tests + service.postCommunicationEvents(eventList); + + //Verify + verify(restClient).post(); + verify(requestBodyUriSpec).uri("/interrogations/communication-events"); + // and with expected body + verify(requestBodyUriSpec).body(eventList); + } + + + @Test + void getInterrogationToFollowUpPaginated_shouldMakeCorrectCalls() { + //Prepare + String partitionId = "PartitionIDXX"; + long page = 69; + Optional isToFollowUp = Optional.of(Boolean.FALSE); + + List mockedResponse = List.of(objectMapper.createObjectNode().put("id", 1).put("id", "toto")); + mockRetrieveBodyResponse(mockedResponse); + //Call method under tests + PageResponse response = service.getInterrogationToFollowUpPaginated(partitionId, page, isToFollowUp); + + //Verify + verify(restClientHelper).getRestClient(KNOWN_API_PLATINE_PILOTAGE); + verify(restClient).get(); + + UriBuilder mockUriBuilder = mockGETURIBuilderAndPrepareForTest(); + + // Verify that the correct path and query parameters were used + verify(mockUriBuilder).path("/interrogations"); + verify(mockUriBuilder).queryParam("page", page); + verify(mockUriBuilder).queryParam("size", pageSizeGetInterro); + verify(mockUriBuilder).queryParam("partition_id", partitionId); + verify(mockUriBuilder).queryParamIfPresent(eq("follow-up"), eq(isToFollowUp)); + + assertEquals(mockedResponse, response.getContent(), "The response is not what was expected/mocked"); + } + + + @Test + void getInterrogationToFollowUpPaginated_shouldCatch() { + //Prepare + String partitionId = "PartitionIDYY"; + long page = 0; + Optional isToFollowUp = Optional.of(Boolean.TRUE); + + mockMakeRetrieveThrow(HttpStatusCode.valueOf(HttpStatus.BAD_REQUEST.value())); + //Call method under tests + assertThrows(HttpClient4xxBPMNError.class, () -> service.getInterrogationToFollowUpPaginated(partitionId, page, isToFollowUp)); + } + + @Test + void getInterrogationToFollowUpPaginated_shouldCatch_404() { + //Prepare + String partitionId = "PartitionIDYY"; + long page = 0; + Optional isToFollowUp = Optional.of(Boolean.TRUE); + + mockMakeRetrieveThrow(HttpStatusCode.valueOf(HttpStatus.NOT_FOUND.value())); + //Call method under tests + HttpClient4xxBPMNError exception = assertThrows(HttpClient4xxBPMNError.class, () -> service.getInterrogationToFollowUpPaginated(partitionId, page, isToFollowUp)); + assertThat(exception.getMessage(), containsString("404")); + } + + @Test + void getInterrogationToFollowUpPaginated_shouldWork_when_responseIsNull() { + //Prepare + String partitionId = "PartitionIDXX77"; + long page = 68; + Optional isToFollowUp = Optional.of(Boolean.TRUE); + + mockRetrieveBody(null); + //Call method under tests + PageResponse response = service.getInterrogationToFollowUpPaginated(partitionId, page, isToFollowUp); + + assertCorrectPageResponseForNull(response); + } +} \ No newline at end of file diff --git a/src/test/java/fr/insee/protools/backend/service/platine/service/PlatineQuestionnaireServiceTest.java b/src/test/java/fr/insee/protools/backend/service/platine/service/PlatineQuestionnaireServiceTest.java new file mode 100644 index 00000000..61f9606c --- /dev/null +++ b/src/test/java/fr/insee/protools/backend/service/platine/service/PlatineQuestionnaireServiceTest.java @@ -0,0 +1,60 @@ +package fr.insee.protools.backend.service.platine.service; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.JsonNodeFactory; +import fr.insee.protools.backend.service.utils.TestServiceWithRestClient; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import static fr.insee.protools.backend.restclient.configuration.ApiConfigProperties.KNOWN_API.KNOWN_API_PLATINE_QUESTIONNAIRE; +import static fr.insee.protools.backend.utils.data.InterroExamples.generateEmptyInterro; +import static org.mockito.Mockito.verify; + +@ExtendWith(MockitoExtension.class) +class PlatineQuestionnaireServiceTest extends TestServiceWithRestClient { + + @InjectMocks + PlatineQuestionnaireServiceImpl service; + + @Test + void postContext_should_call_correctURIAndBody(){ + //Prepare + JsonNode contextNode = JsonNodeFactory.instance.objectNode(); + + //Call method under test + service.postContext("TOTO", contextNode); + + //Verifications + verify(restClientHelper).getRestClient(KNOWN_API_PLATINE_QUESTIONNAIRE); + verify(restClient).post(); + // Then - Verify that the uri method was called with "/context" + verify(requestBodyUriSpec).uri("/context"); + // and with expected body + verify(requestBodyUriSpec).body(contextNode); + } + + @Test + void postInterrogations_should_makeCorrectCall() { + //Prepare + List interroList = IntStream.range(0, 100) + .mapToObj(i -> generateEmptyInterro().interro()) // Call your function and get the JsonNode + .collect(Collectors.toList()); + + //Call method under tests + service.postInterrogations("TOTO", interroList); + + //Verify + verify(restClientHelper).getRestClient(KNOWN_API_PLATINE_QUESTIONNAIRE); + verify(restClient).post(); + verify(requestBodyUriSpec).uri("/interrogations"); + // and with expected body + verify(requestBodyUriSpec).body(interroList); + } + +} \ No newline at end of file diff --git a/src/test/java/fr/insee/protools/backend/service/platine/utils/PlatineHelperTest.java b/src/test/java/fr/insee/protools/backend/service/platine/utils/PlatineHelperTest.java deleted file mode 100644 index 6cba1e11..00000000 --- a/src/test/java/fr/insee/protools/backend/service/platine/utils/PlatineHelperTest.java +++ /dev/null @@ -1,20 +0,0 @@ -package fr.insee.protools.backend.service.platine.utils; - -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.junit.jupiter.MockitoExtension; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -@ExtendWith(MockitoExtension.class) -class PlatineHelperTest { - - @Test - void computePilotagePartitionID_should_returnConcat(){ - assertEquals("A1",PlatineHelper.computePilotagePartitionID("A",1l)); - assertEquals("AAAAAAAAA1",PlatineHelper.computePilotagePartitionID("AAAAAAAAA",1l)); - assertEquals(null,PlatineHelper.computePilotagePartitionID(null,1l)); - assertEquals(null,PlatineHelper.computePilotagePartitionID("1",null)); - assertEquals(null,PlatineHelper.computePilotagePartitionID(null,null)); - } -} \ No newline at end of file diff --git a/src/test/java/fr/insee/protools/backend/service/rem/RemDtoUtilsTest.java b/src/test/java/fr/insee/protools/backend/service/rem/RemDtoUtilsTest.java deleted file mode 100644 index 273073f5..00000000 --- a/src/test/java/fr/insee/protools/backend/service/rem/RemDtoUtilsTest.java +++ /dev/null @@ -1,194 +0,0 @@ -package fr.insee.protools.backend.service.rem; - -import fr.insee.protools.backend.service.exception.IncorrectSUBPMNError; -import fr.insee.protools.backend.dto.rem.PersonDto; -import fr.insee.protools.backend.dto.rem.REMSurveyUnitDto; -import org.apache.commons.lang3.tuple.Pair; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; -import org.mockito.junit.jupiter.MockitoExtension; - -import java.util.List; -import java.util.Optional; -import java.util.stream.Stream; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.*; - -@ExtendWith(MockitoExtension.class) -class RemDtoUtilsTest { - - static PersonDto person1_main_surveyed = PersonDto.builder().index(1).main(Boolean.TRUE).surveyed(Boolean.TRUE).coDeclarant(Boolean.FALSE).build(); - static PersonDto person2_main = PersonDto.builder().index(2).main(Boolean.TRUE).surveyed(Boolean.FALSE).coDeclarant(Boolean.FALSE).build(); - static PersonDto person3_surveyed = PersonDto.builder().index(3).main(Boolean.FALSE).surveyed(Boolean.TRUE).coDeclarant(Boolean.FALSE).build(); - - static PersonDto person4_main_surveyed_codeclarant = PersonDto.builder().index(4).main(Boolean.TRUE).surveyed(Boolean.TRUE).coDeclarant(Boolean.TRUE).build(); - static PersonDto person5_main_codeclarant = PersonDto.builder().index(5).main(Boolean.TRUE).surveyed(Boolean.FALSE).coDeclarant(Boolean.TRUE).build(); - static PersonDto person6_surveyed_codeclarant = PersonDto.builder().index(6).main(Boolean.FALSE).surveyed(Boolean.TRUE).coDeclarant(Boolean.TRUE).build(); - - static PersonDto person7_main_surveyed_codeclarantNull = PersonDto.builder().index(7).main(Boolean.TRUE).surveyed(Boolean.TRUE).coDeclarant(null).build(); - static PersonDto person8 = PersonDto.builder().index(8).main(Boolean.FALSE).surveyed(Boolean.FALSE).coDeclarant(Boolean.FALSE).build(); - static PersonDto person9 = PersonDto.builder().index(9).main(Boolean.FALSE).surveyed(Boolean.FALSE).coDeclarant(Boolean.FALSE).build(); - static PersonDto person10_codeclarant = PersonDto.builder().index(10).main(Boolean.FALSE).surveyed(Boolean.FALSE).coDeclarant(Boolean.TRUE).build(); - - - private static Stream findContactIndividuArgument() { - return Stream.of( - //Run method under test : 1 person surveyed - Arguments.of(REMSurveyUnitDto.builder().persons(List.of(person3_surveyed)).build(),3), - //Run method under test : 2 person including 1 surveyed - Arguments.of(REMSurveyUnitDto.builder().persons(List.of(person3_surveyed, person2_main)).build(),3), - //Run method under test : 2 person including 1 surveyed (swapped) - Arguments.of(REMSurveyUnitDto.builder().persons(List.of(person2_main, person3_surveyed)).build(),3), - //Run method under test : 3 person including 1 surveyed (reswap) - Arguments.of(REMSurveyUnitDto.builder().persons(List.of(person8, person3_surveyed, person9)).build(),3), - //Run method under test : 3 person including 1 surveyed (swapped 1) - Arguments.of(REMSurveyUnitDto.builder().persons(List.of(person3_surveyed, person9, person8)).build(),3), - Arguments.of(REMSurveyUnitDto.builder().persons(List.of(person9, person8, person3_surveyed)).build(),3), - Arguments.of(REMSurveyUnitDto.builder().persons(List.of(person9, person8, person8,person8,person8,person8,person8,person8,person8,person8,person3_surveyed)).build(),3) - - ); - } - - private static Stream findContactIndividuArgument_noSurveyed() { - return Stream.of( - Arguments.of(REMSurveyUnitDto.builder().persons(List.of(person2_main)).build()), - Arguments.of(REMSurveyUnitDto.builder().persons(List.of(person2_main, person5_main_codeclarant)).build()), - Arguments.of(REMSurveyUnitDto.builder().persons(List.of(person2_main, person5_main_codeclarant,person9,person8)).build()) - ); - } - - @ParameterizedTest - @MethodSource("findContactIndividuArgument_noSurveyed") - void findContactIndividu_shouldThrow_whenNoSurved(REMSurveyUnitDto su) { - assertThrows(IncorrectSUBPMNError.class, () -> RemDtoUtils.findContact(null, su, false)); - } - - - @ParameterizedTest - @MethodSource("findContactIndividuArgument") - void findContact_shouldWork_for_individu(REMSurveyUnitDto su, int expectedContactIndex) { - PersonDto res = RemDtoUtils.findContact(null, su, false); - //Check - assertEquals(res.getIndex(), expectedContactIndex); - } - - - - private static Stream findContactLogementArgument() { - return Stream.of( - //Run method under test : 1 person main - Arguments.of(REMSurveyUnitDto.builder().persons(List.of(person2_main)).build(),2), - Arguments.of(REMSurveyUnitDto.builder().persons(List.of(person5_main_codeclarant)).build(),5), - //Run method under test : 2 person including 1 main - Arguments.of(REMSurveyUnitDto.builder().persons(List.of(person2_main, person3_surveyed)).build(),2), - //Run method under test : 2 person including 1 main (swapped) - Arguments.of(REMSurveyUnitDto.builder().persons(List.of(person3_surveyed, person2_main)).build(),2), - //Run method under test : 3 person including 1 main - Arguments.of(REMSurveyUnitDto.builder().persons(List.of(person8, person2_main, person9)).build(),2), - //Run method under test : 3 person including 1 surveyed (swapped 1) - Arguments.of(REMSurveyUnitDto.builder().persons(List.of(person2_main, person9, person8)).build(),2), - Arguments.of(REMSurveyUnitDto.builder().persons(List.of(person9, person8, person2_main)).build(),2), - Arguments.of(REMSurveyUnitDto.builder().persons(List.of(person9, person8, person8,person8,person8,person8,person8,person8,person8,person8,person5_main_codeclarant)).build(),5), - //2 mains - Arguments.of(REMSurveyUnitDto.builder().persons(List.of(person9, person8, person8,person8,person8,person8,person8,person8,person8,person8,person5_main_codeclarant,person2_main)).build(),5) - - ); - } - - private static Stream findContactLogementArgument_noMain() { - return Stream.of( - Arguments.of(REMSurveyUnitDto.builder().persons(List.of(person3_surveyed)).build()), - Arguments.of(REMSurveyUnitDto.builder().persons(List.of(person3_surveyed, person9)).build()), - Arguments.of(REMSurveyUnitDto.builder().persons(List.of(person3_surveyed,person9,person8)).build()) - - ); - } - - @ParameterizedTest - @MethodSource("findContactLogementArgument_noMain") - void findContact_shouldThrow_whenNoSurved_for_logment(REMSurveyUnitDto su) { - assertThrows(IncorrectSUBPMNError.class, () -> RemDtoUtils.findContact(null, su, true)); - } - - @ParameterizedTest - @MethodSource("findContactLogementArgument") - void findContactAndSecondary_shouldWork_for_logement(REMSurveyUnitDto su, int expectedContactIndex) { - PersonDto res = RemDtoUtils.findContact(null, su, true); - //Check - assertEquals(res.getIndex(), expectedContactIndex); - } - - - private static Stream findContactAndSecondaryIndividuArgument() { - return Stream.of( - //Run method under test : 1 person surveyed - Arguments.of(REMSurveyUnitDto.builder().persons(List.of(person3_surveyed)).build(),3,-1), - Arguments.of(REMSurveyUnitDto.builder().persons(List.of(person1_main_surveyed)).build(),1,-1), - //2 Persons ; 1 Main/Surveyed - 1 N/A - Arguments.of(REMSurveyUnitDto.builder().persons(List.of(person1_main_surveyed,person8)).build(),1,-1), - Arguments.of(REMSurveyUnitDto.builder().persons(List.of(person8,person1_main_surveyed)).build(),1,-1), - Arguments.of(REMSurveyUnitDto.builder().persons(List.of(person3_surveyed,person8)).build(),3,-1), - - //2 or 3 Persons : 1 Main/Surveyed - 1 Declarant - Arguments.of(REMSurveyUnitDto.builder().persons(List.of(person1_main_surveyed,person10_codeclarant)).build(),1,10), - Arguments.of(REMSurveyUnitDto.builder().persons(List.of(person1_main_surveyed,person10_codeclarant,person9)).build(),1,10), - Arguments.of(REMSurveyUnitDto.builder().persons(List.of(person8,person1_main_surveyed,person10_codeclarant,person9)).build(),1,10), - //2 or 3 Persons : 1 Surveyed (not main) - 1 Main - Arguments.of(REMSurveyUnitDto.builder().persons(List.of(person3_surveyed,person2_main)).build(),3,2), - Arguments.of(REMSurveyUnitDto.builder().persons(List.of(person3_surveyed,person5_main_codeclarant)).build(),3,5), - Arguments.of(REMSurveyUnitDto.builder().persons(List.of(person8,person3_surveyed,person5_main_codeclarant)).build(),3,5), - Arguments.of(REMSurveyUnitDto.builder().persons(List.of(person8,person3_surveyed,person5_main_codeclarant,person9)).build(),3,5) - ); - } - @ParameterizedTest - @MethodSource("findContactAndSecondaryIndividuArgument") - void findContactAndSecondary_shouldWork_for_individu(REMSurveyUnitDto su, int expectedFirstContactIndex, int expectedSecondContact) { - Pair> res = RemDtoUtils.findContactAndSecondary(null, su, false); - //Check - assertEquals(res.getLeft().getIndex(), expectedFirstContactIndex); - if(expectedSecondContact==-1){ - assertThat(res.getRight()).isEmpty(); - } - else{ - assertThat(res.getRight().get().getIndex()).isEqualTo(expectedSecondContact); - } - } - - - - private static Stream findContactAndSecondaryLogementArgument() { - return Stream.of( - //Run method under test : 1 person surveyed - Arguments.of(REMSurveyUnitDto.builder().persons(List.of(person2_main)).build(),2,-1), - Arguments.of(REMSurveyUnitDto.builder().persons(List.of(person1_main_surveyed)).build(),1,-1), - //2/3 Persons ; 1 Main - 1 N/A - Arguments.of(REMSurveyUnitDto.builder().persons(List.of(person1_main_surveyed,person8)).build(),1,-1), - Arguments.of(REMSurveyUnitDto.builder().persons(List.of(person8,person1_main_surveyed)).build(),1,-1), - Arguments.of(REMSurveyUnitDto.builder().persons(List.of(person2_main,person8)).build(),2,-1), - Arguments.of(REMSurveyUnitDto.builder().persons(List.of(person9,person2_main,person8)).build(),2,-1), - - //2 or 3 Persons : 1 Main - 1 Declarant - Arguments.of(REMSurveyUnitDto.builder().persons(List.of(person1_main_surveyed,person10_codeclarant)).build(),1,10), - Arguments.of(REMSurveyUnitDto.builder().persons(List.of(person1_main_surveyed,person10_codeclarant,person9)).build(),1,10), - Arguments.of(REMSurveyUnitDto.builder().persons(List.of(person8,person1_main_surveyed,person10_codeclarant,person9)).build(),1,10), - Arguments.of(REMSurveyUnitDto.builder().persons(List.of(person8,person7_main_surveyed_codeclarantNull,person10_codeclarant,person9)).build(),7,10) - ); - } - @ParameterizedTest - @MethodSource("findContactAndSecondaryLogementArgument") - void findContactAndSecondary_shouldWork_for_Logement(REMSurveyUnitDto su, int expectedFirstContactIndex, int expectedSecondContact) { - Pair> res = RemDtoUtils.findContactAndSecondary(null, su, true); - //Check - assertEquals(res.getLeft().getIndex(), expectedFirstContactIndex); - if(expectedSecondContact==-1){ - assertThat(res.getRight()).isEmpty(); - } - else{ - assertThat(res.getRight().get().getIndex()).isEqualTo(expectedSecondContact); - } - } -} \ No newline at end of file diff --git a/src/test/java/fr/insee/protools/backend/service/rem/RemServiceImplTest.java b/src/test/java/fr/insee/protools/backend/service/rem/RemServiceImplTest.java new file mode 100644 index 00000000..225658a4 --- /dev/null +++ b/src/test/java/fr/insee/protools/backend/service/rem/RemServiceImplTest.java @@ -0,0 +1,297 @@ +package fr.insee.protools.backend.service.rem; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import fr.insee.protools.backend.dto.rem_tmp.InterrogationAccountDto; +import fr.insee.protools.backend.dto.rem_tmp.InterrogationIdentifiersDto; +import fr.insee.protools.backend.restclient.exception.runtime.HttpClient4xxBPMNError; +import fr.insee.protools.backend.restclient.pagination.PageResponse; +import fr.insee.protools.backend.service.utils.TestServiceWithRestClient; +import org.hamcrest.collection.IsIterableContainingInAnyOrder; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.InjectMocks; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; +import org.springframework.web.util.UriBuilder; + +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import static fr.insee.protools.backend.restclient.configuration.ApiConfigProperties.KNOWN_API.KNOWN_API_REM; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; + +@ExtendWith(MockitoExtension.class) +class RemServiceImplTest extends TestServiceWithRestClient { + static ObjectMapper objectMapper = new ObjectMapper(); + @InjectMocks + RemServiceImpl service; + + @Value("${fr.insee.protools.api.rem.interrogation.page.size:5000}") + private int pageSizeGetInterro; + + @Test + void getPartitionAllInterroPaginated_should_makeCorrectCalls() { + //Prepare + String partitionId = "PartitionIDXXREM"; + long page = 1024; + + List mockedResponse = List.of(objectMapper.createObjectNode().put("xxx", 1).put("66969jj", "toto")); + mockRetrieveBodyResponse(mockedResponse); + //Call method under tests + PageResponse response = service.getPartitionAllInterroPaginated(partitionId, page); + + //Verify + verify(restClientHelper).getRestClient(KNOWN_API_REM); + verify(restClient).get(); + + UriBuilder mockUriBuilder = mockGETURIBuilderAndPrepareForTest(); + + // Verify that the correct path and query parameters were used + verify(mockUriBuilder).path("/interrogations"); + verify(mockUriBuilder).queryParam("page", page); + verify(mockUriBuilder).queryParam("size", pageSizeGetInterro); + verify(mockUriBuilder).queryParam("partition_id", partitionId); + + assertEquals(mockedResponse, response.getContent(), "The response is not what was expected/mocked"); + } + + + @Test + void getPartitionAllInterroPaginated_shouldCatch() { + //Prepare + String partitionId = "PartitionIDYY"; + long page = 0; + + mockMakeRetrieveThrow(HttpStatusCode.valueOf(HttpStatus.BAD_REQUEST.value())); + //Call method under tests + assertThrows(HttpClient4xxBPMNError.class, () -> service.getPartitionAllInterroPaginated(partitionId, page)); + } + + @Test + void getPartitionAllInterroPaginated_shouldCatch_404() { + //Prepare + String partitionId = "PartitionIDYY"; + long page = 0; + + mockMakeRetrieveThrow(HttpStatusCode.valueOf(HttpStatus.NOT_FOUND.value())); + //Call method under tests + HttpClient4xxBPMNError exception = assertThrows(HttpClient4xxBPMNError.class, () -> service.getPartitionAllInterroPaginated(partitionId, page)); + assertThat(exception.getMessage(), containsString("404")); + } + + + @Test + void getPartitionAllInterroPaginated_shouldWork_when_responseIsNull() { + //Prepare + String partitionId = "PartitionIDYY"; + long page = 0; + + mockRetrieveBody(null); + //Call method under tests + PageResponse response = service.getPartitionAllInterroPaginated(partitionId, page); + + assertCorrectPageResponseForNull(response); + } + + @Test + void getInterrogationIdsWithoutAccountForPartition_should_makeCorrectCalls() { + //Prepare + String partitionId = "PartitionIDXXREM"; + UUID expectedID1=UUID.randomUUID(); + UUID expectedID2=UUID.randomUUID(); + + + List mockedResponse = + List.of( + InterrogationIdentifiersDto.builder() + .interrogationId(expectedID1).surveyUnitId(UUID.randomUUID()).originId(UUID.randomUUID().toString()) + .build() + , + InterrogationIdentifiersDto.builder() + .interrogationId(expectedID2).surveyUnitId(UUID.randomUUID()).originId(UUID.randomUUID().toString()) + .build() + ); + mockRetrieveBody(mockedResponse); + + //Call method under tests + List response = service.getInterrogationIdsWithoutAccountForPartition(partitionId); + + //Verify + verify(restClientHelper).getRestClient(KNOWN_API_REM); + verify(restClient).get(); + + UriBuilder mockUriBuilder = mockGETURIBuilderAndPrepareForTest(); + + // Verify that the correct path and query parameters were used + verify(mockUriBuilder).path("/interrogations/ids"); + verify(mockUriBuilder).queryParam("hasAccount", false); + verify(mockUriBuilder).queryParam("partition_id", partitionId); + + assertThat(response, + IsIterableContainingInAnyOrder.containsInAnyOrder(expectedID1.toString(),expectedID2.toString())); + } + + + @Test + void getInterrogationIdsWithoutAccountForPartition_shouldCatch() { + //Prepare + String partitionId = "PartitionIDYY"; + + mockMakeRetrieveThrow(HttpStatusCode.valueOf(HttpStatus.BAD_REQUEST.value())); + //Call method under tests + assertThrows(HttpClient4xxBPMNError.class, () -> service.getInterrogationIdsWithoutAccountForPartition(partitionId)); + } + + @Test + void getInterrogationIdsWithoutAccountForPartition_shouldCatch_404() { + //Prepare + String partitionId = "PartitionIDYxY"; + + mockMakeRetrieveThrow(HttpStatusCode.valueOf(HttpStatus.NOT_FOUND.value())); + //Call method under tests + HttpClient4xxBPMNError exception = assertThrows(HttpClient4xxBPMNError.class, () -> service.getInterrogationIdsWithoutAccountForPartition(partitionId)); + assertThat(exception.getMessage(), containsString("404")); + } + + @Test + void patchInterrogationsSetAccounts() { + //Prepare + Map userByInterroId = Map.of( + UUID.randomUUID().toString(), "USER1", + UUID.randomUUID().toString(), "USER2", + UUID.randomUUID().toString(), "USER3", + UUID.randomUUID().toString(), "USER4"); + + //Call method under tests + service.patchInterrogationsSetAccounts(userByInterroId); + + //Verify + verify(restClientHelper).getRestClient(KNOWN_API_REM); + verify(restClient).patch(); + verify(requestBodyUriSpec).uri("/interrogations/account"); + // and with expected body + final ArgumentCaptor> bodyCaptor + = ArgumentCaptor.forClass((Class) List.class); + verify(requestBodyUriSpec).body(bodyCaptor.capture()); + + List> bodyValues = bodyCaptor.getAllValues(); + assertEquals(1, bodyValues.size(), "We should have exactly one value"); + List bodyListDto = bodyValues.get(0); + + assertEquals(userByInterroId.size(), bodyListDto.size(), "Wrong number of elements in the body"); + + boolean allMatch = userByInterroId.entrySet().stream() + .allMatch(entry -> + bodyListDto.stream().anyMatch(dto -> + dto.getInterrogationId().toString().equals(entry.getKey()) && + dto.getAccount().equals(entry.getValue()) + ) + ); + assertTrue(allMatch, "Body does not match the input"); + } + + + @Test + void putContactsPlatine_should_call_correctURIAndBody() { + //Prepare + List listNodes = IntStream.range(0, 25) + .mapToObj(i -> + objectMapper.createObjectNode().put("id", UUID.randomUUID().toString()).put("toto", i) + ) + .collect(Collectors.toList()); + + //Call method under tests + service.putContactsPlatine(listNodes); + + //Verify + verify(restClientHelper).getRestClient(KNOWN_API_REM); verify(restClient).put(); + verify(restClient).put(); + + verify(requestBodyUriSpec).uri("/contacts-platine"); + // and with expected body + verify(requestBodyUriSpec).body(listNodes); + } + + @Test + void putContactsPlatine_should_NotCallIfEmpty() { + //Prepare + List listNodes = List.of(); + + //Call method under tests + service.putContactsPlatine(listNodes); + + //Verify + verify(restClient, never()).put(); + verify(requestBodyUriSpec, never()).uri(anyString()); + } + + @Test + void putContactsPlatine_should_NotCallIfNull() { + //Prepare + List listNodes = null; + + //Call method under tests + service.putContactsPlatine(listNodes); + + //Verify + verify(restClient, never()).put(); + verify(requestBodyUriSpec, never()).uri(anyString()); + } + + @Test + void postRemiseEnCollecte_should_call_correctURIAndBody() { + //Prepare + List listNodes = IntStream.range(0, 69) + .mapToObj(i -> + objectMapper.createObjectNode().put("id", UUID.randomUUID().toString()).put("toto", i) + ) + .collect(Collectors.toList()); + + //Call method under tests + service.postRemiseEnCollecte(listNodes); + + //Verify + verify(requestBodyUriSpec).uri("/remise-en-collecte"); + verify(restClient).post(); + // and with expected body + verify(requestBodyUriSpec).body(listNodes); + } + + @Test + void postRemiseEnCollecte_should_NotCallIfEmpty() { + //Prepare + List listNodes = List.of(); + + //Call method under tests + service.postRemiseEnCollecte(listNodes); + + //Verify + verify(restClient, never()).post(); + verify(requestBodyUriSpec, never()).uri(anyString()); + } + + @Test + void postRemiseEnCollecte_should_NotCallIfNull() { + //Prepare + List listNodes = null; + + //Call method under tests + service.postRemiseEnCollecte(listNodes); + + //Verify + verify(restClient, never()).post(); + verify(requestBodyUriSpec, never()).uri(anyString()); + } +} \ No newline at end of file diff --git a/src/test/java/fr/insee/protools/backend/service/rem/delegate/ExtractContactIdentifierFromREMSUTaskTest.java b/src/test/java/fr/insee/protools/backend/service/rem/delegate/ExtractContactIdentifierFromREMSUTaskTest.java deleted file mode 100644 index 9b110583..00000000 --- a/src/test/java/fr/insee/protools/backend/service/rem/delegate/ExtractContactIdentifierFromREMSUTaskTest.java +++ /dev/null @@ -1,119 +0,0 @@ -package fr.insee.protools.backend.service.rem.delegate; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import fr.insee.protools.backend.service.exception.IncorrectSUBPMNError; -import fr.insee.protools.backend.service.utils.TestWithContext; -import org.flowable.common.engine.api.FlowableIllegalArgumentException; -import org.flowable.engine.delegate.DelegateExecution; -import org.flowable.engine.test.FlowableTest; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.junit.jupiter.MockitoExtension; - -import static fr.insee.protools.backend.service.FlowableVariableNameConstants.VARNAME_DIRECTORYACCESS_ID_CONTACT; -import static fr.insee.protools.backend.service.FlowableVariableNameConstants.VARNAME_REM_SURVEY_UNIT; -import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.*; - -@ExtendWith(MockitoExtension.class) -@FlowableTest -class ExtractContactIdentifierFromREMSUTaskTest extends TestWithContext { - - - @Test - @DisplayName("ExtractContactIdentifierFromREMSUTask should throw an exception when the VARNAME_REM_SURVEY_UNIT variable is missing") - void execute_should_throw_when_variable_missing() { - //Prepare - DelegateExecution execution = createMockedExecution(); - ExtractContactIdentifierFromREMSUTask extractTask = new ExtractContactIdentifierFromREMSUTask(); - - //No variable set ==> Error - assertThrows(FlowableIllegalArgumentException.class, () -> extractTask.execute(execution)); - - //Wrong Type ==> Error - lenient().doReturn(Boolean.FALSE).when(execution).getVariable(VARNAME_REM_SURVEY_UNIT, Boolean.class); - assertThrows(FlowableIllegalArgumentException.class, () -> extractTask.execute(execution)); - - } - - @Test - void execute_should_thow_when_variable_OKand_UEJson_NOT_OK() throws JsonProcessingException { - //Prepare - DelegateExecution execution = mock(DelegateExecution.class); - doReturn(dumyId).when(execution).getProcessInstanceId(); - ExtractContactIdentifierFromREMSUTask extractTask = new ExtractContactIdentifierFromREMSUTask(); - ObjectMapper objectMapper = new ObjectMapper(); - - - //JSon content with missing additionalInformations node - String content = - """ - { - "otherIdentifier": null, - "missing_tag": [ ] - } - """; - doReturn(objectMapper.readTree(content)).when(execution).getVariable(VARNAME_REM_SURVEY_UNIT, JsonNode.class); - //Execute - assertThrows(IncorrectSUBPMNError.class, () -> extractTask.execute(execution)); - - //JSon content with missing identifiantCompte key - content = - """ - { - "otherIdentifier": null, - "additionalInformations": [ - { - "key": "xxxx", - "value": "xxxxxxxxxx" - }, - { - "key": "yyyyyy", - "value": "yyyyyyyyyyyyyyyy" - } ] - } - """; - doReturn(objectMapper.readTree(content)).when(execution).getVariable(VARNAME_REM_SURVEY_UNIT, JsonNode.class); - //Execute - assertThrows(IncorrectSUBPMNError.class, () -> extractTask.execute(execution)); - } - - @Test - void execute_should_work_when_variable_and_UEJson_OK() throws JsonProcessingException { - //Prepare - DelegateExecution execution = mock(DelegateExecution.class); - doReturn(dumyId).when(execution).getProcessInstanceId(); - - ExtractContactIdentifierFromREMSUTask extractTask = new ExtractContactIdentifierFromREMSUTask(); - ObjectMapper objectMapper = new ObjectMapper(); - final String content = - """ - { - "otherIdentifier": null, - "additionalInformations": [ - { - "key": "xxxx", - "value": "xxxxxxxxxx" - }, - { - "key": "identifiantCompte", - "value": "TOTO_55" - }, - { - "key": "yyyyyy", - "value": "yyyyyyyyyyyyyyyy" - } ] - } - """; - doReturn(objectMapper.readTree(content)).when(execution).getVariable(VARNAME_REM_SURVEY_UNIT, JsonNode.class); - - //Execute - assertDoesNotThrow(() -> extractTask.execute(execution)); - - verify(execution).setVariableLocal(VARNAME_DIRECTORYACCESS_ID_CONTACT, "TOTO_55"); - } -} \ No newline at end of file diff --git a/src/test/java/fr/insee/protools/backend/service/rem/delegate/RemGetPartitionListOfInterroPaginatedTaskTest.java b/src/test/java/fr/insee/protools/backend/service/rem/delegate/RemGetPartitionListOfInterroPaginatedTaskTest.java new file mode 100644 index 00000000..561bd5d2 --- /dev/null +++ b/src/test/java/fr/insee/protools/backend/service/rem/delegate/RemGetPartitionListOfInterroPaginatedTaskTest.java @@ -0,0 +1,49 @@ +package fr.insee.protools.backend.service.rem.delegate; + +import fr.insee.protools.backend.restclient.pagination.PageResponse; +import fr.insee.protools.backend.service.rem.RemServiceImpl; +import fr.insee.protools.backend.service.utils.delegate.IDelegateWithVariableGetPaginated; +import org.flowable.engine.delegate.JavaDelegate; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.Map; + +import static fr.insee.protools.backend.service.FlowableVariableNameConstants.VARNAME_CURRENT_PARTITION_ID; +import static fr.insee.protools.backend.service.FlowableVariableNameConstants.VARNAME_REM_INTERRO_LIST; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.lenient; + +@ExtendWith(MockitoExtension.class) +class RemGetPartitionListOfInterroPaginatedTaskTest implements IDelegateWithVariableGetPaginated { + + @Mock + RemServiceImpl remService; + @InjectMocks + RemGetPartitionListOfInterroPaginatedTask task; + + @Override + public JavaDelegate getTaskUnderTest() { + return task; + } + + @Override + public Map getVariablesAndTypes() { + return Map.of( + VARNAME_CURRENT_PARTITION_ID, String.class + ); + } + + @Override + public void initReadValueMock(PageResponse expectedPageResponse) { + lenient().doReturn(expectedPageResponse).when(remService).getPartitionAllInterroPaginated(anyString(), anyLong()); + } + + @Override + public String getOutListVariableName() { + return VARNAME_REM_INTERRO_LIST; + } +} \ No newline at end of file diff --git a/src/test/java/fr/insee/protools/backend/service/rem/delegate/RemGetPartitionListOfSuIdTaskTest.java b/src/test/java/fr/insee/protools/backend/service/rem/delegate/RemGetPartitionListOfSuIdTaskTest.java deleted file mode 100644 index 6cf5d4b4..00000000 --- a/src/test/java/fr/insee/protools/backend/service/rem/delegate/RemGetPartitionListOfSuIdTaskTest.java +++ /dev/null @@ -1,115 +0,0 @@ -package fr.insee.protools.backend.service.rem.delegate; - -import com.fasterxml.jackson.core.JsonProcessingException; -import fr.insee.protools.backend.service.context.ContextService; -import fr.insee.protools.backend.service.rem.RemService; -import org.flowable.common.engine.api.FlowableIllegalArgumentException; -import org.flowable.engine.delegate.DelegateExecution; -import org.flowable.engine.test.FlowableTest; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.Spy; -import org.mockito.junit.jupiter.MockitoExtension; -import org.springframework.util.ClassUtils; - -import java.util.List; - -import static fr.insee.protools.backend.service.FlowableVariableNameConstants.VARNAME_CURRENT_PARTITION_ID; -import static fr.insee.protools.backend.service.FlowableVariableNameConstants.VARNAME_REM_SU_ID_LIST; -import static fr.insee.protools.backend.service.utils.FlowableVariableUtils.getMissingVariableMessage; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.*; - - -@ExtendWith(MockitoExtension.class) -@FlowableTest -class RemGetPartitionListOfSuIdTaskTest { - - - @Mock RemService remService; - @Spy ContextService protoolsContext; - - @InjectMocks RemGetPartitionListOfSuIdTask remGetPartitionListOfSuIdTask; - - String dumyId = "ID1"; - - final static String ressourceFolder = ClassUtils.convertClassNameToResourcePath(RemGetPartitionListOfSuIdTaskTest.class.getPackageName()); - - final String json1Partition = - "{ \"partitions\": [{ " + - " \"id\": 1" + - " }]" + - "}"; - - /* - @Test - void execute_should_throw_BadContextIncorrectException_when_noContext() { - //Precondition - DelegateExecution execution = mock(DelegateExecution.class); - when(execution.getProcessInstanceId()).thenReturn(dumyId); - - //Execute the unit under test - assertThrows(BadContextIncorrectException.class, () -> remGetPartitionListOfSuIdTask.execute(execution)); - } - */ - - - @Test - void execute_should_throw_FlowableIllegalArgumentException_when_variableCurrentPartition_notDefined() throws JsonProcessingException { - //Precondition - DelegateExecution execution = mock(DelegateExecution.class); - lenient().when(execution.getProcessInstanceId()).thenReturn(dumyId); - //No context used for this taks - - //Execute the unit under test - FlowableIllegalArgumentException exception = assertThrows(FlowableIllegalArgumentException.class, () -> remGetPartitionListOfSuIdTask.execute(execution)); - assertThat(exception.getMessage()).isEqualTo(getMissingVariableMessage(VARNAME_CURRENT_PARTITION_ID)); - } - - - void execute_should_work_when_contextNpartition_and_variable_OK(String contexte, Long currentPartitionId, Long[] remSuIdList) throws JsonProcessingException { - //Préconditions - DelegateExecution execution = mock(DelegateExecution.class); - DelegateExecution executionParent = mock(DelegateExecution.class); - - when(execution.getProcessInstanceId()).thenReturn(dumyId); - - //No context used by this task - when(execution.getVariable(VARNAME_CURRENT_PARTITION_ID, Long.class)).thenReturn(currentPartitionId); - when(execution.getParent()).thenReturn(executionParent); - - List expectedResult = List.of(remSuIdList); - when(remService.getSampleSuIds(currentPartitionId)).thenReturn(remSuIdList); - //Execute the unit under test - remGetPartitionListOfSuIdTask.execute(execution); - - - //Post conditions - //Service called once and for the right partition - verify(remService).getSampleSuIds(currentPartitionId); - //Process instance variable set with the list of retrieved Ids - verify(executionParent).setVariableLocal(VARNAME_REM_SU_ID_LIST, expectedResult); - } - - @Test - void execute_should_work_when_context1partition_and_variable_OK() throws JsonProcessingException { - Long[] remSuIdList = {1l, 2l, 3l}; - String json1Partition = - "{ \"partitions\": [{ " + - " \"id\": 1" + - " }]" + - "}"; - execute_should_work_when_contextNpartition_and_variable_OK(json1Partition, 1l, remSuIdList); - } - - @Test - void execute_should_work_when_context3partition_and_variable_OK() throws JsonProcessingException { - Long[] remSuIdList = {1l, 2l, 3l}; - String json3Partition = - "{ \"partitions\": [{ \"id\": 1 },{ \"id\": 56 }, { \"id\": 99 }] }"; - execute_should_work_when_contextNpartition_and_variable_OK(json3Partition, 1l, remSuIdList); - } -} \ No newline at end of file diff --git a/src/test/java/fr/insee/protools/backend/service/rem/delegate/RemGetSUTaskTest.java b/src/test/java/fr/insee/protools/backend/service/rem/delegate/RemGetSUTaskTest.java deleted file mode 100644 index 185a4994..00000000 --- a/src/test/java/fr/insee/protools/backend/service/rem/delegate/RemGetSUTaskTest.java +++ /dev/null @@ -1,65 +0,0 @@ -package fr.insee.protools.backend.service.rem.delegate; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import fr.insee.protools.backend.service.rem.RemService; -import fr.insee.protools.backend.dto.rem.REMSurveyUnitDto; -import org.flowable.common.engine.api.FlowableIllegalArgumentException; -import org.flowable.engine.delegate.DelegateExecution; -import org.flowable.engine.test.FlowableTest; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.Spy; -import org.mockito.junit.jupiter.MockitoExtension; - -import static fr.insee.protools.backend.service.FlowableVariableNameConstants.VARNAME_REM_SURVEY_UNIT; -import static fr.insee.protools.backend.service.FlowableVariableNameConstants.VARNAME_REM_SURVEY_UNIT_IDENTIFIER; -import static fr.insee.protools.backend.service.utils.FlowableVariableUtils.getMissingVariableMessage; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.*; - -@ExtendWith(MockitoExtension.class) -@FlowableTest -class RemGetSUTaskTest { - - @Mock RemService remService; - @Spy ObjectMapper objectMapper; - @InjectMocks RemGetSUTask remGetSUTask; - - String dumyId = "ID1"; - - @Test - void execute_should_throw_FlowableIllegalArgumentException_when_variableremSurveyUnitIdentifier_notDefined() throws JsonProcessingException { - //Precondition - DelegateExecution execution = mock(DelegateExecution.class); - lenient().when(execution.getProcessInstanceId()).thenReturn(dumyId); - - //Execute the unit under test - FlowableIllegalArgumentException exception = assertThrows(FlowableIllegalArgumentException.class, () -> remGetSUTask.execute(execution)); - assertThat(exception.getMessage()).isEqualTo(getMissingVariableMessage(VARNAME_REM_SURVEY_UNIT_IDENTIFIER)); - } - - @Test - void execute_should_work_when_variable_OK() { - //Préconditions - DelegateExecution execution = mock(DelegateExecution.class); - Long variableSuId=98455435l; - REMSurveyUnitDto expectedREMSU = REMSurveyUnitDto.builder().externalId("TOTO").build(); - - when(execution.getProcessInstanceId()).thenReturn(dumyId); - when(execution.getVariable(VARNAME_REM_SURVEY_UNIT_IDENTIFIER, Long.class)).thenReturn(variableSuId); - when(remService.getSurveyUnit(variableSuId)).thenReturn(expectedREMSU); - - //Execute the unit under test - remGetSUTask.execute(execution); - - //Post conditions - //Service called once and for the right SU ID - verify(remService).getSurveyUnit(variableSuId); - //Process instance variable set with the retrieved SU content - verify(execution).setVariableLocal(VARNAME_REM_SURVEY_UNIT, objectMapper.valueToTree(expectedREMSU)); - } -} \ No newline at end of file diff --git a/src/test/java/fr/insee/protools/backend/service/rem/delegate/RemPostResmiseEnCollecteTaskRESTTest.java b/src/test/java/fr/insee/protools/backend/service/rem/delegate/RemPostResmiseEnCollecteTaskRESTTest.java new file mode 100644 index 00000000..5915d534 --- /dev/null +++ b/src/test/java/fr/insee/protools/backend/service/rem/delegate/RemPostResmiseEnCollecteTaskRESTTest.java @@ -0,0 +1,128 @@ +package fr.insee.protools.backend.service.rem.delegate; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.read.ListAppender; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import fr.insee.protools.backend.service.rem.RemServiceImpl; +import fr.insee.protools.backend.service.utils.delegate.IDelegateWithVariables; +import org.assertj.core.api.Assertions; +import org.flowable.engine.delegate.DelegateExecution; +import org.flowable.engine.delegate.JavaDelegate; +import org.hamcrest.collection.IsIterableContainingInAnyOrder; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.mockito.ArgumentCaptor; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.slf4j.LoggerFactory; + +import java.util.List; +import java.util.Map; +import java.util.stream.Stream; + +import static fr.insee.protools.backend.service.FlowableVariableNameConstants.*; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.*; + + +@ExtendWith(MockitoExtension.class) +class RemPostResmiseEnCollecteTaskRESTTest implements IDelegateWithVariables { + + private static ObjectMapper objectMapper = new ObjectMapper(); + @Mock + RemServiceImpl remService; + @InjectMocks + RemPostResmiseEnCollecteTaskREST task; + + static Stream initExecuteParametersOK() { + List list1node = List.of(objectMapper.createObjectNode().put("id", 1).put("id", "toto")); + List list2node = List.of( + objectMapper.createObjectNode().put("id", 1).put("id", "toto"), + objectMapper.createObjectNode().put("identifier", 1).put("tata", "toto")); + + return Stream.of( + Arguments.of(list1node), + Arguments.of(list2node)); + } + + @Override + public JavaDelegate getTaskUnderTest() { + return task; + } + + @Override + public Map getVariablesAndTypes() { + return Map.of(VARNAME_INTERRO_REMISE_EN_COLLECTE_LIST, List.class); + } + + @ParameterizedTest + @MethodSource("initExecuteParametersOK") + @DisplayName("Test execute method - should work and make correct call to service") + void execute_should_work_whenEverythingOk(List interros) { + //Prepare + DelegateExecution execution = createMockedExecution(); + doReturn(interros).when(execution).getVariable(VARNAME_INTERRO_REMISE_EN_COLLECTE_LIST, List.class); + + //Execute method under test + task.execute(execution); + + //verify + final ArgumentCaptor> listCaptor = ArgumentCaptor.forClass((Class) List.class); + + verify(remService, times(1)).postRemiseEnCollecte(listCaptor.capture()); + List> allValues = listCaptor.getAllValues(); + assertEquals(1, allValues.size(), "We should have exactly one value"); + + List actualArgument = listCaptor.getValue(); + assertEquals(interros.size(), actualArgument.size(), "The passed list of interros has an incorrect size : Exepected " + interros.size() + " - actual:" + actualArgument.size()); + + //check that we passed the correct items + if (interros.isEmpty()) { + assertThat("If no interro (empty List) ==> should pass an empty list", actualArgument.isEmpty()); + } else { + assertThat(actualArgument, + IsIterableContainingInAnyOrder.containsInAnyOrder(interros.toArray(new Object[0]))); + } + } + + + @Test + @DisplayName("Test execute method - should write a log and not call service when the interro list is empty ") + public void execute_should_writeLog_and_notCallService_when_interroListIsEmpty() { + //Prepare + DelegateExecution execution = createMockedExecution(); + //empty list + doReturn(List.of()).when(execution).getVariable(VARNAME_INTERRO_REMISE_EN_COLLECTE_LIST, List.class); + + // create and start a ListAppender to capture logs + Logger fooLogger = (Logger) LoggerFactory.getLogger(task.getClass()); + ListAppender listAppender = new ListAppender<>(); + fooLogger.addAppender(listAppender); + listAppender.start(); + + //Execute method under test + task.execute(execution); + + //Verify + List logsList = listAppender.list; + Assertions.assertThat(logsList.get(0).getFormattedMessage()) + .contains("begin",execution.getProcessInstanceId()); + + assertEquals(Level.INFO, logsList.get(1) + .getLevel()); + Assertions.assertThat(logsList.get(1).getFormattedMessage()) + .contains("end",execution.getProcessInstanceId(),"Nothing to do"); + + verify(remService,never()).postRemiseEnCollecte(any()); + } +} \ No newline at end of file diff --git a/src/test/java/fr/insee/protools/backend/service/rem/delegate/RemPutContactPlatineTaskRESTTest.java b/src/test/java/fr/insee/protools/backend/service/rem/delegate/RemPutContactPlatineTaskRESTTest.java new file mode 100644 index 00000000..acace749 --- /dev/null +++ b/src/test/java/fr/insee/protools/backend/service/rem/delegate/RemPutContactPlatineTaskRESTTest.java @@ -0,0 +1,121 @@ +package fr.insee.protools.backend.service.rem.delegate; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.read.ListAppender; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import fr.insee.protools.backend.service.rem.RemServiceImpl; +import fr.insee.protools.backend.service.utils.delegate.IDelegateWithVariables; +import org.assertj.core.api.Assertions; +import org.flowable.engine.delegate.DelegateExecution; +import org.flowable.engine.delegate.JavaDelegate; +import org.hamcrest.collection.IsIterableContainingInAnyOrder; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.mockito.ArgumentCaptor; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.slf4j.LoggerFactory; + +import java.util.List; +import java.util.Map; +import java.util.stream.Stream; + +import static fr.insee.protools.backend.service.FlowableVariableNameConstants.*; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +class RemPutContactPlatineTaskRESTTest implements IDelegateWithVariables { + + private static ObjectMapper objectMapper = new ObjectMapper(); + @Mock + RemServiceImpl remService; + @InjectMocks + RemPutContactPlatineTaskREST task; + + static Stream initExecuteParametersOK() { + List list1node = List.of(objectMapper.createObjectNode().put("id", 1).put("id", "toto")); + List list2node = List.of( + objectMapper.createObjectNode().put("id", 1).put("id", "toto"), + objectMapper.createObjectNode().put("identifier", 1).put("tata", "toto")); + + return Stream.of( + Arguments.of(list1node), + Arguments.of(list2node)); + } + + @Override + public JavaDelegate getTaskUnderTest() { + return task; + } + + @Override + public Map getVariablesAndTypes() { + return Map.of(VARNAME_PLATINE_CONTACT_LIST, List.class); + } + + @ParameterizedTest + @MethodSource("initExecuteParametersOK") + @DisplayName("Test execute method - should work and make correct call to service") + void execute_should_work_whenEverythingOk(List contacts) { + //Prepare + DelegateExecution execution = createMockedExecution(); + doReturn(contacts).when(execution).getVariable(VARNAME_PLATINE_CONTACT_LIST, List.class); + + //Execute method under test + task.execute(execution); + + //verify + final ArgumentCaptor> listCaptor = ArgumentCaptor.forClass((Class) List.class); + + verify(remService, times(1)).putContactsPlatine(listCaptor.capture()); + List> allValues = listCaptor.getAllValues(); + assertEquals(1, allValues.size(), "We should have exactly one value"); + + List actualArgument = listCaptor.getValue(); + assertEquals(contacts.size(), actualArgument.size(), "The passed list of contacts has an incorrect size : Exepected " + contacts.size() + " - actual:" + actualArgument.size()); + assertThat(actualArgument, + IsIterableContainingInAnyOrder.containsInAnyOrder(contacts.toArray(new Object[0]))); + } + + @Test + @DisplayName("Test execute method - should write a log and not call service when List of contacts is empty ") + public void execute_should_writeLog_and_notCallService_when_interroListIsEmpty() { + //Prepare + DelegateExecution execution = createMockedExecution(); + doReturn(List.of()).when(execution).getVariable(VARNAME_PLATINE_CONTACT_LIST, List.class); + + // create and start a ListAppender to capture logs + Logger fooLogger = (Logger) LoggerFactory.getLogger(task.getClass()); + ListAppender listAppender = new ListAppender<>(); + fooLogger.addAppender(listAppender); + listAppender.start(); + + //Execute method under test + task.execute(execution); + + //Verify + List logsList = listAppender.list; + Assertions.assertThat(logsList.get(0).getFormattedMessage()) + .contains("begin") + .contains(execution.getProcessInstanceId()); + + assertEquals(Level.INFO, logsList.get(1) + .getLevel()); + Assertions.assertThat(logsList.get(1).getFormattedMessage()) + .contains("end",execution.getProcessInstanceId(),"Nothing to do"); + + verify(remService,never()).putContactsPlatine(any()); + + } +} \ No newline at end of file diff --git a/src/test/java/fr/insee/protools/backend/service/rem/delegate/RemWriteEraSUListTaskTest.java b/src/test/java/fr/insee/protools/backend/service/rem/delegate/RemWriteEraSUListTaskTest.java deleted file mode 100644 index 21ca242b..00000000 --- a/src/test/java/fr/insee/protools/backend/service/rem/delegate/RemWriteEraSUListTaskTest.java +++ /dev/null @@ -1,100 +0,0 @@ -package fr.insee.protools.backend.service.rem.delegate; - -import com.fasterxml.jackson.core.JsonProcessingException; -import fr.insee.protools.backend.dto.era.CensusJsonDto; -import fr.insee.protools.backend.service.rem.RemService; -import fr.insee.protools.backend.dto.rem.SuIdMappingJson; -import fr.insee.protools.backend.dto.rem.SuIdMappingRecord; -import org.flowable.common.engine.api.FlowableIllegalArgumentException; -import org.flowable.engine.delegate.DelegateExecution; -import org.flowable.engine.test.FlowableTest; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -import java.util.List; - -import static fr.insee.protools.backend.service.FlowableVariableNameConstants.*; -import static fr.insee.protools.backend.service.utils.FlowableVariableUtils.getMissingVariableMessage; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.*; - -@ExtendWith(MockitoExtension.class) -@FlowableTest -class RemWriteEraSUListTaskTest { - - @Mock RemService remService; - @InjectMocks RemWriteEraSUListTask remWriteEraSUListTask; - - String dumyId = "ID999"; - - @Test - @DisplayName("Test execute method - should throw if VARNAME_ERA_RESPONSE or VARNAME_CURRENT_PARTITION_ID not initialized") - void execute_should_throw_FlowableIllegalArgumentException_when_variables_notDefined() throws JsonProcessingException { - //Precondition - DelegateExecution execution = mock(DelegateExecution.class); - lenient().when(execution.getProcessInstanceId()).thenReturn(dumyId); - - //Execute the unit under test - FlowableIllegalArgumentException exception = assertThrows(FlowableIllegalArgumentException.class, () -> remWriteEraSUListTask.execute(execution)); - //Post conditions - assertThat(exception.getMessage()).isEqualTo(getMissingVariableMessage(VARNAME_ERA_RESPONSE)); - - - //Create First variable - when(execution.getVariable(VARNAME_ERA_RESPONSE, List.class)).thenReturn(List.of(CensusJsonDto.builder().build())); - - //Execute again - exception = assertThrows(FlowableIllegalArgumentException.class, () -> remWriteEraSUListTask.execute(execution)); - //Check the error - assertThat(exception.getMessage()).isEqualTo(getMissingVariableMessage(VARNAME_CURRENT_PARTITION_ID)); - - } - - @Test - @DisplayName("Test execute method - should tVARNAME_ERA_RESPONSE or VARNAME_CURRENT_PARTITION_ID not initialized") - void execute_should_work_when_variables_Ok() throws JsonProcessingException { - //Precondition - DelegateExecution execution = mock(DelegateExecution.class); - DelegateExecution executionParent = mock(DelegateExecution.class); - when(execution.getParent()).thenReturn(executionParent); - lenient().when(execution.getProcessInstanceId()).thenReturn(dumyId); - - //PArtitionID - Long partitionID = 99l; - //Stubbed list of ERA Values - Long eraId1=500l, eraId2=1000l; - CensusJsonDto eraSU1 = CensusJsonDto.builder() - .id(eraId1) - .build(); - CensusJsonDto eraSU2 = CensusJsonDto.builder() - .id(eraId2) - .build(); - List listOfEraSU = List.of(eraSU1,eraSU2); - lenient().when(execution.getVariable(VARNAME_ERA_RESPONSE, List.class)).thenReturn(listOfEraSU); - lenient().when(execution.getVariable(VARNAME_CURRENT_PARTITION_ID, Long.class)).thenReturn(partitionID); - - //Stubbed list id mapping between ERA SU and created REM SU - long remId1=1l,remId2=2l; - when(remService.writeERASUList(partitionID,listOfEraSU)) - .thenReturn(SuIdMappingJson.builder() - .count(2) - .partitionId(partitionID) - .data( - List.of( - new SuIdMappingRecord(remId1,String.valueOf(eraId1)), - new SuIdMappingRecord(remId2,String.valueOf(eraId2)))) - .build()); - //Execute method under test - assertDoesNotThrow(() -> remWriteEraSUListTask.execute(execution)); - - //Post conditions - verify(remService,times(1)).writeERASUList(partitionID,listOfEraSU); - verify(executionParent,times(1)).setVariableLocal(VARNAME_REM_SU_ID_LIST,List.of(remId1,remId2)); - } -} \ No newline at end of file diff --git a/src/test/java/fr/insee/protools/backend/service/sabiane/SabianeIdHelperTest.java b/src/test/java/fr/insee/protools/backend/service/sabiane/SabianeIdHelperTest.java deleted file mode 100644 index 75a1cca1..00000000 --- a/src/test/java/fr/insee/protools/backend/service/sabiane/SabianeIdHelperTest.java +++ /dev/null @@ -1,31 +0,0 @@ -package fr.insee.protools.backend.service.sabiane; - -import fr.insee.protools.backend.service.exception.IncorrectSUBPMNError; -import org.junit.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.CsvSource; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertThrows; - -class SabianeIdHelperTest { - - @ParameterizedTest - @CsvSource( - { - "1,2,1P2", - "A,B,APB", - "99999999,aJJTJJTTJPPPP,99999999PaJJTJJTTJPPPP" - }) - void computeSabianeID_should_work_when_inputsAreCorrects(String partitionId, String remRepositoryID, String expectedResult) { - assertThat(SabianeIdHelper.computeSabianeID(partitionId,remRepositoryID)).isEqualTo(expectedResult); - } - - @Test - void computeSabianeID_should_throw_when_inputsAreInCorrects() { - assertThrows(IncorrectSUBPMNError.class,() -> SabianeIdHelper.computeSabianeID("99",null)); - assertThrows(IncorrectSUBPMNError.class,() -> SabianeIdHelper.computeSabianeID(null,"99")); - assertThrows(IncorrectSUBPMNError.class,() -> SabianeIdHelper.computeSabianeID(null,null)); - } - -} \ No newline at end of file diff --git a/src/test/java/fr/insee/protools/backend/service/sabiane/delegate/SabianeCtxExamples.java b/src/test/java/fr/insee/protools/backend/service/sabiane/delegate/SabianeCtxExamples.java deleted file mode 100644 index 7e2613d4..00000000 --- a/src/test/java/fr/insee/protools/backend/service/sabiane/delegate/SabianeCtxExamples.java +++ /dev/null @@ -1,70 +0,0 @@ -package fr.insee.protools.backend.service.sabiane.delegate; - -public class SabianeCtxExamples { - - - public static final String ctx_ok_idCampagne_idPartition_typeIndividu_prioritaire = - """ - { - "id": "AAC2023A00", - "partitions": [{ - "id": 99, - "typeEchantillon" : "individu", - "prioritaire": "true" - }] - } - """; - - public static final String ctx_ok_idCampagne_idPartition_typeIndividu_nonPrioritaire = - """ - { - "id": "AAC2023A00", - "partitions": [{ - "id": 99, - "typeEchantillon" : "individu", - "prioritaire": "false" - }] - } - """; - - public static final String ctx_ok_idCampagne_idPartition_typeLogement_prioritaire = - """ - { - "id": "AAC2023A00", - "partitions": [{ - "id": 99, - "typeEchantillon" : "individu", - "prioritaire": "true" - }] - } - """; - - public static final String ctx_ok_idCampagne_idPartition_typeLogement_nonPrioritaire = - """ - { - "id": "AAC2023A00", - "partitions": [{ - "id": 99, - "typeEchantillon" : "individu", - "prioritaire": "false" - }] - } - """; - - public static final String ctx_ok_idCampagne_idQuestionnaireModel_idPartition_questionnaireModelPartition = - """ - { - "id": "AAC2023A00", - "partitions": [{ - "id": 99, - "questionnaireModel": "ID_1" - }], - "questionnaireModels": [ - { - "id": "ID_1" - }] - } - """; - - private SabianeCtxExamples(){} -} diff --git a/src/test/java/fr/insee/protools/backend/service/sabiane/delegate/SabianePilotageCreateContextTaskTest.java b/src/test/java/fr/insee/protools/backend/service/sabiane/delegate/SabianePilotageCreateContextTaskTest.java deleted file mode 100644 index 658791e7..00000000 --- a/src/test/java/fr/insee/protools/backend/service/sabiane/delegate/SabianePilotageCreateContextTaskTest.java +++ /dev/null @@ -1,87 +0,0 @@ -package fr.insee.protools.backend.service.sabiane.delegate; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import fr.insee.protools.backend.ProtoolsTestUtils; -import fr.insee.protools.backend.service.context.ContextService; -import fr.insee.protools.backend.service.context.exception.BadContextIncorrectBPMNError; -import fr.insee.protools.backend.service.sabiane.pilotage.SabianePilotageService; -import fr.insee.protools.backend.dto.sabiane.pilotage.CampaignContextDto; -import fr.insee.protools.backend.service.utils.TestWithContext; -import org.flowable.engine.delegate.DelegateExecution; -import org.flowable.engine.test.FlowableTest; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.ArgumentCaptor; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.Spy; -import org.mockito.junit.jupiter.MockitoExtension; -import org.springframework.util.ClassUtils; - -import java.util.List; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.*; - -@ExtendWith(MockitoExtension.class) -@FlowableTest -class SabianePilotageCreateContextTaskTest extends TestWithContext { - final static String ressourceFolder = ClassUtils.convertClassNameToResourcePath(SabianePilotageCreateContextTaskTest.class.getPackageName()); - final static String sabiane_context_json = ressourceFolder+"/protools-contexte-sabiane.json"; - final static String sabiane_context_incorrect_json = ressourceFolder+"/protools-contexte-sabiane-incorrect.json"; - - @Mock SabianePilotageService platinePilotageService; - @Spy ObjectMapper objectMapper; - - @InjectMocks - SabianePilotageCreateContextTask sabianePilotageTask; - - String dumyId="ID1"; - - @Test - void execute_should_throwError_when_null_context(){ - assertThat_delegate_throwError_when_null_context(sabianePilotageTask); - } - - @Test - void execute_should_throw_BadContextIncorrectException_when_noContext() { - DelegateExecution execution = mock(DelegateExecution.class); - when(execution.getProcessInstanceId()).thenReturn(dumyId); - - //Execute the unit under test - assertThrows(BadContextIncorrectBPMNError.class,() -> sabianePilotageTask.execute(execution)); - } - - @Test - void execute_should_work_when_contextOK() { - DelegateExecution execution = mock(DelegateExecution.class); - when(execution.getProcessInstanceId()).thenReturn(dumyId); - initContexteMockWithFile(sabiane_context_json); - - //Execute the unit under test - sabianePilotageTask.execute(execution); - - //Post conditions : Exactly one call to post platinePilotageService.putMetadata - // it is one call per partition defined in context -// verify(platinePilotageService,times(1)).putMetadata(eq(partitionId), notNull()); - - - //Verify postCampaign - ArgumentCaptor acMetadataDto = ArgumentCaptor.forClass(CampaignContextDto.class); - //Exactly one Call to the postCampaign method - verify(platinePilotageService,times(1)).postCampaign(acMetadataDto.capture()); - List allValues = acMetadataDto.getAllValues(); - assertEquals(1, allValues.size(),"We should have exactly one call to postCampaign"); - - //Simple (redundant) verification of the campaignId - assertEquals("MBG2022X01",allValues.get(0).getCampaign(),"Erreur with generated campaign id"); - //Verification that the sent json is exactly what we expected - CampaignContextDto expectedCampaignDto = ProtoolsTestUtils.asObject(ressourceFolder + "/pilotage_expected_post_campaign.json", CampaignContextDto.class); - assertEquals(expectedCampaignDto,allValues.get(0)); - - } - -} diff --git a/src/test/java/fr/insee/protools/backend/service/sabiane/delegate/SabianePilotageCreateSUTaskTest.java b/src/test/java/fr/insee/protools/backend/service/sabiane/delegate/SabianePilotageCreateSUTaskTest.java deleted file mode 100644 index 3a860ed0..00000000 --- a/src/test/java/fr/insee/protools/backend/service/sabiane/delegate/SabianePilotageCreateSUTaskTest.java +++ /dev/null @@ -1,711 +0,0 @@ -package fr.insee.protools.backend.service.sabiane.delegate; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ObjectNode; -import fr.insee.protools.backend.ProtoolsTestUtils; -import fr.insee.protools.backend.dto.rem.*; -import fr.insee.protools.backend.dto.sabiane.pilotage.*; -import fr.insee.protools.backend.service.context.exception.BadContextIncorrectBPMNError; -import fr.insee.protools.backend.service.exception.IncorrectSUBPMNError; -import fr.insee.protools.backend.service.sabiane.SabianeIdHelper; -import fr.insee.protools.backend.service.sabiane.pilotage.SabianePilotageService; -import fr.insee.protools.backend.service.utils.TestWithContext; -import fr.insee.protools.backend.service.utils.data.CtxExamples; -import fr.insee.protools.backend.service.utils.data.RemSUData; -import org.apache.commons.lang3.tuple.Pair; -import org.flowable.common.engine.api.FlowableIllegalArgumentException; -import org.flowable.engine.delegate.DelegateExecution; -import org.json.JSONException; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.CsvSource; -import org.junit.jupiter.params.provider.MethodSource; -import org.junit.jupiter.params.provider.ValueSource; -import org.mockito.ArgumentCaptor; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.skyscreamer.jsonassert.JSONAssert; - -import java.time.Instant; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; -import java.util.stream.Stream; - -import static fr.insee.protools.backend.service.FlowableVariableNameConstants.VARNAME_CURRENT_PARTITION_ID; -import static fr.insee.protools.backend.service.FlowableVariableNameConstants.VARNAME_REM_SURVEY_UNIT; -import static fr.insee.protools.backend.service.utils.FlowableVariableUtils.getMissingVariableMessage; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.*; - -class SabianePilotageCreateSUTaskTest extends TestWithContext { - - static final Long ctx_partition1 = 99L; - static final String minimal_ctx_ok = - """ - { "id": "TEST_ID" , "partitions": [{ "id":99, "typeEchantillon": "logement" , "prioritaire": "false"}] } - """; - - @Mock SabianePilotageService sabianePilotageService; - - @InjectMocks - SabianePilotageCreateSUTask sabianePilotageTask; - - @Test - void execute_should_throwError_when_null_context(){ - assertThat_delegate_throwError_when_null_context(sabianePilotageTask); - } - - @Test - @DisplayName("convertREMGenderToSabianeCivilityTitle should return MISS when param '2' ; 'MISTER' when param is '1' and throw in other cases") - void convertREMGenderToSabianeCivilityTitle_should_ReturnCorrectValues() { - assertThat(SabianePilotageCreateSUTask.convertREMGenderToSabianeCivilityTitle("1")).isEqualTo(SabianeTitle.MISTER); - assertThat(SabianePilotageCreateSUTask.convertREMGenderToSabianeCivilityTitle("1").getSabianeTitle()).isEqualTo("Mister"); - assertThat(SabianePilotageCreateSUTask.convertREMGenderToSabianeCivilityTitle("1").getFrenchCivility()).isEqualTo("M"); - - assertThat(SabianePilotageCreateSUTask.convertREMGenderToSabianeCivilityTitle("2")).isEqualTo(SabianeTitle.MISS); - assertThat(SabianePilotageCreateSUTask.convertREMGenderToSabianeCivilityTitle("2").getSabianeTitle()).isEqualTo("MISS"); - assertThat(SabianePilotageCreateSUTask.convertREMGenderToSabianeCivilityTitle("2").getFrenchCivility()).isEqualTo("MME"); - - assertThat(SabianePilotageCreateSUTask.convertREMGenderToSabianeCivilityTitle("2 ")).isEqualTo(SabianeTitle.MISS); - assertThat(SabianePilotageCreateSUTask.convertREMGenderToSabianeCivilityTitle(" 2 ")).isEqualTo(SabianeTitle.MISS); - assertThat(SabianePilotageCreateSUTask.convertREMGenderToSabianeCivilityTitle("3")).isEqualTo(SabianeTitle.MISS); - assertThat(SabianePilotageCreateSUTask.convertREMGenderToSabianeCivilityTitle("23JZKEOSJF")).isEqualTo(SabianeTitle.MISS); - assertThat(SabianePilotageCreateSUTask.convertREMGenderToSabianeCivilityTitle("0")).isEqualTo(SabianeTitle.MISS); - assertThat(SabianePilotageCreateSUTask.convertREMGenderToSabianeCivilityTitle("-1")).isEqualTo(SabianeTitle.MISS); - assertThat(SabianePilotageCreateSUTask.convertREMGenderToSabianeCivilityTitle("-2")).isEqualTo(SabianeTitle.MISS); - assertThat(SabianePilotageCreateSUTask.convertREMGenderToSabianeCivilityTitle("& ukdslw,kvlk,l")).isEqualTo(SabianeTitle.MISS); - assertThat(SabianePilotageCreateSUTask.convertREMGenderToSabianeCivilityTitle("")).isEqualTo(SabianeTitle.MISS); - assertThat(SabianePilotageCreateSUTask.convertREMGenderToSabianeCivilityTitle(null)).isEqualTo(SabianeTitle.MISS); - } - - @Test - void createSabianePhoneList_should_ReturnCorrectValues_2favorites_initial() { - //Prepare - List remPhones1 = - List.of( - PhoneNumberDto.builder().source(REMPhoneSource.INITIAL).number("01").favorite(Boolean.TRUE).build(), - PhoneNumberDto.builder().source(REMPhoneSource.INITIAL).number("02").favorite(Boolean.TRUE).build(), - PhoneNumberDto.builder().source(REMPhoneSource.INITIAL).number("03").favorite(Boolean.FALSE).build(), - PhoneNumberDto.builder().source(REMPhoneSource.DIRECTORY).number("04").favorite(Boolean.FALSE).build(), - PhoneNumberDto.builder().source(REMPhoneSource.DIRECTORY).number("05").favorite(Boolean.FALSE).build(), - PhoneNumberDto.builder().source(REMPhoneSource.INTERVIEWER).number("06").favorite(Boolean.TRUE).build(), - PhoneNumberDto.builder().source(REMPhoneSource.INTERVIEWER).number("07").favorite(Boolean.FALSE).build(), - PhoneNumberDto.builder().source(REMPhoneSource.INTERVIEWER).number("08").favorite(Boolean.TRUE).build(), - PhoneNumberDto.builder().source(REMPhoneSource.OTHER).number("09").favorite(Boolean.FALSE).build()); - - Set expectedSabiane1 = - Set.of( - SabianePhoneNumberDto.builder().source(Source.FISCAL).number("01").favorite(Boolean.TRUE).build(), - SabianePhoneNumberDto.builder().source(Source.DIRECTORY).number("02").favorite(Boolean.TRUE).build(), - SabianePhoneNumberDto.builder().source(Source.INTERVIEWER).number("06").favorite(Boolean.TRUE).build(), - SabianePhoneNumberDto.builder().source(Source.INTERVIEWER).number("07").favorite(Boolean.FALSE).build(), - SabianePhoneNumberDto.builder().source(Source.INTERVIEWER).number("08").favorite(Boolean.TRUE).build() - ); - //Execute the unit under test - List res = SabianePilotageCreateSUTask.createSabianePhoneList(new ArrayList<>(remPhones1)); - //Post conditions - assertEquals(expectedSabiane1.size(), res.size()); - assertTrue(res.containsAll(expectedSabiane1)); - - } - - @Test - void createSabianePhoneList_should_ReturnCorrectValues_noFavorite() { - //Prepare - List remPhones1 = - List.of( - PhoneNumberDto.builder().source(REMPhoneSource.INITIAL).number("01").favorite(Boolean.FALSE).build(), - PhoneNumberDto.builder().source(REMPhoneSource.INITIAL).number("02").favorite(Boolean.FALSE).build(), - PhoneNumberDto.builder().source(REMPhoneSource.INITIAL).number("03").favorite(Boolean.FALSE).build() - ); - Set expectedSabiane1 = - Set.of( - SabianePhoneNumberDto.builder().source(Source.FISCAL).number("01").favorite(Boolean.FALSE).build(), - SabianePhoneNumberDto.builder().source(Source.DIRECTORY).number("02").favorite(Boolean.FALSE).build() - ); - //Execute the unit under test - List res = SabianePilotageCreateSUTask.createSabianePhoneList(new ArrayList<>(remPhones1)); - //Post conditions - assertEquals(expectedSabiane1.size(), res.size()); - assertTrue(res.containsAll(expectedSabiane1)); - } - - @Test - void createSabianePhoneList_should_ReturnCorrectValues_1Favorite() { - //Prepare - List remPhones1 = - List.of( - PhoneNumberDto.builder().source(REMPhoneSource.INITIAL).number("01").favorite(Boolean.FALSE).build(), - PhoneNumberDto.builder().source(REMPhoneSource.INITIAL).number("02").favorite(Boolean.FALSE).build(), - PhoneNumberDto.builder().source(REMPhoneSource.INITIAL).number("03").favorite(Boolean.TRUE).build() - ); - Set expectedSabiane1 = - Set.of( - SabianePhoneNumberDto.builder().source(Source.FISCAL).number("03").favorite(Boolean.TRUE).build(), - SabianePhoneNumberDto.builder().source(Source.DIRECTORY).number("01").favorite(Boolean.FALSE).build() - ); - //Execute the unit under test - List res = SabianePilotageCreateSUTask.createSabianePhoneList(new ArrayList<>(remPhones1)); - //Post conditions - assertEquals(expectedSabiane1.size(), res.size()); - assertTrue(res.containsAll(expectedSabiane1)); - } - - @Test - void createSabianePhoneList_should_ReturnCorrectValues_1InterviewerFavorite() { - //Prepare - List remPhones1 = - List.of( - PhoneNumberDto.builder().source(REMPhoneSource.INITIAL).number("01").favorite(Boolean.FALSE).build(), - PhoneNumberDto.builder().source(REMPhoneSource.INITIAL).number("02").favorite(Boolean.FALSE).build(), - PhoneNumberDto.builder().source(REMPhoneSource.INITIAL).number("03").favorite(Boolean.FALSE).build(), - PhoneNumberDto.builder().source(REMPhoneSource.INTERVIEWER).number("04").favorite(Boolean.TRUE).build() - ); - Set expectedSabiane1 = - Set.of( - SabianePhoneNumberDto.builder().source(Source.FISCAL).number("01").favorite(Boolean.FALSE).build(), - SabianePhoneNumberDto.builder().source(Source.DIRECTORY).number("02").favorite(Boolean.FALSE).build(), - SabianePhoneNumberDto.builder().source(Source.INTERVIEWER).number("04").favorite(Boolean.TRUE).build() - - ); - //Execute the unit under test - List res = SabianePilotageCreateSUTask.createSabianePhoneList(new ArrayList<>(remPhones1)); - assertEquals(expectedSabiane1.size(), res.size()); - assertTrue(res.containsAll(expectedSabiane1)); - } - - - @Test - void createSabianePhoneList_should_throw_moreThan2Favorites() { - //Prepare - List remPhones1 = - List.of( - PhoneNumberDto.builder().source(REMPhoneSource.INITIAL).number("01").favorite(Boolean.FALSE).build(), - PhoneNumberDto.builder().source(REMPhoneSource.INITIAL).number("02").favorite(Boolean.TRUE).build(), - PhoneNumberDto.builder().source(REMPhoneSource.INITIAL).number("03").favorite(Boolean.TRUE).build(), - PhoneNumberDto.builder().source(REMPhoneSource.INITIAL).number("04").favorite(Boolean.TRUE).build() - ); - - //Execute the unit under test - assertThrows(IncorrectSUBPMNError.class, () ->SabianePilotageCreateSUTask.createSabianePhoneList(new ArrayList<>(remPhones1))); - } - - @Test - void createSabianePhoneList_should_throw_moreThan2Favorites_excludingInterviewers() { - //Prepare - List remPhones1 = - List.of( - PhoneNumberDto.builder().source(REMPhoneSource.INITIAL).number("01").favorite(Boolean.FALSE).build(), - PhoneNumberDto.builder().source(REMPhoneSource.INITIAL).number("02").favorite(Boolean.TRUE).build(), - PhoneNumberDto.builder().source(REMPhoneSource.INITIAL).number("03").favorite(Boolean.TRUE).build(), - PhoneNumberDto.builder().source(REMPhoneSource.INTERVIEWER).number("04").favorite(Boolean.TRUE).build() - ); - - //Execute the unit under test - assertDoesNotThrow(() ->SabianePilotageCreateSUTask.createSabianePhoneList(new ArrayList<>(remPhones1))); - } - - @ParameterizedTest - @CsvSource( - { "20110808, 1312754400", - "20110801, 1312149600", - "201108, 1312149600", - "2000, 946681200", - "," - }) - void computeSabianeBirthDateFromRem_should_ReturnCorrectValues(String remBirthdateInput, Long expectedOutputTimestampMs) { - //Prepare - //Call method under test - Long result = SabianePilotageCreateSUTask.computeSabianeBirthDateFromRem(remBirthdateInput); - // Post status - assertEquals(expectedOutputTimestampMs, result, "The computed timestamp for the birthdate : " + remBirthdateInput + " is incorrect"); - } - - @ParameterizedTest - @ValueSource(strings = {"20001", "anabab", "200099", "2011010111111", "2", "200", "2011a", "1600010a", ",", "01122024"}) - // Les valeurs à tester - void computeSabianeBirthDateFromRem_should_Throw_when_dateIsIncorrect(String inccorectDate) { - assertThrows(IncorrectSUBPMNError.class, () -> SabianePilotageCreateSUTask.computeSabianeBirthDateFromRem(inccorectDate)); - } - - - @ParameterizedTest - @CsvSource( - {"0123456789012345678901234567891234567abcd,0123456789012345678901234567891234567a,bcd", - "'','',''", - "' ','',''", - "' ','',''", - "0123456789012345678901234567891234567, 0123456789012345678901234567891234567,''" - }) - @DisplayName("computeL2L3 should cut the string at 38th caracter (included in L2)") - void computeL2L3_should_ReturnCorrectValues(String input, String expectedL2, String expectedL3) { - //Prepare - //Call method under test - Pair result = SabianePilotageCreateSUTask.computeL2L3(input); - // Post status - assertEquals(Pair.of(expectedL2, expectedL3), result, "The computed L2 & L3 for input " + input + " is incorrect"); - } - - // Méthode statique fournissant des données de test - static Stream providedREMAdressAndContactAndExpectedResults() { - return Stream.of( - Arguments.of( - REMAddressDto.builder().streetNumber("01").repetitionIndex("bis").streetType("rue") - .streetName("des lilas").specialDistribution("specialDistribution") - .zipCode("59000").cityName("Lille")/*.countryName("FRANCE")*/ - .addressSupplement("SupplementAdresse") - .locationHelp(null).build() - , PersonDto.builder().gender("1").firstName("FirstName").lastName("LastName").build(), - AddressDto.builder() - .l1("M FirstName LastName") - .l2("SupplementAdresse").l3("") - .l4("01 bis rue des lilas") - .l5("specialDistribution") - .l6("59000 Lille") - .l7("FRANCE") - .build() - ), - - Arguments.of( - REMAddressDto.builder().streetNumber("01").repetitionIndex("bis").streetType("rue") - .streetName("des lilas").specialDistribution("specialDistribution") - .zipCode("59000")/*.cityName("").countryName("FRANCE")*/ - .addressSupplement("SupplementAdresse") - .locationHelp(null).build() - , PersonDto.builder().gender("1")/*.firstName("FirstName")*/.lastName("LastName").build(), - AddressDto.builder() - .l1("M LastName") - .l2("SupplementAdresse").l3("") - .l4("01 bis rue des lilas") - .l5("specialDistribution") - .l6("59000") - .l7("FRANCE") - .build() - ), - - Arguments.of( - REMAddressDto.builder().streetNumber("01").repetitionIndex("bis").streetType("rue") - .streetName("des lilas").specialDistribution("specialDistribution") - /*.zipCode("59000")*/.cityName("TOTO")/*.countryName("FRANCE")*/ - .addressSupplement("SupplementAdresse") - .locationHelp(null).build() - , PersonDto.builder().gender("1").firstName("FirstName")/*.lastName("LastName")*/.build(), - AddressDto.builder() - .l1("M FirstName") - .l2("SupplementAdresse").l3("") - .l4("01 bis rue des lilas") - .l5("specialDistribution") - .l6("TOTO") - .l7("FRANCE") - .build() - ), - Arguments.of( - REMAddressDto.builder().streetNumber("01").repetitionIndex("bis").streetType("rue") - .streetName("des lilas").specialDistribution("specialDistribution") - /*.zipCode("59000").cityName("TOTO").countryName("FRANCE")*/ - .addressSupplement("SupplementAdresse") - .locationHelp(null).build() - , PersonDto.builder().gender("1")/*.firstName("FirstName").lastName("LastName")*/.build(), - AddressDto.builder() - .l1("M") - .l2("SupplementAdresse").l3("") - .l4("01 bis rue des lilas") - .l5("specialDistribution") - .l6("") - .l7("FRANCE") - .build() - ), - - - Arguments.of( - REMAddressDto.builder().streetNumber("1110")/*.repetitionIndex()*/.streetType("route") - .streetName("des Touches").specialDistribution("specialDistribution") - .zipCode("59000").cityName("Lille").countryName("FRANCE") - .addressSupplement("SupplementAdresse") - .locationHelp(null).build() - , PersonDto.builder().gender("XXKLXKEZSDKWLJDWSKKJ").firstName("FirstName").lastName("LastName").build(), - AddressDto.builder() - .l1("MME FirstName LastName") - .l2("SupplementAdresse").l3("") - .l4("1110 route des Touches") - .l5("specialDistribution") - .l6("59000 Lille") - .l7("FRANCE") - .build() - ), - - Arguments.of( - REMAddressDto.builder()/*.streetNumber().repetitionIndex()*/.streetType("place") - .streetName("de la Poste").specialDistribution("specialDistribution") - .zipCode("59000").cityName("Lille").countryName("FRANCE") - .addressSupplement("SupplementAdresse") - .locationHelp(null).build() - , PersonDto.builder()/*.gender("2")*/.firstName("FirstName").lastName("LastName").build(), - AddressDto.builder() - .l1("MME FirstName LastName") - .l2("SupplementAdresse").l3("") - .l4("place de la Poste") - .l5("specialDistribution") - .l6("59000 Lille") - .l7("FRANCE") - .build() - ), - - Arguments.of( - REMAddressDto.builder().streetNumber("").repetitionIndex(" ").streetType("place") - .streetName("de la Poste").specialDistribution("specialDistribution") - .zipCode("59000").cityName("Lille").countryName(" ") - .addressSupplement("SupplementAdresse") - .locationHelp(null).build() - , PersonDto.builder().gender(null).firstName("FirstName").lastName("LastName").build(), - AddressDto.builder() - .l1("MME FirstName LastName") - .l2("SupplementAdresse").l3("") - .l4("place de la Poste") - .l5("specialDistribution") - .l6("59000 Lille") - .l7("FRANCE") - .build()) - - , - - Arguments.of( - REMAddressDto.builder().streetNumber("").repetitionIndex(" ").streetType("place") - .streetName("de la Poste").specialDistribution("specialDistribution") - .zipCode("59000").cityName("Lille").countryName(" ") - .addressSupplement("SupplementAdresse") - .locationHelp( - LocationHelpDto.builder() - .building("building") - .cityPriorityDistrict(Boolean.FALSE) - .door("door") - .elevator(Boolean.TRUE) - .floor("floor") - .build()) - .build() - , PersonDto.builder().gender(" ").firstName("FirstName").lastName("LastName").build(), - AddressDto.builder() - .l1("MME FirstName LastName") - .l2("SupplementAdresse").l3("") - .l4("place de la Poste") - .l5("specialDistribution") - .l6("59000 Lille") - .l7("FRANCE") - .building("building") - .cityPriorityDistrict(Boolean.FALSE) - .door("door") - .elevator(Boolean.TRUE) - .floor("floor") - .build()) - ); - } - - @ParameterizedTest - @MethodSource("providedREMAdressAndContactAndExpectedResults") - void computeSabianeAdress_should_returnCorrectValues(REMAddressDto remAdress, PersonDto remContact, AddressDto expectedSabianeAdress) { - //Prepare - //Call method under test - AddressDto sabianeAdress = SabianePilotageCreateSUTask.computeSabianeAdress(remAdress, remContact); - //Post conditions - assertEquals(expectedSabianeAdress, sabianeAdress); - } - - @Test - void createSabianePersonFromRemPerson_should_returnCorrectValues_for_individu() throws JsonProcessingException, JSONException { - String ctx_ok = -""" - { "id": "TEST_ID" } -"""; - - String expectedJsonSabiane = -""" -{ - "organizationUnitId": "ID_POLE_GESTION_OPALE", - "address": { - "cityPriorityDistrict": false, - "door": "door", - "floor": "00/_", - "l1": "MME firstName2 lastName2", - "l2": "SupplementAdresse", - "l3": "", - "l4": "1 RUE DE L INSEE", - "l5": "specialDistribution", - "l6": "59000 Lille", - "l7": "FRANCE" - }, - "persons": [ - { - "birthdate": 315615600, - "email": "test2@gmail.com", - "favoriteEmail": false, - "firstName": "firstName2", - "lastName": "lastName2", - "phoneNumbers": [ - { - "favorite": false, - "number": "02", - "source": "FISCAL" - } - ], - "privileged": true, - "title": "MISS" - } - ], - "sampleIdentifiers": { - "autre": "0", - "bs": 0, - "ec": "0", - "le": 0, - "nograp": null, - "noi": 0, - "nole": 0, - "nolog": 0, - "numfa": 0, - "rges": 0, - "ssech": 99 - } -} -"""; - - //Prepare - JsonNode ctxNode = new ObjectMapper().readTree(ctx_ok); - JsonNode remNode = ProtoolsTestUtils.asObject(RemSUData.rem_su_test_selection_3personnes,JsonNode.class); - - - //Run Methode under tests - SurveyUnitContextDto sabianeDto = SabianePilotageCreateSUTask.createSabianeSUContextDto(ctxNode, ctx_partition1, remNode, false, false); - - //Verifications - JsonNode sabianeResultNode = new ObjectMapper().valueToTree(sabianeDto); - assertThat(sabianeResultNode.get("states").isArray()).isTrue(); - assertThat(sabianeResultNode.get("states").size()).isEqualTo(1); - assertThat(sabianeResultNode.get("states").get(0).get("type").textValue()).isEqualTo(StateType.NVM.toString()); - //state datetime - long statesTS = sabianeResultNode.get("states").get(0).get("date").longValue(); - long currentTs = Instant.now().toEpochMilli(); - long difference = currentTs - statesTS; - assertThat(statesTS).isLessThanOrEqualTo(currentTs); - assertThat(difference).isLessThanOrEqualTo(1 * 60 * 1000);//less than one minute old - - - //Put static values in expected result - JsonNode expectedSabianeNode = new ObjectMapper().readTree(expectedJsonSabiane);//Execute method under test - ObjectNode objectNode = (ObjectNode) expectedSabianeNode; - // Ajouter une nouvelle clé/valeur - objectNode.put("priority", false); - objectNode.put("campaign", "TEST_ID"); - String idSabiane = SabianeIdHelper.computeSabianeID(ctx_partition1.toString(), "3043280"); - objectNode.put("id", idSabiane); - - //We are sure of the state; we can just override the expected value with the actual one - objectNode.put("states", sabianeResultNode.get("states")); - // Convertir l'ObjectNode en JsonNode - expectedSabianeNode = objectNode; - JSONAssert.assertEquals(expectedSabianeNode.toString(), sabianeResultNode.toString(), false); - } - - - @Test - void createSabianePersonFromRemPerson_should_returnCorrectValues_for_logement() throws JsonProcessingException, JSONException { - String ctx_ok = - """ - { "id": "TEST_ID" } - """; - - String expectedJsonSabiane = - """ - { - "organizationUnitId": "ID_POLE_GESTION_OPALE", - "address": { - "cityPriorityDistrict": false, - "door": "door", - "floor": "00/_", - "l1": "MME firstName2 lastName2", - "l2": "SupplementAdresse", - "l3": "", - "l4": "1 RUE DE L INSEE", - "l5": "specialDistribution", - "l6": "59000 Lille", - "l7": "FRANCE" - }, - "persons": [ - { - "birthdate": 315615600, - "email": "test2@gmail.com", - "favoriteEmail": false, - "firstName": "firstName2", - "lastName": "lastName2", - "phoneNumbers": [ - { - "favorite": false, - "number": "02", - "source": "FISCAL" - } - ], - "privileged": true, - "title": "MISS" - } - ], - "sampleIdentifiers": { - "autre": "0", - "bs": 0, - "ec": "0", - "le": 0, - "nograp": null, - "noi": 0, - "nole": 0, - "nolog": 0, - "numfa": 0, - "rges": 0, - "ssech": 99 - } - } - """; - - //Prepare - JsonNode ctxNode = new ObjectMapper().readTree(ctx_ok); - JsonNode remNode = ProtoolsTestUtils.asObject(RemSUData.rem_su_test_selection_3personnes,JsonNode.class); - - //Run Methode under tests - SurveyUnitContextDto sabianeDto = SabianePilotageCreateSUTask.createSabianeSUContextDto(ctxNode, ctx_partition1, remNode, true, false); - - //Verifications - JsonNode sabianeResultNode = new ObjectMapper().valueToTree(sabianeDto); - assertThat(sabianeResultNode.get("states").isArray()).isTrue(); - assertThat(sabianeResultNode.get("states").size()).isEqualTo(1); - assertThat(sabianeResultNode.get("states").get(0).get("type").textValue()).isEqualTo(StateType.NVM.toString()); - //state datetime - long statesTS = sabianeResultNode.get("states").get(0).get("date").longValue(); - long currentTs = Instant.now().toEpochMilli(); - long difference = currentTs - statesTS; - assertThat(statesTS).isLessThanOrEqualTo(currentTs); - assertThat(difference).isLessThanOrEqualTo(1 * 60 * 1000);//less than one minute old - - - //Put static values in expected result - JsonNode expectedSabianeNode = new ObjectMapper().readTree(expectedJsonSabiane);//Execute method under test - ObjectNode objectNode = (ObjectNode) expectedSabianeNode; - // Ajouter une nouvelle clé/valeur - objectNode.put("priority", false); - objectNode.put("campaign", "TEST_ID"); - String idSabiane = SabianeIdHelper.computeSabianeID(ctx_partition1.toString(), "3043280"); - objectNode.put("id", idSabiane); - - //We are sure of the state; we can just override the expected value with the actual one - objectNode.put("states", sabianeResultNode.get("states")); - // Convertir l'ObjectNode en JsonNode - expectedSabianeNode = objectNode; - JSONAssert.assertEquals(expectedSabianeNode.toString(), sabianeResultNode.toString(), false); - } - - @Test - @DisplayName("Test execute method - should throw if VARNAME_CURRENT_PARTITION_ID or VARNAME_REM_SURVEY_UNIT not initialized") - void execute_should_throw_FlowableIllegalArgumentException_when_variables_notDefined() throws JsonProcessingException { - //Precondition - DelegateExecution execution = createMockedExecution(); - initContexteMockWithString(minimal_ctx_ok); - - //Execute the unit under test - FlowableIllegalArgumentException exception = assertThrows(FlowableIllegalArgumentException.class, () -> sabianePilotageTask.execute(execution)); - //Post conditions - assertThat(exception.getMessage()).isEqualTo(getMissingVariableMessage(VARNAME_CURRENT_PARTITION_ID)); - - //Create First variable - when(execution.getVariable(VARNAME_CURRENT_PARTITION_ID, Long.class)).thenReturn(99L); - //Execute again - exception = assertThrows(FlowableIllegalArgumentException.class, () -> sabianePilotageTask.execute(execution)); - //Check the error - assertThat(exception.getMessage()).isEqualTo(getMissingVariableMessage(VARNAME_REM_SURVEY_UNIT)); - - //Create 2nd variable - when(execution.getVariable(VARNAME_REM_SURVEY_UNIT, JsonNode.class)).thenReturn(ProtoolsTestUtils.asJsonNode(RemSUData.rem_su_1personne)); - //Execute again - assertDoesNotThrow(() -> sabianePilotageTask.execute(execution)); - } - - - private static Stream contextErrorArguments() { - return Stream.of( - Arguments.of(CtxExamples.ctx_no_part), - Arguments.of(CtxExamples.ctx_idCampagne_idPartition), - Arguments.of(CtxExamples.ctx_idCampagne_1emptyPartition), - Arguments.of(CtxExamples.ctx_idCampagne_idPartition_typeLogement), - Arguments.of(CtxExamples.ctx_idCampagne_idPartition_typeIndividu) - ); - } - - @ParameterizedTest - @MethodSource("contextErrorArguments") - @DisplayName("Test execute method - should throw if Context is not correct") - void execute_should_throw_BadContext_when_contextIncorrect(String context_json) throws JsonProcessingException { - //Precondition - DelegateExecution execution = createMockedExecution(); - //Variables - lenient().when(execution.getVariable(VARNAME_CURRENT_PARTITION_ID, Long.class)).thenReturn(CtxExamples.ctx_partition1); - lenient().when(execution.getVariable(VARNAME_REM_SURVEY_UNIT, JsonNode.class)).thenReturn(ProtoolsTestUtils.asJsonNode(RemSUData.rem_su_1personne)); - //Ctx - ProtoolsTestUtils.initContexteMockFromString(protoolsContext, context_json); - - //Run test - assertThrows(BadContextIncorrectBPMNError.class, () -> sabianePilotageTask.execute(execution)); - Mockito.reset(protoolsContext); - } - - - static Stream initExecuteParameters() { - return Stream.of( - Arguments.of( - SabianeCtxExamples.ctx_ok_idCampagne_idPartition_typeLogement_prioritaire, - RemSUData.rem_su_1personne, - Boolean.TRUE), - Arguments.of( - SabianeCtxExamples.ctx_ok_idCampagne_idPartition_typeLogement_nonPrioritaire, - RemSUData.rem_su_1personne, - Boolean.FALSE) - ); - } - - @ParameterizedTest - @MethodSource("initExecuteParameters") - @DisplayName("Test execute method - should work and make correct call to service when context has one partition") - void execute_should_work_when_ctx_1part_logement(String inputCtx, String inputRemSU, Boolean expectedPriority) { - //Precondition - DelegateExecution execution = mock(DelegateExecution.class); - lenient().when(execution.getProcessInstanceId()).thenReturn(dumyId); - lenient().when(execution.getVariable(VARNAME_CURRENT_PARTITION_ID, Long.class)).thenReturn(CtxExamples.ctx_partition1); - JsonNode remSU = ProtoolsTestUtils.asJsonNode(inputRemSU); - lenient().when(execution.getVariable(VARNAME_REM_SURVEY_UNIT, JsonNode.class)).thenReturn(remSU); - //Ctx - initContexteMockWithString(inputCtx); - - //Run method under test - assertDoesNotThrow(() -> sabianePilotageTask.execute(execution)); - - final ArgumentCaptor > listCaptor - = ArgumentCaptor.forClass((Class) List.class); - verify(sabianePilotageService,times(1)).postSurveyUnits(listCaptor.capture()); - - List> captured = listCaptor.getAllValues(); - assertEquals(1,captured.size(),"We are supposed to call the method only one"); - List actualListOfSU = captured.get(0); - assertEquals(1,actualListOfSU.size(),"We are supposed to create SU one by one"); - SurveyUnitContextDto actualSU = actualListOfSU.get(0); - - assertEquals(1,actualSU.getPersons().size()); - //Prioritaire - assertEquals(expectedPriority,actualSU.getPriority()); - - - assertEquals(remSU.path("persons").path(0).path("emails").path(0).path("mailAddress").asText(),actualSU.getPersons().get(0).getEmail()); - assertEquals(remSU.path("persons").path(0).path("firstName").asText(),actualSU.getPersons().get(0).getFirstName()); - Mockito.reset(protoolsContext); - } - -} \ No newline at end of file diff --git a/src/test/java/fr/insee/protools/backend/service/sabiane/delegate/SabianeQuestionnaireCreateContextTaskTest.java b/src/test/java/fr/insee/protools/backend/service/sabiane/delegate/SabianeQuestionnaireCreateContextTaskTest.java deleted file mode 100644 index 7774d633..00000000 --- a/src/test/java/fr/insee/protools/backend/service/sabiane/delegate/SabianeQuestionnaireCreateContextTaskTest.java +++ /dev/null @@ -1,139 +0,0 @@ -package fr.insee.protools.backend.service.sabiane.delegate; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import fr.insee.protools.backend.ProtoolsTestUtils; -import fr.insee.protools.backend.dto.platine_sabiane_questionnaire.campaign.CampaignDto; -import fr.insee.protools.backend.dto.platine_sabiane_questionnaire.campaign.MetadataValue; -import fr.insee.protools.backend.service.context.ContextConstants; -import fr.insee.protools.backend.service.context.ContextService; -import fr.insee.protools.backend.service.context.exception.BadContextIncorrectBPMNError; -import fr.insee.protools.backend.service.nomenclature.NomenclatureService; -import fr.insee.protools.backend.service.questionnaire_model.QuestionnaireModelService; -import fr.insee.protools.backend.service.sabiane.questionnaire.SabianeQuestionnaireService; -import fr.insee.protools.backend.service.utils.TestWithContext; -import org.flowable.engine.delegate.DelegateExecution; -import org.flowable.engine.test.FlowableTest; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.ArgumentCaptor; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.Spy; -import org.mockito.junit.jupiter.MockitoExtension; -import org.springframework.util.ClassUtils; - -import java.io.IOException; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import static fr.insee.protools.backend.service.context.ContextConstants.*; -import static org.assertj.core.api.AssertionsForClassTypes.assertThatCode; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.*; - - -@ExtendWith(MockitoExtension.class) -@FlowableTest -public -class SabianeQuestionnaireCreateContextTaskTest extends TestWithContext { - - - final static String ressourceFolder = ClassUtils.convertClassNameToResourcePath(SabianeQuestionnaireCreateContextTaskTest.class.getPackageName()); - final static String sabiane_context_json = ressourceFolder+"/protools-contexte-sabiane.json"; - final static String sabiane_context_incorrect_json = ressourceFolder+"/protools-contexte-sabiane-incorrect.json"; - - @Mock SabianeQuestionnaireService sabianeQuestionnaireService; - @Mock QuestionnaireModelService questionnaireModelService; - @Mock NomenclatureService nomenclatureService; - @Spy ObjectMapper objectMapper; - - @InjectMocks - SabianeQuestionnaireCreateContextTask sabianeQuestTask; - - private final String questionnaireContent1 ="{\"id\": \"TOTO\" , \"toto\": 55 }"; - - @Test - void execute_should_throwError_when_null_context(){ - assertThat_delegate_throwError_when_null_context(sabianeQuestTask); - } - - @Test - void execute_should_throwBadContextIncorrect_when_contextIsKO() { - // preconditions - DelegateExecution execution = mock(DelegateExecution.class); - when(execution.getProcessInstanceId()).thenReturn("1"); - initContexteMockWithFile(sabiane_context_incorrect_json); - - //Execute the unit under test - assertThrows(BadContextIncorrectBPMNError.class, () -> sabianeQuestTask.execute(execution)); - - // postconditions - //assertThat(execution.getVariable("myVariable")).isEqualTo("myValue"); - - } - - /*@Test - void initQuestionnaireModels_should_produce_correct_json(){ - sabianeQuestTask.² - }*/ - - @Test - void execute_should_work_and_make_correct_calls() throws IOException { - DelegateExecution execution = mock(DelegateExecution.class); - when(execution.getProcessInstanceId()).thenReturn("1"); - JsonNode contextRootNode = initContexteMockWithFile(sabiane_context_json); - assertEquals(2,contextRootNode.path(ContextConstants.CTX_QUESTIONNAIRE_MODELS).size(), "Context error : expected exactly 2 questionnaire model"); - - //Prepare the list of existing nomenclatures ("L_NATIONETR-1-1-0" does not exists yet) - when(sabianeQuestionnaireService.getNomenclaturesId()).thenReturn(Set.of("L_DEPNAIS-1-1-0","L_PAYSNAIS-1-1-0","L_COMMUNEPASSEE-1-1-0")); - //Mock the read nomenclature - String nomenclatureContent="{\"id\": \"nomenclatureContent\"}"; - - when(nomenclatureService.getNomenclatureContent("L_NATIONETR-1-1-0","NATIONETR")).thenReturn(nomenclatureContent); - //Mock questionnaire - when(sabianeQuestionnaireService.questionnaireModelExists(anyString())).thenReturn(false); - when(questionnaireModelService.getQuestionnaireModel(anyString(), anyString())).thenReturn(questionnaireContent1); - - - //Execute the unit under test - assertThatCode(() -> sabianeQuestTask.execute(execution)).doesNotThrowAnyException(); - - //Verifications on nomenclatures - verify(sabianeQuestionnaireService,atLeastOnce()).getNomenclaturesId(); - verify(sabianeQuestionnaireService).postNomenclature( - "L_NATIONETR-1-1-0", - "liste des nationalités", - objectMapper.readTree(nomenclatureContent)); - - //Verifications on questionnaires (2 questionnaires models to create) - verify(sabianeQuestionnaireService,times(2)).postQuestionnaireModel(any(),any(),any(),any()); - for(int i =0; i<2; i++){ - String idQuestionnaireModel = contextRootNode.path(ContextConstants.CTX_QUESTIONNAIRE_MODELS).get(i).path(CTX_QUESTIONNAIRE_MODEL_ID).asText(); - String labelQuestionnaireModel = contextRootNode.path(ContextConstants.CTX_QUESTIONNAIRE_MODELS).get(i).path(CTX_QUESTIONNAIRE_MODEL_LABEL).asText(); - String repertoireQuestionnaireModel = contextRootNode.path(ContextConstants.CTX_QUESTIONNAIRE_MODELS).get(i).path(CTX_QUESTIONNAIRE_MODEL_CHEMIN_REPERTOIRE).asText(); - Set nomenclatures = new HashSet<>(); - var iter=contextRootNode.path(ContextConstants.CTX_QUESTIONNAIRE_MODELS).get(i).path(CTX_QUESTIONNAIRE_MODEL_REQUIRED_NOMENCLATURES).elements(); - while(iter.hasNext()){ - var nomenclature=iter.next().asText(); - nomenclatures.add(nomenclature); - } - - verify(sabianeQuestionnaireService,times(1)).questionnaireModelExists(idQuestionnaireModel); - verify(questionnaireModelService,times(1)).getQuestionnaireModel(idQuestionnaireModel,repertoireQuestionnaireModel); - verify(sabianeQuestionnaireService).postQuestionnaireModel(idQuestionnaireModel,labelQuestionnaireModel, - objectMapper.readTree(questionnaireContent1),nomenclatures); - } - - //Verify postCampaign - ArgumentCaptor acCampaignDto = ArgumentCaptor.forClass(CampaignDto.class); - verify(sabianeQuestionnaireService,times(1)).postCampaign(acCampaignDto.capture()); - List allValues = acCampaignDto.getAllValues(); - assertEquals(1, allValues.size(),"We should have exactly one campaign"); - MetadataValue expectedMetadataNode = ProtoolsTestUtils.asObject(ressourceFolder + "/expected_post_questionnaire_metadata.json", MetadataValue.class); - assertEquals(expectedMetadataNode,allValues.get(0).getMetadata(),"Erreur with generated Metadata"); - } -} diff --git a/src/test/java/fr/insee/protools/backend/service/sabiane/delegate/SabianeQuestionnaireCreateSUTaskTest.java b/src/test/java/fr/insee/protools/backend/service/sabiane/delegate/SabianeQuestionnaireCreateSUTaskTest.java deleted file mode 100644 index 7c574839..00000000 --- a/src/test/java/fr/insee/protools/backend/service/sabiane/delegate/SabianeQuestionnaireCreateSUTaskTest.java +++ /dev/null @@ -1,165 +0,0 @@ -package fr.insee.protools.backend.service.sabiane.delegate; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonNode; -import fr.insee.protools.backend.ProtoolsTestUtils; -import fr.insee.protools.backend.dto.platine_sabiane_questionnaire.surveyunit.SurveyUnitResponseDto; -import fr.insee.protools.backend.service.context.exception.BadContextIncorrectBPMNError; -import fr.insee.protools.backend.service.sabiane.SabianeIdHelper; -import fr.insee.protools.backend.service.sabiane.questionnaire.SabianeQuestionnaireService; -import fr.insee.protools.backend.service.utils.TestWithContext; -import fr.insee.protools.backend.service.utils.data.CtxExamples; -import fr.insee.protools.backend.service.utils.data.RemSUData; -import org.flowable.common.engine.api.FlowableIllegalArgumentException; -import org.flowable.engine.delegate.DelegateExecution; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; -import org.mockito.ArgumentCaptor; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.Mockito; - -import java.util.List; -import java.util.stream.Stream; - -import static fr.insee.protools.backend.service.FlowableVariableNameConstants.VARNAME_CURRENT_PARTITION_ID; -import static fr.insee.protools.backend.service.FlowableVariableNameConstants.VARNAME_REM_SURVEY_UNIT; -import static fr.insee.protools.backend.service.utils.FlowableVariableUtils.getMissingVariableMessage; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.*; - - -class SabianeQuestionnaireCreateSUTaskTest extends TestWithContext { - - - static final String minimal_ctx_ok = - """ - { "id": "TEST_ID" , "partitions": [{ "id":99, "questionnaireModel": "ID_1"}] , "questionnaireModels": [{"id": "ID_1"}]} - """; - - @Mock SabianeQuestionnaireService sabianeQuestionnaireService; - - @InjectMocks - SabianeQuestionnaireCreateSUTask sabianePilotageTask; - - private static Stream contextErrorArguments() { - return Stream.of( - Arguments.of(CtxExamples.ctx_no_part), - Arguments.of(CtxExamples.ctx_idCampagne_questionnaireModels_idPartition), - Arguments.of(CtxExamples.ctx_questionnaireModels_no_part), - Arguments.of(CtxExamples.ctx_idCampagne_questionnaireModels_1emptyPartition), - Arguments.of(CtxExamples.ctx_idCampagne_emptyQuestionnaireModels_idPartition) - ); - } - - static Stream initExecuteParameters() { - return Stream.of( - Arguments.of( - SabianeCtxExamples.ctx_ok_idCampagne_idQuestionnaireModel_idPartition_questionnaireModelPartition, - RemSUData.rem_su_1personne, - Boolean.TRUE) - ); - } - - @Test - void execute_should_throwError_when_null_context(){ - assertThat_delegate_throwError_when_null_context(sabianePilotageTask); - } - - @Test - @DisplayName("Test execute method - should throw if VARNAME_CURRENT_PARTITION_ID or VARNAME_REM_SURVEY_UNIT not initialized") - void execute_should_throw_FlowableIllegalArgumentException_when_variables_notDefined() { - //Precondition - DelegateExecution execution = createMockedExecution(); - initContexteMockWithString(minimal_ctx_ok); - - //Execute the unit under test - FlowableIllegalArgumentException exception = assertThrows(FlowableIllegalArgumentException.class, () -> sabianePilotageTask.execute(execution)); - //Post conditions - assertThat(exception.getMessage()).isEqualTo(getMissingVariableMessage(VARNAME_CURRENT_PARTITION_ID)); - - //Create First variable - when(execution.getVariable(VARNAME_CURRENT_PARTITION_ID, Long.class)).thenReturn(99L); - //Execute again - exception = assertThrows(FlowableIllegalArgumentException.class, () -> sabianePilotageTask.execute(execution)); - //Check the error - assertThat(exception.getMessage()).isEqualTo(getMissingVariableMessage(VARNAME_REM_SURVEY_UNIT)); - - //Create 2nd variable - when(execution.getVariable(VARNAME_REM_SURVEY_UNIT, JsonNode.class)).thenReturn(ProtoolsTestUtils.asJsonNode(RemSUData.rem_su_1personne)); - //Execute again - assertDoesNotThrow(() -> sabianePilotageTask.execute(execution)); - } - - @Test - void execute_should_throw_BadContextIncorrectException_when_noContext() { - DelegateExecution execution = createMockedExecution(); - //Execute the unit under test - assertThrows(BadContextIncorrectBPMNError.class, () -> sabianePilotageTask.execute(execution)); - } - - @ParameterizedTest - @MethodSource("contextErrorArguments") - @DisplayName("Test execute method - should throw if Context is not correct") - void execute_should_throw_BadContext_when_contextIncorrect(String context_json) throws JsonProcessingException { - //Precondition - DelegateExecution execution = createMockedExecution(); - //Variables - lenient().when(execution.getVariable(VARNAME_CURRENT_PARTITION_ID, Long.class)).thenReturn(CtxExamples.ctx_partition1); - lenient().when(execution.getVariable(VARNAME_REM_SURVEY_UNIT, JsonNode.class)).thenReturn(ProtoolsTestUtils.asJsonNode(RemSUData.rem_su_1personne)); - //Ctx - ProtoolsTestUtils.initContexteMockFromString(protoolsContext, context_json); - - //Run test - assertThrows(BadContextIncorrectBPMNError.class, () -> sabianePilotageTask.execute(execution)); - Mockito.reset(protoolsContext); - } - - @ParameterizedTest - @MethodSource("initExecuteParameters") - @DisplayName("Test execute method - should work and make correct call to service when context has one partition") - void execute_should_work_when_ctx_1part_logement(String inputCtx, String inputRemSU) { - //Precondition - DelegateExecution execution = mock(DelegateExecution.class); - lenient().when(execution.getProcessInstanceId()).thenReturn(dumyId); - lenient().when(execution.getVariable(VARNAME_CURRENT_PARTITION_ID, Long.class)).thenReturn(CtxExamples.ctx_partition1); - JsonNode remSU = ProtoolsTestUtils.asJsonNode(inputRemSU); - lenient().when(execution.getVariable(VARNAME_REM_SURVEY_UNIT, JsonNode.class)).thenReturn(remSU); - //Ctx - JsonNode ctxNode = initContexteMockWithString(inputCtx); - - //Run method under test - assertDoesNotThrow(() -> sabianePilotageTask.execute(execution)); - - //Post conditions - ArgumentCaptor acSUDto = ArgumentCaptor.forClass(SurveyUnitResponseDto.class); - verify(sabianeQuestionnaireService, times(1)).postSurveyUnit(acSUDto.capture(), eq("AAC2023A00")); - List allValues = acSUDto.getAllValues(); - assertEquals(1, allValues.size(), "We should have exactly one SU Created"); - - SurveyUnitResponseDto actualSU = allValues.get(0); - assertEquals( - ctxNode.path("partitions").path(0).path("questionnaireModel").asText(), - actualSU.getQuestionnaireId()); - assertEquals( - remSU.path("externals"), - actualSU.getData()); - - String idSabiane = SabianeIdHelper.computeSabianeID(CtxExamples.ctx_partition1.toString(), remSU.path("repositoryId").asText()); - assertEquals( - idSabiane, - actualSU.getId(), - "Expected a correctly formed sabiane SU ID"); - - assertThat(actualSU.getPersonalization()).isEmpty(); - assertThat(actualSU.getComment()).isEmpty(); - //assertThat(actualSU.getStateData()).isEmpty(); - - Mockito.reset(protoolsContext); - } - -} \ No newline at end of file diff --git a/src/test/java/fr/insee/protools/backend/service/sugoi/SugoiCreateUserTaskTest.java b/src/test/java/fr/insee/protools/backend/service/sugoi/SugoiCreateUserTaskTest.java deleted file mode 100644 index d1fdf2f4..00000000 --- a/src/test/java/fr/insee/protools/backend/service/sugoi/SugoiCreateUserTaskTest.java +++ /dev/null @@ -1,84 +0,0 @@ -package fr.insee.protools.backend.service.sugoi; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.ObjectMapper; -import fr.insee.protools.backend.dto.sugoi.User; -import fr.insee.protools.backend.service.utils.password.PasswordService; -import org.flowable.engine.delegate.DelegateExecution; -import org.flowable.engine.test.FlowableTest; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.ArgumentCaptor; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -import static fr.insee.protools.backend.service.FlowableVariableNameConstants.VARNAME_DIRECTORYACCESS_ID_CONTACT; -import static fr.insee.protools.backend.service.sugoi.SugoiCreateUserTask.PLATINE_HABILITATION; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.*; - -@ExtendWith(MockitoExtension.class) -@FlowableTest -class SugoiCreateUserTaskTest { - - @Mock SugoiService sugoiService; - @Mock PasswordService passwordService; - @InjectMocks SugoiCreateUserTask task; - - protected final String dumyId="ID1"; - - @Test - void execute_should_work() throws JsonProcessingException { - //Prepare - DelegateExecution execution = mock(DelegateExecution.class); - doReturn(dumyId).when(execution).getProcessInstanceId(); - String expectedPwd="veryComplicatedPassword"; - doReturn(expectedPwd).when(passwordService).generatePassword(); - final String userId="D96QSST"; - final String sugoiResponse = - """ - { - "username": "D96QSST", - "groups": [], - "habilitations": [ - { - "id": "repondant_platine", - "application": "platine", - "role": "repondant", - "property": null - } - ], - "metadatas": { - "userStorage": "default", - "realm": "questionnaire-particuliers", - "modifyTimestamp": "20231106141045Z" - }, - "attributes": { - "hasPassword": false - } - } - """; - doReturn( - new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) - .readValue(sugoiResponse,User.class)) - .when(sugoiService).postCreateUsers(any()); - - //Execute - assertDoesNotThrow(() -> task.execute(execution)); - - //post conditions - verify(execution).setVariableLocal(VARNAME_DIRECTORYACCESS_ID_CONTACT, userId); - //verif on user creation - ArgumentCaptor acUserDto = ArgumentCaptor.forClass(User.class); - verify(sugoiService).postCreateUsers(acUserDto.capture()); - assertEquals(1, acUserDto.getAllValues().size(),"We should have exactly one call to postCreateUsers"); - User userParam = acUserDto.getValue(); - assertEquals(1, userParam.getHabilitations().size(),"We should have exactly one habilitation"); - assertTrue(userParam.getHabilitations().contains(PLATINE_HABILITATION),"Platine habilitiation not found"); - - //verif on password - verify(sugoiService).postInitPassword(userId,expectedPwd); - } -} \ No newline at end of file diff --git a/src/test/java/fr/insee/protools/backend/service/sugoi/SugoiServiceTest.java b/src/test/java/fr/insee/protools/backend/service/sugoi/SugoiServiceTest.java new file mode 100644 index 00000000..623047bf --- /dev/null +++ b/src/test/java/fr/insee/protools/backend/service/sugoi/SugoiServiceTest.java @@ -0,0 +1,141 @@ +package fr.insee.protools.backend.service.sugoi; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import fr.insee.protools.backend.dto.sugoi.Habilitation; +import fr.insee.protools.backend.dto.sugoi.User; +import fr.insee.protools.backend.restclient.exception.runtime.HttpClient4xxBPMNError; +import fr.insee.protools.backend.service.exception.SugoiServiceCallBPMNError; +import fr.insee.protools.backend.service.exception.UsernameAlreadyExistsSugoiBPMNError; +import fr.insee.protools.backend.service.utils.TestServiceWithRestClient; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.InjectMocks; +import org.mockito.Spy; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; +import org.springframework.web.util.UriBuilder; + +import java.util.List; + +import static fr.insee.protools.backend.restclient.configuration.ApiConfigProperties.KNOWN_API.KNOWN_API_SUGOI; +import static fr.insee.protools.backend.service.sugoi.SugoiServiceImpl.STORAGE; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.verify; + +@ExtendWith(MockitoExtension.class) +class SugoiServiceTest extends TestServiceWithRestClient { + + @Spy + private ObjectMapper objectMapper; // Mock the ObjectMapper + + + @InjectMocks + SugoiServiceImpl service; + + @Value("${fr.insee.protools.api.sugoi.dmz-account-creation-realm:questionnaire-particuliers}") + private String realm; + + @Test + void postCreateUser_should_call_correctURIAndBody() { + //Prepare + Habilitation PLATINE_HABILITATION = new Habilitation("platine", "repondant", null); + User createSugoiUserBody = User.builder().habilitations(List.of(PLATINE_HABILITATION)).build(); + User mockedResponse = User.builder().username("TOTO").habilitations(List.of(PLATINE_HABILITATION)).build(); + mockRetrieveBody(mockedResponse); + + //Call method under tests + User returnerUser = service.postCreateUser(createSugoiUserBody); + + //Verify + verify(restClientHelper).getRestClient(KNOWN_API_SUGOI); + verify(restClient).post(); + + UriBuilder mockUriBuilder = mockPostPutPatchURIBuilderAndPrepareForTest(); + + // Verify that the correct path and query parameters were used + verify(mockUriBuilder).path(eq("/realms/{realm}/storages/{storage}/users")); + verify(mockUriBuilder).build(eq(realm), eq(STORAGE)); + + // and with expected body + verify(requestBodyUriSpec).body(createSugoiUserBody); + } + + @Test + void postCreateUser_should_throw_when_param_is_null(){ + assertThrows(SugoiServiceCallBPMNError.class, () -> service.postCreateUser(null)); + } + + + + @Test + void postCreateUsers_shouldCatch() { + //Prepare + Habilitation PLATINE_HABILITATION = new Habilitation("platine", "repondant", null); + User createSugoiUserBody = User.builder().habilitations(List.of(PLATINE_HABILITATION)).build(); + + mockMakeRetrieveThrow(HttpStatusCode.valueOf(HttpStatus.BAD_REQUEST.value())); + //Call method under tests + assertThrows(HttpClient4xxBPMNError.class, () -> service.postCreateUser(createSugoiUserBody)); + + //Call method under tests + createSugoiUserBody.setUsername(null); + assertThrows(HttpClient4xxBPMNError.class, () -> service.postCreateUser(createSugoiUserBody)); + } + + + @Test + void postCreateUser_shouldCatch_409Conflict() { + //Prepare + Habilitation PLATINE_HABILITATION = new Habilitation("platine", "repondant", null); + User createSugoiUserBody = User.builder().habilitations(List.of(PLATINE_HABILITATION)).build(); + + + mockMakeRetrieveThrow(HttpStatusCode.valueOf(HttpStatus.CONFLICT.value())); + //Call method under tests + UsernameAlreadyExistsSugoiBPMNError exception = assertThrows(UsernameAlreadyExistsSugoiBPMNError.class, () -> service.postCreateUser(createSugoiUserBody)); + assertThat(exception.getMessage(), containsString("during SUGOI post create users")); + + + //Call method under tests + createSugoiUserBody.setUsername(null); + UsernameAlreadyExistsSugoiBPMNError exception2 = assertThrows(UsernameAlreadyExistsSugoiBPMNError.class, () -> service.postCreateUser(createSugoiUserBody)); + assertThat(exception.getMessage(), containsString("during SUGOI post create users")); + assertThat(exception.getMessage(), containsString("null")); + + + } + + @Test + void postInitPassword_should_call_correctURIAndBody() { + //Prepare + String userId="GéGé"; + String pwd = "****"; + + //Call method under tests + service.postInitPassword(userId,pwd); + + //Verify + verify(restClientHelper).getRestClient(KNOWN_API_SUGOI); + verify(restClient).post(); + + UriBuilder mockUriBuilder = mockPostPutPatchURIBuilderAndPrepareForTest(); + + // Verify that the correct path and query parameters were used + verify(mockUriBuilder).path(eq("/realms/{realm}/users/{id}/init-password")); + verify(mockUriBuilder).build(eq(realm), eq(userId)); + ArgumentCaptor bodyCaptor = ArgumentCaptor.forClass(JsonNode.class); + verify(requestBodyUriSpec).body(bodyCaptor.capture()); + + assertEquals(1, bodyCaptor.getAllValues().size(),"We should have exactly one body"); + JsonNode body=bodyCaptor.getValue(); + assertEquals(pwd,body.path("password").asText(),"The passed password is incorrect"); + } +} \ No newline at end of file diff --git a/src/test/java/fr/insee/protools/backend/service/sugoi_rem/delegate/SugoiREMCreateMissingAccountListTaskTest.java b/src/test/java/fr/insee/protools/backend/service/sugoi_rem/delegate/SugoiREMCreateMissingAccountListTaskTest.java new file mode 100644 index 00000000..29a2bd57 --- /dev/null +++ b/src/test/java/fr/insee/protools/backend/service/sugoi_rem/delegate/SugoiREMCreateMissingAccountListTaskTest.java @@ -0,0 +1,170 @@ +package fr.insee.protools.backend.service.sugoi_rem.delegate; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import fr.insee.protools.backend.dto.ContexteProcessus; +import fr.insee.protools.backend.dto.sugoi.Habilitation; +import fr.insee.protools.backend.dto.sugoi.User; +import fr.insee.protools.backend.service.rem.RemServiceImpl; +import fr.insee.protools.backend.service.sugoi.SugoiServiceImpl; +import fr.insee.protools.backend.service.utils.delegate.TestDelegateWithContext; +import fr.insee.protools.backend.service.utils.password.PasswordService; +import org.apache.commons.lang3.RandomStringUtils; +import org.flowable.engine.delegate.DelegateExecution; +import org.flowable.engine.delegate.JavaDelegate; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.mockito.AdditionalAnswers; +import org.mockito.ArgumentCaptor; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.stream.IntStream; +import java.util.stream.Stream; + +import static fr.insee.protools.backend.service.FlowableVariableNameConstants.VARNAME_CURRENT_PARTITION_ID; +import static fr.insee.protools.backend.utils.data.CtxExamples.*; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +class SugoiREMCreateMissingAccountListTaskTest extends TestDelegateWithContext { + + @Mock + RemServiceImpl remService; + + @Mock + SugoiServiceImpl sugoiService; + + @Mock + PasswordService passwordService; + + @InjectMocks + SugoiREMCreateMissingAccountListTask task; + + @Override + public JavaDelegate getTaskUnderTest() { + return task; + } + + ///provide ctx and expected password length and list of rem Ids for which we need to init a username/pwd + private static Stream executeContextOKArgs() { + return Stream.of("menage", "entreprise") + .flatMap(contexte -> + IntStream.rangeClosed(0, 10) + .mapToObj(size -> Arguments.of(contexte, + IntStream.rangeClosed(1, 1+10*size) + .mapToObj(i -> "ID_" + i) + .toList() + )) + ); + } + + @ParameterizedTest + @MethodSource("executeContextOKArgs") + public void execute_should_work_whenEverythingOk(String context,List remIdInterroWithoutAccount) { + record MockData(String idInterro, String sugoiResponseUserName, User createdUser, String pwd) { + } + Habilitation PLATINE_HABILITATION = new Habilitation("platine", "repondant", null); + User expectedCreateSugoiUserBody = User.builder().habilitations(List.of(PLATINE_HABILITATION)).build(); + String partitionId = UUID.randomUUID().toString(); + + int tmpexpectedPwdSize=-1; + String contexts_as_string; + if(context.equals("menage")) + { + contexts_as_string= CTX_CONTEXTE_MENAGE; + tmpexpectedPwdSize=8; + } + else if(context.equals("entreprise")){ + contexts_as_string=ctx_contexte_entreprise; + tmpexpectedPwdSize=12; + } + else { + assertFalse(Boolean.TRUE,"Tests parameters are incorrects"); + return; + } + final int expectedPwdSize=tmpexpectedPwdSize; + + //Prepare + DelegateExecution execution = createMockedExecution(); + JsonNode expectedContext = initContexteMockWithString(contexts_as_string); + + List mockDataList = remIdInterroWithoutAccount.stream() + .map(id -> { + String pwd = RandomStringUtils.randomAlphanumeric(expectedPwdSize); + String userName = "USER_" + RandomStringUtils.randomAlphanumeric(10); + User sugoiUserResponse = User.builder().username(userName).habilitations(List.of(PLATINE_HABILITATION)).build(); + return new MockData(id, userName, sugoiUserResponse, pwd); + }) + .toList(); + + when(sugoiService.postCreateUser(any())).thenAnswer(AdditionalAnswers.returnsElementsOf(mockDataList.stream().map(MockData::createdUser).toList())); + when(passwordService.generatePassword(expectedPwdSize)).thenAnswer(AdditionalAnswers.returnsElementsOf(mockDataList.stream().map(MockData::pwd).toList())); + + doReturn(partitionId).when(execution).getVariable(VARNAME_CURRENT_PARTITION_ID, String.class); + doReturn(remIdInterroWithoutAccount).when(remService).getInterrogationIdsWithoutAccountForPartition(partitionId); + + //Call method under test + task.execute(execution); + + //Verify + verify(remService, times(1)).getInterrogationIdsWithoutAccountForPartition(eq(partitionId)); + verify(passwordService, times(remIdInterroWithoutAccount.size())).generatePassword(eq(expectedPwdSize)); + verify(sugoiService, times(remIdInterroWithoutAccount.size())).postCreateUser(eq(expectedCreateSugoiUserBody)); + + // Verification that postInitPassword was called once for each element in mockDataList + for (MockData mockData : mockDataList) { + verify(sugoiService, times(1)).postInitPassword(mockData.sugoiResponseUserName(), mockData.pwd()); + } + + ArgumentCaptor patchArgs = ArgumentCaptor.forClass(Map.class); + verify(remService, times(1)).patchInterrogationsSetAccounts(patchArgs.capture()); + var args = patchArgs.getValue(); + for (MockData mockData : mockDataList) { + assertTrue(args.containsKey(mockData.idInterro), "Arguments passed to patchInterrogationsSetAccounts are incorrect"); + assertEquals(args.get(mockData.idInterro), mockData.sugoiResponseUserName, "Arguments passed to patchInterrogationsSetAccounts are incorrect"); + } + assertEquals(mockDataList.size(), args.size(), "Arguments passed to patchInterrogationsSetAccounts are incorrect (wrong number)"); + } + + @Override + public Map getVariablesAndTypes() { + return Map.of( + VARNAME_CURRENT_PARTITION_ID, String.class + ); + } + + @Override + protected String minimalValidCtxt() { + return CTX_CONTEXTE_MENAGE; + } + + @Test + void getPasswordSize_should_return8_for_menage() throws JsonProcessingException { + //prepare + ContexteProcessus schema = new ObjectMapper().readValue(CTX_CONTEXTE_MENAGE, ContexteProcessus.class); + //Call method under tests + int pwdSize=task.getPasswordSize(schema); + //Verify + assertEquals(8,pwdSize,"Expected password size of 8 for menage"); + } + + @Test + void getPasswordSize_should_return_12_for_not_menage() throws JsonProcessingException { + //prepare + ContexteProcessus schema = new ObjectMapper().readValue(ctx_contexte_entreprise, ContexteProcessus.class); + //Call method under tests + int pwdSize=task.getPasswordSize(schema); + //Verify + assertEquals(12,pwdSize,"Expected password size of 12 for entreprise"); + } +} \ No newline at end of file diff --git a/src/test/java/fr/insee/protools/backend/service/traiterxxxx/TraiterXXXServiceTest.java b/src/test/java/fr/insee/protools/backend/service/traiterxxxx/TraiterXXXServiceTest.java new file mode 100644 index 00000000..730055d1 --- /dev/null +++ b/src/test/java/fr/insee/protools/backend/service/traiterxxxx/TraiterXXXServiceTest.java @@ -0,0 +1,76 @@ +package fr.insee.protools.backend.service.traiterxxxx; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.JsonNodeFactory; +import fr.insee.protools.backend.service.utils.TestServiceWithRestClient; +import org.hamcrest.collection.IsIterableContainingInAnyOrder; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.web.util.UriBuilder; + +import java.util.List; +import java.util.UUID; + +import static fr.insee.protools.backend.restclient.configuration.ApiConfigProperties.KNOWN_API.KNOWN_API_TRAITERXXX; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.mockito.Mockito.verify; + +@ExtendWith(MockitoExtension.class) +class TraiterXXXServiceTest extends TestServiceWithRestClient { + + private static ObjectMapper objectMapper = new ObjectMapper(); + + @InjectMocks + TraiterXXXServiceImpl service; + + @Test + void postContext_should_call_correctURIAndBody() { + //Prepare + JsonNode contextNode = JsonNodeFactory.instance.objectNode(); + + //Call method under test + service.postContext("TOTO", contextNode); + + //Verifications + // Then - Verify that the uri method was called with "/context" + verify(restClientHelper).getRestClient(KNOWN_API_TRAITERXXX); + verify(restClient).post(); + verify(requestBodyUriSpec).uri("/context"); + // and with expected body + verify(requestBodyUriSpec).body(contextNode); + } + + @Test + void getRemiseEnCollecteForPartition_should_makeCorrectCalls() { + //Prepare + String partitionId = "PartitionIDXXREM"; + String expectedID1 = UUID.randomUUID().toString(); + String expectedID2 = UUID.randomUUID().toString(); + + + List mockedResponse = List.of( + objectMapper.createObjectNode().put("id", expectedID1).put("count", "1"), + objectMapper.createObjectNode().put("id", expectedID2).put("compta", "2") + ); + mockRetrieveBody(mockedResponse); + + //Call method under tests + List response = service.getRemiseEnCollecteForPartition(partitionId); + + //Verify + verify(restClientHelper).getRestClient(KNOWN_API_TRAITERXXX); + verify(restClient).get(); + + UriBuilder mockUriBuilder = mockGETURIBuilderAndPrepareForTest(); + + // Verify that the correct path and query parameters were used + verify(mockUriBuilder).path("/remise-en-collecte"); + verify(mockUriBuilder).queryParam("partition_id", partitionId); + + assertThat(response, + IsIterableContainingInAnyOrder.containsInAnyOrder(mockedResponse.toArray())); + } +} \ No newline at end of file diff --git a/src/test/java/fr/insee/protools/backend/service/traiterxxxx/delegate/TraiterXXXCreateContextTaskRESTTest.java b/src/test/java/fr/insee/protools/backend/service/traiterxxxx/delegate/TraiterXXXCreateContextTaskRESTTest.java new file mode 100644 index 00000000..3021f6ca --- /dev/null +++ b/src/test/java/fr/insee/protools/backend/service/traiterxxxx/delegate/TraiterXXXCreateContextTaskRESTTest.java @@ -0,0 +1,64 @@ +package fr.insee.protools.backend.service.traiterxxxx.delegate; + +import com.fasterxml.jackson.databind.JsonNode; +import fr.insee.protools.backend.service.traiterxxxx.TraiterXXXServiceImpl; +import fr.insee.protools.backend.service.utils.delegate.TestDelegateWithContext; +import org.flowable.engine.delegate.DelegateExecution; +import org.flowable.engine.delegate.JavaDelegate; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.InjectMocks; +import org.mockito.Mock; + +import java.util.List; +import java.util.Map; + +import static fr.insee.protools.backend.utils.data.CtxExamples.CTX_EMPTY; +import static fr.insee.protools.backend.utils.data.CtxExamples.CTX_EMPTY_ID; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +public class TraiterXXXCreateContextTaskRESTTest extends TestDelegateWithContext { + + @Mock + TraiterXXXServiceImpl traiterService; + + @InjectMocks + TraiterXXXCreateContextTaskREST traiterCreateContextTask; + + + @Override + public JavaDelegate getTaskUnderTest() { + return traiterCreateContextTask; + } + + @Override + public Map getVariablesAndTypes() { + return Map.of(); + } + + @Test + void execute_should_work_when_contextOK() { + DelegateExecution execution = createMockedExecution(); + JsonNode expectedContext = initContexteMockWithString(CTX_EMPTY); + + //Execute the unit under test + traiterCreateContextTask.execute(execution); + + //Verify postContext + ArgumentCaptor acCtx = ArgumentCaptor.forClass(JsonNode.class); + verify(traiterService, times(1)).postContext(eq(CTX_EMPTY_ID), acCtx.capture()); + List allValues = acCtx.getAllValues(); + assertEquals(1, allValues.size(), "We should have exactly one value"); + + assertEquals(expectedContext, allValues.get(0), "Wrong context passed"); + + } + + @Override + protected String minimalValidCtxt() { + return CTX_EMPTY; + } +} \ No newline at end of file diff --git a/src/test/java/fr/insee/protools/backend/service/traiterxxxx/delegate/TraiterXXXGetRemiseEnCollecteTaskRESTTest.java b/src/test/java/fr/insee/protools/backend/service/traiterxxxx/delegate/TraiterXXXGetRemiseEnCollecteTaskRESTTest.java new file mode 100644 index 00000000..82d79367 --- /dev/null +++ b/src/test/java/fr/insee/protools/backend/service/traiterxxxx/delegate/TraiterXXXGetRemiseEnCollecteTaskRESTTest.java @@ -0,0 +1,68 @@ +package fr.insee.protools.backend.service.traiterxxxx.delegate; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import fr.insee.protools.backend.service.traiterxxxx.TraiterXXXServiceImpl; +import fr.insee.protools.backend.service.utils.delegate.IDelegateWithVariables; +import org.flowable.engine.delegate.DelegateExecution; +import org.flowable.engine.delegate.JavaDelegate; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import static fr.insee.protools.backend.service.FlowableVariableNameConstants.VARNAME_CURRENT_PARTITION_ID; +import static fr.insee.protools.backend.service.FlowableVariableNameConstants.VARNAME_INTERRO_REMISE_EN_COLLECTE_LIST; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +class TraiterXXXGetRemiseEnCollecteTaskRESTTest implements IDelegateWithVariables { + + private static ObjectMapper objectMapper = new ObjectMapper(); + + @Mock + TraiterXXXServiceImpl service; + + @InjectMocks + TraiterXXXGetRemiseEnCollecteTaskREST task; + + @Override + public JavaDelegate getTaskUnderTest() { + return task; + } + + @Override + public Map getVariablesAndTypes() { + return Map.of( + VARNAME_CURRENT_PARTITION_ID, String.class + ); + } + + @Test + @DisplayName("Test execute method - should work and make correct call to service") + void execute_should_work_whenEverythingOk() { + //Prepare + String currentPartitionId = UUID.randomUUID().toString(); + DelegateExecution execution = createMockedExecution(); + doReturn(execution).when(execution).getParent(); + doReturn(currentPartitionId).when(execution).getVariable(VARNAME_CURRENT_PARTITION_ID,String.class); + + List mockedResponse = List.of( + objectMapper.createObjectNode().put("id", 1).put("id", "toto"), + objectMapper.createObjectNode().put("identifier", 1).put("tatxa", "toto")); + + doReturn(mockedResponse).when(service).getRemiseEnCollecteForPartition(eq(currentPartitionId)); + //Call method under tests + task.execute(execution); + + //Verify + verify(execution).setVariableLocal(eq(VARNAME_INTERRO_REMISE_EN_COLLECTE_LIST), eq(mockedResponse)); + } +} \ No newline at end of file diff --git a/src/test/java/fr/insee/protools/backend/service/utils/ContextUtilsTest.java b/src/test/java/fr/insee/protools/backend/service/utils/ContextUtilsTest.java deleted file mode 100644 index 07582aac..00000000 --- a/src/test/java/fr/insee/protools/backend/service/utils/ContextUtilsTest.java +++ /dev/null @@ -1,61 +0,0 @@ -package fr.insee.protools.backend.service.utils; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.flowable.common.engine.api.FlowableIllegalArgumentException; -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; - -class ContextUtilsTest { - - final String json0Partition = - "{ \"partitions\": [ ] }"; - final String json1Partition = - "{ \"partitions\": [{ \"id\": 1 , \"toto\": \"val1\" }] }"; - final String json2Partition = - "{ \"partitions\": [{ \"id\": 1 , \"toto\": \"val1\" }, { \"id\": 2 , \"toto\": \"val2\" }] }"; - - @Test - void getCurrentPartitionNode_ShouldReturnCorrectPartitionNode_WhenFound() throws JsonProcessingException { - // Arrange - JsonNode contextRootNode = new ObjectMapper().readTree(json1Partition); - // Act - JsonNode result = ContextUtils.getCurrentPartitionNode(contextRootNode, 1l); - // Assert - assertEquals("val1",result.path("toto").asText()); - } - - @Test - void getCurrentPartitionNode_ShouldReturnCorrectPartitionNode_WhenFound2() throws JsonProcessingException { - // Arrange - JsonNode contextRootNode = new ObjectMapper().readTree(json2Partition); - // Act - JsonNode result = ContextUtils.getCurrentPartitionNode(contextRootNode, 2l); - // Assert - assertEquals("val2",result.path("toto").asText()); - } - - - @Test - void getCurrentPartitionNode_ShouldThrowFlowableIllegalArgumentException_WhenPartitionNotFound() throws JsonProcessingException { - // Arrange - JsonNode contextRootNode = new ObjectMapper().readTree(json0Partition); - - // Act - assertThrows(FlowableIllegalArgumentException.class, - () -> ContextUtils.getCurrentPartitionNode(contextRootNode, 55l)); - } - - @Test - void getCurrentPartitionNode_ShouldThrowFlowableIllegalArgumentException_WhenPartitionNoPartition() throws JsonProcessingException { - // Arrange - JsonNode contextRootNode = new ObjectMapper().readTree(""); - - // Act - assertThrows(FlowableIllegalArgumentException.class, - () -> ContextUtils.getCurrentPartitionNode(contextRootNode, 55l)); - } -} \ No newline at end of file diff --git a/src/test/java/fr/insee/protools/backend/service/utils/CustomJWTHelper.java b/src/test/java/fr/insee/protools/backend/service/utils/CustomJWTHelper.java new file mode 100644 index 00000000..946f69e6 --- /dev/null +++ b/src/test/java/fr/insee/protools/backend/service/utils/CustomJWTHelper.java @@ -0,0 +1,63 @@ +package fr.insee.protools.backend.service.utils; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.springframework.security.oauth2.jwt.Jwt; + +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; +import java.nio.charset.StandardCharsets; +import java.util.Base64; +import java.util.List; + +public class CustomJWTHelper { + + private static final String SECRET_KEY = "my-secret-key"; + private static final String ALGO = "HmacSHA256"; + + private static final ObjectMapper objectMapper = new ObjectMapper(); + + private CustomJWTHelper() { + } + + public static String getEncodedToken(List roles) throws Exception { + + ObjectNode realmAccessNode = new ObjectMapper().createObjectNode(); + ArrayNode rolesNode = new ObjectMapper().createArrayNode(); + for (String role:roles){ + rolesNode.add(role); + } + realmAccessNode.set("roles", rolesNode); + + Jwt kcToken = Jwt.withTokenValue("token").header("alg", ALGO). + claim("realm_access", realmAccessNode) + .build(); + return getEncodedToken(kcToken); + } + + public static String getEncodedToken(Jwt token) throws Exception { + + byte[] a = objectMapper.writeValueAsString(token.getHeaders()).getBytes(StandardCharsets.UTF_8); + byte[] b = objectMapper.writeValueAsString(token.getClaims()).getBytes(StandardCharsets.UTF_8); + + String encodedHeader = Base64.getEncoder().encodeToString(a); + String encodedPayload = Base64.getEncoder().encodeToString(b); + + // Create the signature + String signature = createSignature(encodedHeader, encodedPayload); + + // Concatenate header, payload, and signature to form the JWT + return encodedHeader + "." + encodedPayload + "." + signature; + } + + public static String createSignature(String header, String payload) throws Exception { + String data = header + "." + payload; + Mac sha256Hmac = Mac.getInstance("HmacSHA256"); + SecretKeySpec secretKeySpec = new SecretKeySpec(SECRET_KEY.getBytes(StandardCharsets.UTF_8), ALGO); + sha256Hmac.init(secretKeySpec); + + byte[] signatureBytes = sha256Hmac.doFinal(data.getBytes(StandardCharsets.UTF_8)); + return Base64.getUrlEncoder().encodeToString(signatureBytes); + } +} diff --git a/src/test/java/fr/insee/protools/backend/service/utils/FlowableVariableUtilsTest.java b/src/test/java/fr/insee/protools/backend/service/utils/FlowableVariableUtilsTest.java index 200a0afb..b7171deb 100644 --- a/src/test/java/fr/insee/protools/backend/service/utils/FlowableVariableUtilsTest.java +++ b/src/test/java/fr/insee/protools/backend/service/utils/FlowableVariableUtilsTest.java @@ -7,10 +7,10 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.junit.jupiter.MockitoExtension; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.*; + @ExtendWith(MockitoExtension.class) class FlowableVariableUtilsTest { diff --git a/src/test/java/fr/insee/protools/backend/service/utils/TestServiceWithRestClient.java b/src/test/java/fr/insee/protools/backend/service/utils/TestServiceWithRestClient.java new file mode 100644 index 00000000..b2637908 --- /dev/null +++ b/src/test/java/fr/insee/protools/backend/service/utils/TestServiceWithRestClient.java @@ -0,0 +1,130 @@ +package fr.insee.protools.backend.service.utils; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.JsonNodeFactory; +import fr.insee.protools.backend.restclient.RestClientHelper; +import fr.insee.protools.backend.restclient.exception.runtime.HttpClient4xxBPMNError; +import fr.insee.protools.backend.restclient.pagination.PageResponse; +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.ArgumentMatchers; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.HttpStatusCode; +import org.springframework.web.client.RestClient; +import org.springframework.web.util.UriBuilder; + +import java.net.URI; +import java.util.List; +import java.util.Optional; +import java.util.function.Function; + +import static fr.insee.protools.backend.restclient.configuration.ApiConfigProperties.KNOWN_API.KNOWN_API_TRAITERXXX; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +public class TestServiceWithRestClient { + @Mock + protected RestClient restClient; + @Mock + protected RestClientHelper restClientHelper; + @Mock + protected RestClient.RequestBodyUriSpec requestBodyUriSpec; // Mock post() call + @Mock + protected RestClient.ResponseSpec responseSpec; // Mock retrieve() call + @Mock + protected RestClient.RequestHeadersUriSpec requestHeadersUriSpec; + + @BeforeEach + void initRestClientMock() { + //Prepare + lenient().doReturn(restClient).when(restClientHelper).getRestClient(any()); + // Mock the chaining of RestClient calls for post/put/patch + lenient().when(restClient.post()).thenReturn(requestBodyUriSpec); + lenient().when(restClient.put()).thenReturn(requestBodyUriSpec); + lenient().when(restClient.patch()).thenReturn(requestBodyUriSpec); + + lenient().when(requestBodyUriSpec.uri(anyString(), any(Object[].class))).thenReturn(requestBodyUriSpec); + lenient().when(requestBodyUriSpec.uri(ArgumentMatchers.>any())).thenReturn(requestBodyUriSpec); + + lenient().when(requestBodyUriSpec.body(any(Object.class))).thenReturn(requestBodyUriSpec); + lenient().when(requestBodyUriSpec.retrieve()).thenReturn(responseSpec); + + //Specific for get + lenient().when(restClient.get()).thenReturn(requestHeadersUriSpec); + lenient().when(requestHeadersUriSpec.uri(anyString(), any(Object[].class))).thenReturn(requestBodyUriSpec); + lenient().when(requestHeadersUriSpec.uri(ArgumentMatchers.>any())).thenReturn(requestBodyUriSpec); + lenient().when(requestHeadersUriSpec.retrieve()).thenReturn(responseSpec); + } + + public UriBuilder mockPostPutPatchURIBuilderAndPrepareForTest() { + // let's manually build a URI using the captured function and a mock UriBuilder + ArgumentCaptor> uriCaptor = ArgumentCaptor.forClass(Function.class); + verify(requestBodyUriSpec).uri(uriCaptor.capture()); + UriBuilder mockUriBuilder = mock(UriBuilder.class); + lenient().when(mockUriBuilder.path(anyString())).thenReturn(mockUriBuilder); + lenient().when(mockUriBuilder.queryParam(anyString(), ArgumentMatchers.any())).thenReturn(mockUriBuilder); + lenient().when(mockUriBuilder.queryParamIfPresent(anyString(), ArgumentMatchers.>any())).thenReturn(mockUriBuilder); + + lenient().when(mockUriBuilder.build(ArgumentMatchers.any())).thenReturn(URI.create("http://mockeduri")); + + // Call the captured function with the mocked UriBuilder + uriCaptor.getValue().apply(mockUriBuilder); + + return mockUriBuilder; + } + + + public UriBuilder mockGETURIBuilderAndPrepareForTest() { + // let's manually build a URI using the captured function and a mock UriBuilder + ArgumentCaptor> uriCaptor = ArgumentCaptor.forClass(Function.class); + verify(requestHeadersUriSpec).uri(uriCaptor.capture()); + UriBuilder mockUriBuilder = mock(UriBuilder.class); + when(mockUriBuilder.path(anyString())).thenReturn(mockUriBuilder); + when(mockUriBuilder.queryParam(anyString(), ArgumentMatchers.any())).thenReturn(mockUriBuilder); + lenient().when(mockUriBuilder.queryParamIfPresent(anyString(), ArgumentMatchers.>any())).thenReturn(mockUriBuilder); + + when(mockUriBuilder.build()).thenReturn(URI.create("http://mockeduri")); + + // Call the captured function with the mocked UriBuilder + uriCaptor.getValue().apply(mockUriBuilder); + + return mockUriBuilder; + } + + public void mockRetrieveBodyResponse(List l) { + PageResponse mockResponse = PageResponse.builder().content(l).build(); + lenient().when(responseSpec.body(ArgumentMatchers.any())).thenReturn(mockResponse); + lenient().when(responseSpec.body(ArgumentMatchers.any())).thenReturn(mockResponse); + } + + public void mockRetrieveBody(Object l) { + lenient().when(responseSpec.body(ArgumentMatchers.any())).thenReturn(l); + lenient().when(responseSpec.body(ArgumentMatchers.any())).thenReturn(l); + } + + public void mockMakeRetrieveThrow(HttpStatusCode errorCode) { + HttpClient4xxBPMNError ex = new HttpClient4xxBPMNError("msg", errorCode); + lenient().when(requestBodyUriSpec.retrieve()).thenThrow(ex); + //Specific for get + lenient().when(requestHeadersUriSpec.retrieve()).thenThrow(ex); + } + + public void assertCorrectPageResponseForNull(PageResponse pageResponse){ + assertNotNull(pageResponse,"The response should not be null"); + assertThat("The response should have empty content",pageResponse.getContent().isEmpty()); + assertEquals(5000,pageResponse.getPageSize(),"The response should have pageSize == 5000"); + assertEquals(0,pageResponse.getPageCount(),"The response should have pageCount == 0"); + assertEquals(0,pageResponse.getCurrentPage(),"The response should have currentPage == 0"); + assertEquals(0,pageResponse.getTotalElements(),"The response should have totalElements == 0"); + } + +} diff --git a/src/test/java/fr/insee/protools/backend/service/utils/TestWithContext.java b/src/test/java/fr/insee/protools/backend/service/utils/TestWithContext.java deleted file mode 100644 index f68ac6b4..00000000 --- a/src/test/java/fr/insee/protools/backend/service/utils/TestWithContext.java +++ /dev/null @@ -1,54 +0,0 @@ -package fr.insee.protools.backend.service.utils; - -import com.fasterxml.jackson.databind.JsonNode; -import fr.insee.protools.backend.ProtoolsTestUtils; -import fr.insee.protools.backend.service.context.ContextService; -import fr.insee.protools.backend.service.context.exception.BadContextIncorrectBPMNError; -import org.flowable.engine.delegate.DelegateExecution; -import org.flowable.engine.delegate.JavaDelegate; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Spy; -import org.mockito.junit.jupiter.MockitoExtension; - -import java.io.IOException; -import java.io.UncheckedIOException; - -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.*; - -@ExtendWith(MockitoExtension.class) -public abstract class TestWithContext { - - @Spy protected ContextService protoolsContext; - - protected final String dumyId="ID1"; - - protected JsonNode initContexteMockWithFile(String contexteToLoad){ - JsonNode contextRootNode = ProtoolsTestUtils.asJsonNode(contexteToLoad); - doReturn(contextRootNode).when(protoolsContext).getContextByProcessInstance(anyString()); - return contextRootNode; - } - - protected JsonNode initContexteMockWithString(String contexteAsString){ - try{ - return ProtoolsTestUtils.initContexteMockFromString(protoolsContext,contexteAsString); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - } - public DelegateExecution createMockedExecution(){ - DelegateExecution execution = mock(DelegateExecution.class); - doReturn(dumyId).when(execution).getProcessInstanceId(); - return execution; - } - - protected void assertThat_delegate_throwError_when_null_context(JavaDelegate delegate) { - //Precondition - DelegateExecution execution = mock(DelegateExecution.class); - lenient().when(execution.getProcessInstanceId()).thenReturn(dumyId); - doReturn(null).when(protoolsContext).getContextByProcessInstance(anyString()); - - assertThrows(BadContextIncorrectBPMNError.class, () -> delegate.execute(execution)); - } -} diff --git a/src/test/java/fr/insee/protools/backend/service/utils/data/CtxExamples.java b/src/test/java/fr/insee/protools/backend/service/utils/data/CtxExamples.java deleted file mode 100644 index 33ca4849..00000000 --- a/src/test/java/fr/insee/protools/backend/service/utils/data/CtxExamples.java +++ /dev/null @@ -1,123 +0,0 @@ -package fr.insee.protools.backend.service.utils.data; - -public class CtxExamples { - - public static final Long ctx_partition1 = 99L; - - //CTX - public static final String ctx_no_part = - """ - { - "id": "AAC2023A00" - } - """; - - public static final String ctx_idCampagne_idPartition = - """ - { - "id": "AAC2023A00", - "partitions": [{ - "id": 99 - }] - } - """; - - public static final String ctx_idCampagne_1emptyPartition = - """ - { - "id": "AAC2023A00", - "partitions": [{ - }] - } - """; - - public static final String ctx_idCampagne_idPartition_typeLogement = - """ - { - "id": "AAC2023A00", - "partitions": [{ - "id": 99, - "typeEchantillon" : "LOGEMENT" - }] - } - """; - - public static final String ctx_idCampagne_idPartition_typeIndividu = - """ - { - "id": "AAC2023A00", - "partitions": [{ - "id": 99, - "typeEchantillon" : "individu" - }] - } - """; - - public static final String ctx_questionnaireModels_no_part = - """ - { - "id": "AAC2023A00", - "questionnaireModels": [{ - "id": "ID_1", - "cheminRepertoire": "path", - "label": "ID_1_LABEL", - "requiredNomenclatureIds": [ - "NOMA-1-1-0", - "NOMB-1-1-0" - ] - }] - } - """; - - public static final String ctx_idCampagne_questionnaireModels_idPartition = - """ - { - "id": "AAC2023A00", - "partitions": [{ - "id": 99 - }], - "questionnaireModels": [{ - "id": "ID_1", - "cheminRepertoire": "path", - "label": "ID_1_LABEL", - "requiredNomenclatureIds": [ - "NOMA-1-1-0", - "NOMB-1-1-0" - ] - }] - } - """; - - public static final String ctx_idCampagne_questionnaireModels_1emptyPartition = - """ - { - "id": "AAC2023A00", - "partitions": [{ - }], - "questionnaireModels": [{ - "id": "ID_1", - "cheminRepertoire": "path", - "label": "ID_1_LABEL", - "requiredNomenclatureIds": [ - "NOMA-1-1-0", - "NOMB-1-1-0" - ] - }] - } - """; - - public static final String ctx_idCampagne_emptyQuestionnaireModels_idPartition = - """ - { - "id": "AAC2023A00", - "partitions": [{ - "id": 99 - }], - "questionnaireModels": [] - } - """; - - - - private CtxExamples(){} -} diff --git a/src/test/java/fr/insee/protools/backend/service/utils/data/RemSUData.java b/src/test/java/fr/insee/protools/backend/service/utils/data/RemSUData.java deleted file mode 100644 index ab41b7c9..00000000 --- a/src/test/java/fr/insee/protools/backend/service/utils/data/RemSUData.java +++ /dev/null @@ -1,16 +0,0 @@ -package fr.insee.protools.backend.service.utils.data; - -import org.springframework.util.ClassUtils; - -public class RemSUData { - private RemSUData() {} - - final static String ressourceFolder = ClassUtils.convertClassNameToResourcePath(RemSUData.class.getPackageName()); - - - public final static String rem_su_1personne = ressourceFolder+"/rem-su_1personne.json"; - public final static String rem_su_3personnes = ressourceFolder+"/rem-su_3personnes.json"; - public final static String getRem_su_1personne_noContact = ressourceFolder+"/rem-su-noMainOrSurveyed.json"; - public final static String rem_su_test_selection_3personnes = ressourceFolder+"/rem-su-test-selection.json"; - -} diff --git a/src/test/java/fr/insee/protools/backend/service/utils/delegate/IDelegateWithVariableGetPaginated.java b/src/test/java/fr/insee/protools/backend/service/utils/delegate/IDelegateWithVariableGetPaginated.java new file mode 100644 index 00000000..3ec413f8 --- /dev/null +++ b/src/test/java/fr/insee/protools/backend/service/utils/delegate/IDelegateWithVariableGetPaginated.java @@ -0,0 +1,91 @@ +package fr.insee.protools.backend.service.utils.delegate; + +import com.fasterxml.jackson.databind.ObjectMapper; +import fr.insee.protools.backend.restclient.pagination.PageResponse; +import org.flowable.engine.delegate.DelegateExecution; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.mockito.ArgumentCaptor; + +import java.util.List; +import java.util.Map; +import java.util.stream.Stream; + +import static fr.insee.protools.backend.service.FlowableVariableNameConstants.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.*; + +public interface IDelegateWithVariableGetPaginated extends IDelegateWithVariables { + + ObjectMapper objectMapper = new ObjectMapper(); + + void initReadValueMock(PageResponse pageResponse); + String getOutListVariableName(); + + + @Override + default void initExtraMocks(DelegateExecution execution) { + IDelegateWithVariables.super.initExtraMocks(execution); + PageResponse exepectedPageResponse = PageResponse.builder().currentPage(0).pageCount(1).content(List.of(objectMapper.createObjectNode().put("xx","yyy"))).build(); + initReadValueMock(exepectedPageResponse); + } + + static Stream executeParamProvider() { + return Stream.of( + Arguments.of(null, true), + Arguments.of(null, false), + Arguments.of(0, true), + Arguments.of(0, false), + Arguments.of(1, true), + Arguments.of(1, false), + Arguments.of(99, true), + Arguments.of(1011, false) + ); + } + + @ParameterizedTest + @MethodSource("executeParamProvider") + default void execute_should_work_when_params_notNullWithPaginated(Integer currentPage,boolean isLastPage) { + //Preconditions + DelegateExecution execution = mock(DelegateExecution.class); + lenient().when(execution.getProcessInstanceId()).thenReturn(dumyId); + lenient().when(execution.getParent()).thenReturn(execution); + + initDefaultVariables(execution); + + //Pages data + lenient().doReturn(currentPage).when(execution).getVariable(eq(VARNAME_INTERRO_LIST_PAGEABLE_CURRENT_PAGE), eq(Integer.class)); + lenient().doReturn(currentPage).when(execution).getVariableLocal(eq(VARNAME_INTERRO_LIST_PAGEABLE_CURRENT_PAGE), eq(Integer.class)); + + lenient().doReturn(isLastPage).when(execution).getVariable(eq(VARNAME_INTERRO_LIST_PAGEABLE_IS_LAST_PAGE), eq(Boolean.class)); + lenient().doReturn(isLastPage).when(execution).getVariableLocal(eq(VARNAME_INTERRO_LIST_PAGEABLE_IS_LAST_PAGE), eq(Boolean.class)); + + + //PageResponse + Integer expectedPageToRead=(currentPage==null)?0:currentPage+1; + PageResponse exepectedPageResponse = PageResponse.builder().currentPage(expectedPageToRead).pageCount(1).content(List.of(objectMapper.createObjectNode().put("xx","yyy"))).build(); + initReadValueMock(exepectedPageResponse); + //Call method under test + getTaskUnderTest().execute(execution); + + + if(!isLastPage) { + // Verify the flowable utils are called to get and treat variables + verify(execution, times(1)).getVariable(VARNAME_CURRENT_PARTITION_ID, String.class); + + ArgumentCaptor> variablesMapCaptor = ArgumentCaptor.forClass(Map.class); + + + verify(execution).setVariablesLocal(variablesMapCaptor.capture()); + Map capturedMap = variablesMapCaptor.getValue(); + assertEquals(exepectedPageResponse.getContent(), capturedMap.get(getOutListVariableName())); + } + else{ + //ArgumentCaptor> variablesMapCaptor = ArgumentCaptor.forClass(Map.class); + verify(execution,never()).setVariablesLocal(any()); + } + } + +} diff --git a/src/test/java/fr/insee/protools/backend/service/utils/delegate/IDelegateWithVariables.java b/src/test/java/fr/insee/protools/backend/service/utils/delegate/IDelegateWithVariables.java new file mode 100644 index 00000000..ffbe9680 --- /dev/null +++ b/src/test/java/fr/insee/protools/backend/service/utils/delegate/IDelegateWithVariables.java @@ -0,0 +1,233 @@ +package fr.insee.protools.backend.service.utils.delegate; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.JsonNodeFactory; +import fr.insee.protools.backend.service.exception.VariableClassCastException; +import org.flowable.common.engine.api.FlowableIllegalArgumentException; +import org.flowable.engine.delegate.DelegateExecution; +import org.flowable.engine.delegate.JavaDelegate; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +import java.util.*; +import java.util.function.Consumer; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.lenient; +import static org.mockito.Mockito.mock; + +public interface IDelegateWithVariables { + + org.slf4j.Logger ilogger = org.slf4j.LoggerFactory.getLogger(IDelegateWithVariables.class); + String dumyId = "ID1"; + + //TODO: activer ce test pour que tous les delegates le prennent en compte + //void execute_should_throw_BadContext_when_contextIncorrect(String context_json); + + JavaDelegate getTaskUnderTest(); + Map getVariablesAndTypes(); + + // extra mocked needed to make some tests work + default void initExtraMocks(DelegateExecution execution) { } + + default void initDefaultVariables(DelegateExecution execution) { + Map typeByVariable = getVariablesAndTypes(); + typeByVariable + .keySet() + .forEach(variable -> { + Class clazz = typeByVariable.get(variable); + var dummyValue = getDefaultValue(clazz); + lenient().doReturn(dummyValue).when(execution).getVariable(eq(variable), eq(clazz)); + lenient().doReturn(dummyValue).when(execution).getVariableLocal(eq(variable), eq(clazz)); + }); + } + + @Test + default void execute_should_work_when_params_notNull(){ + //Preconditions + DelegateExecution execution = mock(DelegateExecution.class); + lenient().when(execution.getProcessInstanceId()).thenReturn(dumyId); + lenient().when(execution.getParent()).thenReturn(execution); + + Map typeByVariable = getVariablesAndTypes(); + typeByVariable + .keySet() + .forEach(variable -> { + Class clazz = typeByVariable.get(variable); + var dummyValue = getDefaultValue(clazz); + lenient().doReturn(dummyValue).when(execution).getVariable(eq(variable), eq(clazz)); + lenient().doReturn(dummyValue).when(execution).getVariableLocal(eq(variable), eq(clazz)); + }); + + //Extra mocks (ex: read) + initExtraMocks(execution); + + //Call method under test + assertDoesNotThrow(() -> getTaskUnderTest().execute(execution)); + } + + @Test + default void execute_should_throw_FlowableIllegalArgumentException_when_variables_wrongType() { + Map typeByVariable = getVariablesAndTypes(); + //No variables==> No test + if(typeByVariable.isEmpty()){ + assertTrue(true); + ilogger.info("No variable configured as mandatory for this delegate"); + return; + } + + + //Precondition + DelegateExecution execution = mock(DelegateExecution.class); + lenient().when(execution.getProcessInstanceId()).thenReturn(dumyId); + + typeByVariable + .keySet() + .forEach(variable -> { + Class clazzOriginal = typeByVariable.get(variable); + Class clazz; + if (clazzOriginal.equals(String.class)) { + clazz = List.class; + } else if (clazzOriginal.equals(List.class)) { + clazz = JsonNode.class; + } else { + clazz = String.class; + } + var dummyValue = getDefaultValue(clazz); + lenient().doReturn(dummyValue).when(execution).getVariable(eq(variable), eq(clazzOriginal)); + lenient().doReturn(dummyValue).when(execution).getVariableLocal(eq(variable), eq(clazzOriginal)); + }); + + initExtraMocks(execution); + + //Run the test + //Verify + assertThrows(VariableClassCastException.class, () -> getTaskUnderTest().execute(execution)); + } + + + @Test + default void execute_should_throw_FlowableIllegalArgumentException_when_variables_notDefined(){ + Map typeByVariable = getVariablesAndTypes(); + //No variables==> No test + if(typeByVariable.isEmpty()){ + ilogger.info("No variable configured as mandatory for this delegate"); + assertTrue(true); + return; + } + + //Precondition + DelegateExecution execution = mock(DelegateExecution.class); + + String[] variables=getVariablesAndTypes().keySet().toArray(new String[0]); + combinations(variables) + .forEach(variablesSubset -> { + ilogger.info("subset of initialized variables: "+variablesSubset); + //Initailize the mocked variables + Set intializedVars=new HashSet<>(); + + //Reinit + lenient().when(execution.getProcessInstanceId()).thenReturn(dumyId); + + //The one not defined ==> Throw + for (String variable :variablesSubset) { + Class clazz = typeByVariable.get(variable); + lenient().doThrow(new FlowableIllegalArgumentException("Variable "+variable+" not exists")).when(execution).getVariable(eq(variable), eq(clazz)); + lenient().doThrow(new FlowableIllegalArgumentException("Variable "+variable+" not exists")).when(execution).getVariableLocal(eq(variable), eq(clazz)); + ilogger.info("mock getVariable Throw : variable="+variable+" - class="+clazz); + intializedVars.add(variable); + } + //The others + getVariablesAndTypes().entrySet() + .stream().filter(entry -> !intializedVars.contains(entry.getKey())) + .forEach(entry -> { + String variable=entry.getKey(); + Class clazz = typeByVariable.get(variable); + var dummyValue = getDefaultValue(clazz); + lenient().doReturn(dummyValue).when(execution).getVariable(eq(variable), eq(clazz)); + lenient().doReturn(dummyValue).when(execution).getVariableLocal(eq(variable), eq(clazz)); + ilogger.info("mock getVariable VALUE: variable="+variable+" - class="+clazz); + }); + + //Run the test for this subset of initialized variables + //Verify + FlowableIllegalArgumentException exception = assertThrows(FlowableIllegalArgumentException.class, () -> getTaskUnderTest().execute(execution)); + assertThat(exception.getMessage(), containsString(" not exists")); + // Reset the mock (this clears all stubbings and invocations) + Mockito.reset(execution); + } ); + } + + default DelegateExecution createMockedExecution(){ + DelegateExecution execution = mock(DelegateExecution.class); + lenient().doReturn(dumyId).when(execution).getProcessInstanceId(); + return execution; + } + + //Init an object of clazz type with default value + default T getDefaultValue(Class clazz){ + if(clazz.equals(List.class)){ + return (T) new ArrayList<>(); + } + else if(clazz.equals(Map.class)){ + return (T) new HashMap<>(); + } + else if(clazz.equals(Set.class)){ + return (T) new HashSet<>(); + } + else if(clazz.equals(JsonNode.class)){ + return (T) JsonNodeFactory.instance.objectNode(); + } + else if(clazz.equals(String.class)) { + return (T) "1"; + } + else if(clazz.equals(Long.class)) { + return (T) Long.valueOf(1); + } + else if(clazz.equals(Integer.class)) { + return (T) Integer.valueOf(1); + } + try { + return clazz.getDeclaredConstructor().newInstance(); + } catch (ReflectiveOperationException e) { + throw new RuntimeException(e); + } + } + + //Generate a Stream of all the combinaisons of elements of the array including the full list (but no empty set) + private static Stream> combinations(T[] arr) { + final long N = (long) Math.pow(2, arr.length); + return StreamSupport.stream(new Spliterators.AbstractSpliterator>(N, Spliterator.SIZED) { + long i = 1; + @Override + public boolean tryAdvance(Consumer> action) { + if(i < N) { + List out = new ArrayList<>(Long.bitCount(i) ); + for (int bit = 0; bit < arr.length; bit++) { + if((i & (1< allElements = Arrays.asList(arr); + action.accept(allElements); // Return the full set + return false; + } + } + }, false); + } + + + +} diff --git a/src/test/java/fr/insee/protools/backend/service/utils/delegate/TestDelegateWithContext.java b/src/test/java/fr/insee/protools/backend/service/utils/delegate/TestDelegateWithContext.java new file mode 100644 index 00000000..b31234d2 --- /dev/null +++ b/src/test/java/fr/insee/protools/backend/service/utils/delegate/TestDelegateWithContext.java @@ -0,0 +1,118 @@ +package fr.insee.protools.backend.service.utils.delegate; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import fr.insee.protools.backend.ProtoolsTestUtils; +import fr.insee.protools.backend.dto.ContexteProcessus; +import fr.insee.protools.backend.service.DelegateContextVerifier; +import fr.insee.protools.backend.service.context.IContextService; +import fr.insee.protools.backend.service.context.exception.BadContexMissingBPMNError; +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; +import org.flowable.engine.delegate.DelegateExecution; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Spy; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.Set; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +@Slf4j +public abstract class TestDelegateWithContext implements IDelegateWithVariables{ + + @Spy protected IContextService protoolsContext; + + private ObjectMapper objectMapper=new ObjectMapper(); + + @AfterEach + void mockitoResetContext() { + reset(protoolsContext); + } + + protected abstract String minimalValidCtxt(); + + @Test + @Override + public void execute_should_work_when_params_notNull() { + initContexteMockWithString(minimalValidCtxt()); + IDelegateWithVariables.super.execute_should_work_when_params_notNull(); + } + + @Override + public void initExtraMocks(DelegateExecution execution) { + initContexteMockWithString(minimalValidCtxt()); + IDelegateWithVariables.super.initExtraMocks(execution); + } + + @Override + @Test + public void execute_should_throw_FlowableIllegalArgumentException_when_variables_notDefined(){ + initContexteMockWithString(minimalValidCtxt()); + IDelegateWithVariables.super.execute_should_throw_FlowableIllegalArgumentException_when_variables_notDefined(); + } + + @SneakyThrows + protected JsonNode initContexteMockWithFile(String contexteToLoad) { + JsonNode contextRootNode = ProtoolsTestUtils.asJsonNode(contexteToLoad); + ContexteProcessus schema = objectMapper.readValue(contexteToLoad, ContexteProcessus.class); + + lenient().doReturn(contextRootNode).when(protoolsContext).getContextJsonNodeByProcessInstance(anyString()); + lenient().doReturn(schema).when(protoolsContext).getContextDtoByProcessInstance(anyString()); + return contextRootNode; + } + + @SneakyThrows + protected JsonNode initContexteMockWithString(String contexteAsString){ + JsonNode contextRootNode = new ObjectMapper().readTree(contexteAsString); + ContexteProcessus schema = objectMapper.readValue(contexteAsString, ContexteProcessus.class); + + lenient().doReturn(contextRootNode).when(protoolsContext).getContextJsonNodeByProcessInstance(anyString()); + lenient().doReturn(schema).when(protoolsContext).getContextDtoByProcessInstance(anyString()); + return contextRootNode; + } + + @Test + @DisplayName("execute should throw an error if the context is null") + void execute_should_throwError_when_null_context(){ + //Precondition + DelegateExecution execution = mock(DelegateExecution.class); + lenient().when(execution.getProcessInstanceId()).thenReturn(dumyId); + doThrow(new BadContexMissingBPMNError("Erreur")).when(protoolsContext).getContextDtoByProcessInstance(anyString()); + doThrow(new BadContexMissingBPMNError("Erreur")).when(protoolsContext).getContextJsonNodeByProcessInstance(anyString()); + + assertThrows(BadContexMissingBPMNError.class, () -> getTaskUnderTest().execute(execution)); + } + + @Test + @DisplayName("execute should throw an error if the context is null") + void execute_should_throwError_when_null_context_2() { + if (getTaskUnderTest() instanceof DelegateContextVerifier) { + //Precondition + DelegateExecution execution = mock(DelegateExecution.class); + lenient().when(execution.getProcessInstanceId()).thenReturn(dumyId); + lenient().doReturn(null).when(protoolsContext).getContextDtoByProcessInstance(anyString()); + lenient().doReturn(null).when(protoolsContext).getContextJsonNodeByProcessInstance(anyString()); + + assertThrows(BadContexMissingBPMNError.class, () -> getTaskUnderTest().execute(execution)); + } + } + + @Test + void getContextErrors_should_work_when_valid_contexte() throws JsonProcessingException { + ContexteProcessus schema = objectMapper.readValue(minimalValidCtxt(), ContexteProcessus.class); + + if(getTaskUnderTest() instanceof DelegateContextVerifier){ + Set errors=((DelegateContextVerifier) getTaskUnderTest()).getContextErrors(schema); + assertTrue(errors.isEmpty(),"We should not have any error in a valid contexte"); + } + } +} diff --git a/src/test/java/fr/insee/protools/backend/service/utils/password/PasswordServiceTest.java b/src/test/java/fr/insee/protools/backend/service/utils/password/PasswordServiceImplTest.java similarity index 58% rename from src/test/java/fr/insee/protools/backend/service/utils/password/PasswordServiceTest.java rename to src/test/java/fr/insee/protools/backend/service/utils/password/PasswordServiceImplTest.java index 4caa095c..803dc005 100644 --- a/src/test/java/fr/insee/protools/backend/service/utils/password/PasswordServiceTest.java +++ b/src/test/java/fr/insee/protools/backend/service/utils/password/PasswordServiceImplTest.java @@ -8,21 +8,19 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.TestPropertySource; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; - +import static org.junit.jupiter.api.Assertions.*; @SpringBootTest(classes = PasswordServiceImpl.class) @TestPropertySource(properties = { - "fr.insee.protools.password.create.length = 19", "fr.insee.protools.password.create.withDigits = true", "fr.insee.protools.password.create.withUpperCase = true", "fr.insee.protools.password.create.withLowerCase = true", "fr.insee.protools.password.create.withSpecial = true", }) -class PasswordServiceTest { +class PasswordServiceImplTest { - @Autowired private PasswordService passwordService; + @Autowired + private PasswordService passwordService; @Test void testGeneratePassword() { @@ -32,16 +30,18 @@ void testGeneratePassword() { //Generate and validate X1000 for (int i = 0; i < 1000 ; i++) { - //Execute method under test - String generatePassword=passwordService.generatePassword(); + for(int length=8; length < 19; length ++) { // and for various sizes + //Execute method under test + String generatePassword = passwordService.generatePassword(length); - //Post condition - PasswordData passwordData = new PasswordData(generatePassword); - RuleResult validate = passwordValidator.validate(passwordData); + //Post condition + PasswordData passwordData = new PasswordData(generatePassword); + RuleResult validate = passwordValidator.validate(passwordData); - assertTrue(validate.isValid(),"Generated password meets the rules : "+generatePassword); - assertEquals(19,generatePassword.length(),"Generated password length should meets the confif : "+generatePassword); + assertTrue(validate.isValid(), "Generated password meets the rules : " + generatePassword); + assertEquals(length, generatePassword.length(), "Generated password length should meets the confif : " + generatePassword); + } } } -} +} \ No newline at end of file diff --git a/src/test/java/fr/insee/protools/backend/utils/data/CtxExamples.java b/src/test/java/fr/insee/protools/backend/utils/data/CtxExamples.java new file mode 100644 index 00000000..b607f237 --- /dev/null +++ b/src/test/java/fr/insee/protools/backend/utils/data/CtxExamples.java @@ -0,0 +1,33 @@ +package fr.insee.protools.backend.utils.data; + +public class CtxExamples { + + + public static final String CTX_EMPTY = + """ + { + "id": "a958cfac-2bf3-478d-a97a-dda5e751898c" + } + """; + public static final String CTX_EMPTY_ID ="a958cfac-2bf3-478d-a97a-dda5e751898c"; + + public static final String CTX_CONTEXTE_MENAGE = + """ + { + "id": "b958cfac-2bf3-478d-a97a-dda5e751898c", + "contexte": "menage" + } + """; + public static final String CTX_CONTEXTE_MENAGE_ID ="b958cfac-2bf3-478d-a97a-dda5e751898c"; + + public static final String ctx_contexte_entreprise = + """ + { + "id": "c958cfac-2bf3-478d-a97a-dda5e751898c", + "contexte": "entreprise" + } + """; + public static final String ctx_contexte_entreprise_id="c958cfac-2bf3-478d-a97a-dda5e751898c"; + + private CtxExamples(){} +} diff --git a/src/test/java/fr/insee/protools/backend/utils/data/InterroExamples.java b/src/test/java/fr/insee/protools/backend/utils/data/InterroExamples.java new file mode 100644 index 00000000..afd80878 --- /dev/null +++ b/src/test/java/fr/insee/protools/backend/utils/data/InterroExamples.java @@ -0,0 +1,29 @@ +package fr.insee.protools.backend.utils.data; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.JsonNodeFactory; +import com.fasterxml.jackson.databind.node.ObjectNode; + +import java.util.UUID; + +public class InterroExamples { + + + public record InterroWithId(String id, JsonNode interro){} + + public static InterroWithId generateEmptyInterro(){ + String uuid = UUID.randomUUID().toString(); + ObjectNode interro = JsonNodeFactory.instance.objectNode(); + interro.put("id", uuid); + return new InterroWithId(uuid, interro); + } + public static final String interro1_empty = + """ + { + "id": "b958cfac-2bf3-478d-a97a-dda5e751898c" + } + """; + public static final String interro1_empty_id="b958cfac-2bf3-478d-a97a-dda5e751898c"; + + private InterroExamples(){} +} diff --git a/src/test/java/fr/insee/protools/backend/webclient/WebClientHelperTest.java b/src/test/java/fr/insee/protools/backend/webclient/WebClientHelperTest.java deleted file mode 100644 index 10bcaeb1..00000000 --- a/src/test/java/fr/insee/protools/backend/webclient/WebClientHelperTest.java +++ /dev/null @@ -1,333 +0,0 @@ -package fr.insee.protools.backend.webclient; - -import com.fasterxml.jackson.databind.ObjectMapper; -import fr.insee.protools.backend.ProtoolsTestUtils; -import fr.insee.protools.backend.webclient.configuration.APIProperties; -import fr.insee.protools.backend.webclient.configuration.ApiConfigProperties; -import fr.insee.protools.backend.webclient.exception.ApiNotConfiguredBPMNError; -import fr.insee.protools.backend.webclient.exception.KeycloakTokenConfigUncheckedBPMNError; -import fr.insee.protools.backend.webclient.exception.runtime.WebClient4xxBPMNError; -import okhttp3.mockwebserver.MockResponse; -import okhttp3.mockwebserver.MockWebServer; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mock; -import org.mockito.Spy; -import org.mockito.junit.jupiter.MockitoExtension; -import org.springframework.core.env.Environment; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.web.reactive.function.client.WebClient; -import org.springframework.web.reactive.function.client.WebClientResponseException; - -import java.io.File; -import java.io.IOException; -import java.io.RandomAccessFile; -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.when; - -@ExtendWith(MockitoExtension.class) -class WebClientHelperTest { - - @Spy - private Environment environment; - - private KeycloakService keycloakService; - - @Mock - private ApiConfigProperties apiConfigProperties; - - private WebClientHelper webClientHelper; - - - private MockWebServer mockWebServer; - private static final int port = 80; - private static String getDummyUriWithPort() { return getServerHostPort()+"/api/test"; } - private static String getServerHostPort() { return "http://localhost:"+port; } - - @BeforeEach - public void prepare() { - keycloakService= new KeycloakService(environment); - webClientHelper = new WebClientHelper(keycloakService,apiConfigProperties); - this.keycloakService.initialize(); - } - - //close the mocked web server if it has been initialized - @AfterEach - void mockServerCleanup() throws Exception { - if(this.mockWebServer!=null){ - this.mockWebServer.close(); - } - } - - private void initMockWebServer() throws IOException { - this.mockWebServer = new MockWebServer(); - mockWebServer.start(port); - } - - - private File createDummyFile(int sizeInByte, String extension) throws IOException { - File file = File.createTempFile("tempFile", ".json"); - file.deleteOnExit(); - RandomAccessFile rafile; - rafile = new RandomAccessFile(file, "rw"); - //In Bytes ==> 1024 = 1Ko ==> 1024X1024 : 1Mo - rafile.setLength(sizeInByte); - return file; - } - - private MockResponse fileToResponse(String contentType, File file) throws IOException { - return new MockResponse() - .setResponseCode(HttpStatus.OK.value()) - .setBody(ProtoolsTestUtils.fileToBytes(file)) - .addHeader("content-type: " + contentType); - } - - @Test - @DisplayName("Test getWebClient method without specifying an API") - void testGetWebClientWithoutApi() { - WebClient client = webClientHelper.getWebClient(); - assertThat(client).isNotNull(); - } - - private void testGetWebClientWithIncompleteKCConfig(APIProperties.AuthProperties kcAuth){ - when(apiConfigProperties.getAPIProperties(any())).thenReturn(new APIProperties(getServerHostPort(), kcAuth, true)); - var webClient = webClientHelper.getWebClient(ApiConfigProperties.KNOWN_API.KNOWN_API_ERA); - assertThat(webClient).isNotNull(); - //Should throw an exception as the realm is missing - assertThrows(KeycloakTokenConfigUncheckedBPMNError.class , () -> webClient.get().uri(getDummyUriWithPort()).exchange().block()); - } - @Test - @DisplayName("Test getWebClient method without incomplete keycloak configuration") - void getWebClientWithIncompleteKCConfig() throws IOException { - //Missing realm - APIProperties.AuthProperties kcAuth = new APIProperties.AuthProperties(getDummyUriWithPort(),null, "toto","toto"); - //Should throw an exception as the realm is missing - testGetWebClientWithIncompleteKCConfig(kcAuth); - - //Missing url - kcAuth = new APIProperties.AuthProperties("null","realm", "toto","toto"); - testGetWebClientWithIncompleteKCConfig(kcAuth); - - //Missing clientId - kcAuth = new APIProperties.AuthProperties(getDummyUriWithPort(),"realm", null,"toto"); - testGetWebClientWithIncompleteKCConfig(kcAuth); - - //Missing secret - kcAuth = new APIProperties.AuthProperties(getDummyUriWithPort(),"realm", "toto",null); - testGetWebClientWithIncompleteKCConfig(kcAuth); - } - - @Test - void getWebClient() throws IOException { - - APIProperties.AuthProperties kcAuth = new APIProperties.AuthProperties(); - kcAuth.setClientId("clientId-toto"); - kcAuth.setClientSecret("client-pwd-toto"); - kcAuth.setRealm("realm-toto"); - kcAuth.setUrl(getDummyUriWithPort()); - - - when(apiConfigProperties.getAPIProperties(any())).thenReturn(new APIProperties(getServerHostPort(), kcAuth, true)); - WebClient webClient = webClientHelper.getWebClient(ApiConfigProperties.KNOWN_API.KNOWN_API_ERA); - assertThat(webClient).isNotNull(); - - KeycloakResponse kcResponse = new KeycloakResponse(); - kcResponse.setAccesToken("MYTOKEN"); - kcResponse.setExpiresIn(5*60*1000); - MockResponse mockResponseKC = new MockResponse() - .addHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON) - .setResponseCode(HttpStatus.OK.value()) - .setBody(new ObjectMapper().writeValueAsString(kcResponse)); - - MockResponse mockResponse = new MockResponse() - .setResponseCode(HttpStatus.NO_CONTENT.value()) - .setBody("XXX"); - - initMockWebServer(); - mockWebServer.enqueue(mockResponseKC); - mockWebServer.enqueue(mockResponse); - - assertThat(webClient.get().uri(getDummyUriWithPort()).exchange().block().statusCode()).isEqualTo(HttpStatus.NO_CONTENT); - } - - @Test - @DisplayName("Test getWebClientForFile method - get the webclient and download files of different sizes") - void getWebClientForFile() throws IOException { - WebClient webClient = webClientHelper.getWebClientForFile(); - assertThat(webClient).isNotNull(); - - //Create a 1Mo File - File file1mo = createDummyFile(1024 * 1024 * 1,".json"); - File file19mo = createDummyFile(WebClientHelper.getDefaultFileBufferSize()-1024,".json"); - int tooBigSize=WebClientHelper.getDefaultFileBufferSize()+1024; - File fileTooBig = createDummyFile(tooBigSize,".json"); - - MockResponse fileToResponse_1Mo = fileToResponse(MediaType.APPLICATION_JSON_VALUE, file1mo); - MockResponse fileToResponse_19Mo = fileToResponse(MediaType.APPLICATION_JSON_VALUE, file19mo); - MockResponse fileToResponseTooBig = fileToResponse(MediaType.APPLICATION_JSON_VALUE, fileTooBig); - - -/* - - KeycloakResponse kcResponse = new KeycloakResponse(); - kcResponse.setAccesToken("MYTOKEN"); - kcResponse.setExpiresIn(5*60*1000); - - - MockResponse mockResponseKC = new MockResponse() - .addHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON) - .setResponseCode(HttpStatus.OK.value()) - .setBody(new ObjectMapper().writeValueAsString(kcResponse)); - - final Dispatcher dispatcher = new Dispatcher() { - public MockResponse dispatch(RecordedRequest request) { - switch (request.getPath()) { - case "/users/1": - return new MockResponse().setResponseCode(200); - case "/users/2": - return new MockResponse().setResponseCode(500); - case "/users/3": - return new MockResponse().setResponseCode(200).setBody("{\"id\": 1, \"name\":\"duke\"}"); - } - return new MockResponse().setResponseCode(404); - } - - mockWebServer.enqueue(mockResponseKC); - - };*/ - - initMockWebServer(); - mockWebServer.enqueue(fileToResponse_1Mo); - mockWebServer.enqueue(fileToResponse_19Mo); - mockWebServer.enqueue(fileToResponseTooBig); - mockWebServer.enqueue(fileToResponseTooBig); - - //Check for 1Mo file - assertDoesNotThrow(()->webClientHelper.getWebClientForFile() - .get() - .uri(getDummyUriWithPort()) - .retrieve() - .bodyToMono(String.class) - .block()); - - //Check for 19Mo file - assertDoesNotThrow(()->webClientHelper.getWebClientForFile() - .get() - .uri(getDummyUriWithPort()) - .retrieve() - .bodyToMono(String.class) - .block()); - - //Check for a too big file : Should throw and exception as default buffer is 20Mo - assertThrows(WebClientResponseException.class, () -> webClientHelper.getWebClientForFile() - .get() - .uri(getDummyUriWithPort()) - .retrieve() - .bodyToMono(String.class) - .block()); - - //Check for a too big file with a custom buffer ==> Should be ok - assertDoesNotThrow(() -> webClientHelper.getWebClientForFile(tooBigSize) - .get() - .uri(getDummyUriWithPort()) - .retrieve() - .bodyToMono(String.class) - .block()); - } - - - @Test - void getWebClient_withInvalidApiConfig() { - when(apiConfigProperties.getAPIProperties(any())).thenReturn(null); - assertThatThrownBy(() -> webClientHelper.getWebClient(any())) - .isInstanceOf(ApiNotConfiguredBPMNError.class) - .hasMessageContaining("is not configured in properties"); - } - - @Test - void getWebClient_withDisabledApiConfig() { - when(apiConfigProperties.getAPIProperties(any())).thenReturn(new APIProperties("http://localhost:8080", new APIProperties.AuthProperties(), false )); - assertThatThrownBy(() -> webClientHelper.getWebClient(any())) - .isInstanceOf(ApiNotConfiguredBPMNError.class) - .hasMessageContaining("is disabled in properties"); - } - - @Test - @DisplayName("Test that the retrieval of spring private field still works") - void extractClientResponseRequestDescriptionPrivateFiledUsingReflexion_shouldWork() throws IOException { - WebClient webClient = webClientHelper.getWebClient(); - assertThat(webClient).isNotNull(); - - //Mock an error response - MockResponse mockResponse = new MockResponse() - .setResponseCode(HttpStatus.BAD_REQUEST.value()) - .setBody("XXX"); - - initMockWebServer(); - mockWebServer.enqueue(mockResponse); - - //Call method under test - WebClient4xxBPMNError exception = assertThrows(WebClient4xxBPMNError.class , () ->webClient.get().uri(getDummyUriWithPort()).retrieve() - .bodyToMono(String.class) - .block()); - - //Post call conditions (we get more or less the expected message with the original request) - //IF it is not the case, check that the spring private field has not changed or been renamed - String actualMessage = exception.getMessage(); - assertThat(actualMessage) - .contains("GET") - .contains(getDummyUriWithPort()) - .contains(String.valueOf(HttpStatus.BAD_REQUEST.value())); - } - - @Test - @DisplayName("Test that containsCauseOfType find an existing cause") - void containsCauseOfType_shouldFindCauseIfExists() { - //Prepare - String rootMessage="TEST"; - ArithmeticException exRoot=new ArithmeticException(rootMessage); - Exception exLvl1=new Exception("dummy",exRoot ); - Exception ex = new Exception("dummy",exLvl1 ); - - //Call - boolean found = WebClientHelper.containsCauseOfType(ex, List.of(ArithmeticException.class)); - //Check - assertTrue(found,"ArithmeticException should be found"); - - //Call - found = WebClientHelper.containsCauseOfType(exLvl1, List.of(ArithmeticException.class)); - //Check - assertTrue(found,"ArithmeticException should be found"); - - //Call - found = WebClientHelper.containsCauseOfType(exRoot, List.of(ArithmeticException.class)); - //Check - assertTrue(found,"ArithmeticException should be found"); - - //Call - found = WebClientHelper.containsCauseOfType(exRoot, List.of(RuntimeException.class)); - //Check - assertTrue(found,"RuntimeException should be found"); - - //Call - found = WebClientHelper.containsCauseOfType(exRoot, List.of(IOException.class,RuntimeException.class)); - //Check - assertTrue(found,"RuntimeException should be found"); - - //Call - found = WebClientHelper.containsCauseOfType(exRoot, List.of(IOException.class)); - //Check (should not be found) - assertFalse(found,"IOException should not be found"); - } - -} \ No newline at end of file diff --git a/src/test/resources/application-test.properties b/src/test/resources/application-test.properties index 7d31fe91..12dcca23 100644 --- a/src/test/resources/application-test.properties +++ b/src/test/resources/application-test.properties @@ -21,7 +21,7 @@ springdoc.swagger-ui.oauth.clientId=localhost-frontend fr.insee.sndil.starter.auth.url=${fr.insee.protools.keycloak-interne-auth-url} #URL For nomenclatures service -fr.insee.protools.nomenclature.uri=https://gitlab.insee.fr/enquetes-menages/integration-metallica/-/raw/master/Nomenclatures +fr.insee.protools.nomenclature.uri=https://gitlab.insee.fr/enquetes-menages/integration-metallica/-/raw/master/_Nomenclatures #URL For questionnaire models service fr.insee.protools.questionnaire.model.uri=https://gitlab.insee.fr/enquetes-menages/integration-metallica/-/raw/master/Questionnaire-Models @@ -101,5 +101,5 @@ fr.insee.protools.api.era.auth.url=${fr.insee.protools.keycloak-interne-auth-url #fr.insee.properties.log.key.prefixes=fr.pwd,fr.insee #Log -logging.level.fr.insee.protools=WARN +logging.level.fr.insee.protools=DEBUG logging.level.org.springframework.web.filter.CommonsRequestLoggingFilter=WARN diff --git a/src/test/resources/fr/insee/protools/backend/integration/SimpleProcessTest.testDelegateProcess.bpmn20.xml b/src/test/resources/fr/insee/protools/backend/integration/SimpleProcessTest.testDelegateProcess.bpmn20.xml new file mode 100644 index 00000000..4d2042a7 --- /dev/null +++ b/src/test/resources/fr/insee/protools/backend/integration/SimpleProcessTest.testDelegateProcess.bpmn20.xml @@ -0,0 +1,17 @@ + + + + + This is a process for testing purposes + + + + + + + + + + + + diff --git a/src/test/resources/fr/insee/protools/backend/flowable/engine/SimpleProcessTest.testSimpleProcess.bpmn20.xml b/src/test/resources/fr/insee/protools/backend/integration/SimpleProcessTest.testSimpleProcess.bpmn20.xml similarity index 65% rename from src/test/resources/fr/insee/protools/backend/flowable/engine/SimpleProcessTest.testSimpleProcess.bpmn20.xml rename to src/test/resources/fr/insee/protools/backend/integration/SimpleProcessTest.testSimpleProcess.bpmn20.xml index 47ffae90..e06d83c6 100644 --- a/src/test/resources/fr/insee/protools/backend/flowable/engine/SimpleProcessTest.testSimpleProcess.bpmn20.xml +++ b/src/test/resources/fr/insee/protools/backend/integration/SimpleProcessTest.testSimpleProcess.bpmn20.xml @@ -7,9 +7,9 @@ This is a process for testing purposes - - - + + + diff --git a/src/test/resources/fr/insee/protools/backend/integration/collecte_web_no_com.json b/src/test/resources/fr/insee/protools/backend/integration/collecte_web_no_com.json deleted file mode 100644 index 1693e245..00000000 --- a/src/test/resources/fr/insee/protools/backend/integration/collecte_web_no_com.json +++ /dev/null @@ -1,160 +0,0 @@ -{ - "id": "AAB2023A00", - "label": "Test FAMILLE 2023 - MARC", - "contexte": "household", - "metadonnees": { - "annee": 2023, - "periodicite": "A", - "periode": "A00", - "operationId": "AAB2023", - "operationLabelCourt": "MARC - Opération test FAMILLE 2023", - "operationLabelLong": "MARC - Super opération test FAMILLE 2023", - "serieId": "AAB", - "serieLabelCourt": "MARC - Enquête test FAMILLE", - "serieLabelLong": "MARC - Super enquête test FAMILLE", - "portailMesEnquetesOperation": false, - "objectifsCourts": "Cette enquête permet de tester...", - "objectifsLongs": "Cette enquête permet de tester des choses...", - "caractereObligatoire": true, - "qualiteStatistique": true, - "testNonLabellise": true, - "anneeVisa": 2023, - "numeroVisa": "2023xxxxxx", - "ministereTutelle": "de l'Économie, des Finances et de la Souveraineté Industrielle et Numérique", - "parutionJo": true, - "dateParutionJo": "2021-12-23", - "responsableOperationnel": "L’Institut national de la statistique et des études économiques (Insee)", - "responsableTraitement": "l'Insee", - "cnisUrl": "http://cnis/DOG2021", - "diffusionUrl": "http://diffusion/DOG2021", - "noticeUrl": "http://notice/DOG2021", - "specimenUrl": "http://specimenUrl/DOG2021", - "proprietaireId": "proprietaireTest", - "proprietaireLabel": "faux proprietaire de test", - "proprietaireLogo": "1", - "assistanceNiveau2Id": "assistance2Test", - "assistanceNiveau2Label": "fausse assistance niveau 2 de test", - "assistanceNiveau2Tel": "0000000000", - "assitanceNiveau2Mail": "mail", - "asssistanceNiveau2Pays": "France", - "assistanceNiveau2NumeroVoie": "1", - "assistanceNiveau2NomVoie": "rue de la Libération", - "assistanceNiveau2Commune": "Besançon", - "assistanceNiveau2CodePostal": "25000", - "mailBoiteRetour": "audrey.dorolle@insee.fr", - "urlEnquete": "https://enquetes.stat-publique.fr/fam", - "themeMieuxConnaitreMail": "les familles", - "serviceCollecteurSignataireFonction": "La directrice des statistiques démographiques et sociales de l’Insee", - "serviceCollecteurSignataireNom": "Christel Colin", - "prestataire": false, - "mailResponsableOperationnel": "contact-rgpd@insee.fr", - "logoPrestataire": "", - "urlLoiStatistique": "urlLoiStatistique_val", - "urlLoiRGPD": "urlLoiRGPD_val", - "urlLoiInformatique": "urlLoiInformatique_val" - }, - "partitions": [{ - "id": 43, - "typeEchantillon" : "logement", - "label": "premier lot FAMILLE 2023", - "dateDebutCollecte": "2023-04-16T14:07:23.001Z", - "dateFinCollecte": "2024-05-16T14:07:23.001Z", - "dateRetour": "2025-05-15T14:07:23.001Z", - "questionnaireModel": "quest_model_famille", - "quiRepond1": "Qui doit répondre paragraphe 1", - "quiRepond2": "Qui doit répondre paragraphe 2", - "quiRepond3": "Qui doit répondre paragraphe 3", - "sexe": "femmes", - "communications" :[ - { - "moyenCommunication" : "mail", - "phaseCommunication" : "ouverture", - "avecQuestionnairePapier" : false, - "protocole" : null, - "mode" : "web", - "typeModele" : "relance_libre", - "objetMail" : "Insee - enquêtes Familles 2024", - "relanceLibreMailParagraphe1" : "Vous avez récemment répondu à l’enquête de recensement de la population de l’Institut national de la statistique et des études économiques (Insee) et je vous en remercie.", - "relanceLibreMailParagraphe2" : "Votre foyer est retenu pour répondre à des questions supplémentaires sur le thème de la famille. Votre participation est essentielle pour connaître les situations et modes de vie des familles aujourd’hui.", - "relanceLibreMailParagraphe3" : "Dans votre foyer, chaque femme âgée de 18 ans ou plus est sollicitée pour répondre à un questionnaire court en ligne.", - "relanceLibreMailParagraphe4" : "Répondre prendra 15 minutes environ. Vous pouvez dès maintenant vous connecter.", - "complementConnexion" : "Il s’agit du mot de passe que vous avez utilisé pour répondre à l’enquête de recensement de la population.", - "echeances" : ["J+0"] - }, - { - "moyenCommunication" : "mail", - "phaseCommunication" : "relance", - "avecQuestionnairePapier" : false, - "protocole" : null, - "mode" : "web", - "typeModele" : "relance_libre", - "objetMail" : "Rappel Insee - enquêtes Familles 2024", - "relanceLibreMailParagraphe1" : "Vous avez été sollicité pour répondre à l'enquête Familles de l'institut national de la statistique et des études économiques (Insee).", - "relanceLibreMailParagraphe2" : "A ce jour nous n'avons pas reçu de réponse de votre part. Votre participation est essentielle pour connaître les situations et modes de vie des familles aujourd’hui.", - "relanceLibreMailParagraphe3" : "Dans votre foyer, chaque femme âgée de 18 ans ou plus est sollicitée pour répondre à un questionnaire court en ligne.", - "relanceLibreMailParagraphe4" : "Répondre prendra 15 minutes environ. Vous pouvez dès maintenant vous connecter.", - "complementConnexion" : "Il s’agit du mot de passe que vous avez utilisé pour répondre à l’enquête de recensement de la population.", - "echeances" : ["J+3","J+7","J+20"] - } - ] - }, - { - "id": 42, - "typeEchantillon" : "logement", - "label": "2nd lot lot FAMILLE 2023", - "dateDebutCollecte": "2023-04-16T14:07:23.001Z", - "dateFinCollecte": "2024-05-16T14:07:23.001Z", - "dateRetour": "2025-05-15T14:07:23.001Z", - "questionnaireModel": "quest_model_famille", - "quiRepond1": "Qui doit répondre paragraphe 1", - "quiRepond2": "Qui doit répondre paragraphe 2", - "quiRepond3": "Qui doit répondre paragraphe 3", - "sexe": "hommes", - "communications": [ - { - "moyenCommunication" : "mail", - "phaseCommunication" : "ouverture", - "avecQuestionnairePapier" : false, - "protocole" : null, - "mode" : "web", - "typeModele" : "relance_libre", - "objetMail" : "Insee - enquêtes Familles 2024", - "relanceLibreMailParagraphe1" : "Vous avez récemment répondu à l’enquête de recensement de la population de l’Institut national de la statistique et des études économiques (Insee) et je vous en remercie.", - "relanceLibreMailParagraphe2" : "Votre foyer est retenu pour répondre à des questions supplémentaires sur le thème de la famille. Votre participation est essentielle pour connaître les situations et modes de vie des familles aujourd’hui.", - "relanceLibreMailParagraphe3" : "Dans votre foyer, chaque homme âgé de 18 ans ou plus est sollicité pour répondre à un questionnaire court en ligne.", - "relanceLibreMailParagraphe4" : "Répondre prendra 15 minutes environ. Vous pouvez dès maintenant vous connecter.", - "complementConnexion" : "Il s’agit du mot de passe que vous avez utilisé pour répondre à l’enquête de recensement de la population.", - "echeances" : ["J+0"] - }, - { - "moyenCommunication" : "mail", - "phaseCommunication" : "relance", - "avecQuestionnairePapier" : false, - "protocole" : null, - "mode" : "web", - "typeModele" : "relance_libre", - "objetMail" : "Rappel Insee - enquêtes Familles 2024", - "relanceLibreMailParagraphe1" : "Vous avez été sollicité pour répondre à l'enquête Familles de l'institut national de la statistique et des études économiques (Insee).", - "relanceLibreMailParagraphe2" : "A ce jour nous n'avons pas reçu de réponse de votre part. Votre participation est essentielle pour connaître les situations et modes de vie des familles aujourd’hui.", - "relanceLibreMailParagraphe3" : "Dans votre foyer, chaque homme âgé de 18 ans ou plus est sollicité pour répondre à un questionnaire court en ligne.", - "relanceLibreMailParagraphe4" : "Répondre prendra 15 minutes environ. Vous pouvez dès maintenant vous connecter.", - "complementConnexion" : "Il s’agit du mot de passe que vous avez utilisé pour répondre à l’enquête de recensement de la population.", - "echeances" : ["J+3","J+7","J+20"] - } - ] - } - ], - "questionnaireModels": [{ - "id": "quest_model_famille", - "cheminRepertoire": "tests/coleman", - "label": "questionnaireModel de famille", - "requiredNomenclatureIds": [] - }, - { - "id": "quest_model_famille", - "cheminRepertoire": "tests/coleman", - "label": "questionnaireModel de famille", - "requiredNomenclatureIds": [] - }], - "nomenclatures": [] -} \ No newline at end of file diff --git a/src/test/resources/fr/insee/protools/backend/integration/noCTX_eraREM.bpmn20.xml b/src/test/resources/fr/insee/protools/backend/integration/noCTX_eraREM.bpmn20.xml deleted file mode 100644 index 38f9bc35..00000000 --- a/src/test/resources/fr/insee/protools/backend/integration/noCTX_eraREM.bpmn20.xml +++ /dev/null @@ -1,232 +0,0 @@ - - - - - - Crée le contexte d'une campagne web dans la plateforme Platine à partir des métadonnées de processus. - - Concerne les données questionnaire (nomenclatures, modèles de questionnaire) - - - Crée le contexte d'une campagne web dans la plateforme Platine à partir des métadonnées de processus. - - Concerne les données pilotage (partitions, dates de collecte...) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2023-09-11T17:00:20+0200 - - - - - - - 00 32 * * * ? - - - - - 2023-09-15T22:00:20+0200 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/test/resources/fr/insee/protools/backend/integration/springGetREMDelegate-context.xml b/src/test/resources/fr/insee/protools/backend/integration/springGetREMDelegate-context.xml new file mode 100644 index 00000000..4f1d7fb5 --- /dev/null +++ b/src/test/resources/fr/insee/protools/backend/integration/springGetREMDelegate-context.xml @@ -0,0 +1,14 @@ + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/fr/insee/protools/backend/integration/springTestDelegate-context.xml b/src/test/resources/fr/insee/protools/backend/integration/springTestDelegate-context.xml new file mode 100644 index 00000000..ae2a77fe --- /dev/null +++ b/src/test/resources/fr/insee/protools/backend/integration/springTestDelegate-context.xml @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file diff --git a/src/test/resources/fr/insee/protools/backend/integration/springTypicalUsageTest-context.xml b/src/test/resources/fr/insee/protools/backend/integration/springTypicalUsageTest-context.xml new file mode 100644 index 00000000..16ff97eb --- /dev/null +++ b/src/test/resources/fr/insee/protools/backend/integration/springTypicalUsageTest-context.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/fr/insee/protools/backend/service/context/minimal_valid_context.json b/src/test/resources/fr/insee/protools/backend/service/context/minimal_valid_context.json new file mode 100644 index 00000000..054b4155 --- /dev/null +++ b/src/test/resources/fr/insee/protools/backend/service/context/minimal_valid_context.json @@ -0,0 +1,132 @@ +{ + "id": "006aa47d-1574-424b-a67f-40705bec81f6", + "labelCourt": "PRO2024X03", + "contexte": "menage", + "metadonnees": { + "serieId": "PRO", + "serieLabelCourt": "PRO", + "serieLabelLong": "Enquête Protools", + "periodicite": "X", + "periode": "X03", + "annee": 2024, + "operationId": "s1558", + "operationLabelCourt": "PRO2024", + "operationLabelLong": "Enquête Protools 2024", + "objectifsCourts": "Cette enquête permet de tester le prototype Protools asynchrone.", + "objectifsLongs": "Cette enquête permet de tester le prototype Protools asynchrone : intégration d'une enquête web avec envoi de courriers et remise en collecte.", + "cnisUrl": "http://cnis/DOG2021", + "diffusionUrl": "http://diffusion/DOG2021", + "noticeUrl": "http://notice/DOG2021", + "specimenUrl": "http://specimenUrl/DOG2021", + "numeroVisa": "2024X005EC", + "anneeVisa": "2024", + "caractereObligatoire": true, + "interetGeneral": true, + "qualiteStatistique": false, + "testNonLabellise": false, + "parutionJo": true, + "dateParutionJo": "2023-11-07", + "portailMesEnquetesOperation": false, + "proprietaireId": "Insee", + "proprietaireLabel": "Institut national de la statistique et des études économiques", + "imageLogos": "Insee", + "ministereTutelle": "de l'Économie, des Finances et de la Souveraineté Industrielle et Numérique", + "commanditaire": "l’Institut national de la statistique et des études économiques (Insee)", + "responsableOperationnel": "l’Institut national de la statistique et des études économiques (Insee)", + "mailResponsableOperationnel": "contact-rgpd@insee.fr", + "responsableTraitement": "l’Institut national de la statistique et des études économiques (Insee)", + "responsableTraitementIdenti": "L'Insee", + "responsableTraitementIdentiFem": false, + "urlResponsableTraitement": "www.insee.fr", + "prestataire": false, + "nomPrestataire": "", + "urlPrestataire": "", + "logoPartenaire": "", + "serviceCollecteurSignataireFonction": "La directrice des statistiques démographiques et sociales de l’Insee", + "serviceCollecteurSignataireNom": "Christel Colin", + "imageLogoSignataire": "Insee", + "assistanceTel": "09 71 10 02 81", + "assistanceMail": "https://enquetes.stat-publique.fr/fam
Rubrique « Contacter l’assistance »", + "assistanceAdresseL1": "Insee", + "assistanceAdresseL2": "Enquête Particuliers", + "assistanceAdresseL3": "CS 54 229", + "assistanceAdresseL4": "54042 Nancy Cedex", + "assistanceAdresseL5": "", + "adresseRetourQL1": "", + "adresseRetourQL2": "", + "adresseRetourQL3": "", + "adresseRetourQL4": "", + "adresseRetourQL5": "", + "adresseRetourQL6": "", + "adresseRetourQL7": "", + "representantLegal": false, + "mineur": false, + "mineurDroit": "", + "dpd": true, + "mailDPD": "le-delegue-a-la-protection-des-donnees-personnelles@finances.gouv.fr", + "appariement": true, + "sourceAdmin": "avec les données sur le revenu", + "archivage": true, + "dureeConservation": "20 ans", + "dureeConservationIdenti": "jusqu'à un an après la dernière utilisation", + "urlEnquete": "https://enquetes.stat-publique.fr/fam", + "incitationARepondre": "", + "mailBoiteRetour": "dr67-etb54-mission-metallica-multimode@insee.fr", + "themeMieuxConnaitreMail": "les familles", + "ville": "Montrouge", + "complementOpportunite": "", + "paragrapheDonneesPersonnelles": true, + "messageOffline": "L'enquête est terminée", + "messageInfoOffline": "", + "configurationVerificationMail": true, + "imageResultat": "", + "paragrapheResultat": "", + "urlInformationEnquete": "https://www.insee.fr/fr/information/6659341", + "dureeConservationDonneesConnexion": "au bout de cinq ans après la validation du fichier de collecte clôturant les trois questionnaires de l’enquête", + "urlAQuoiServentVosReponses": "https://www.insee.fr/fr/information/7651977", + "texteUrlAQuoiServentVosReponses": "Sans vos réponses à nos enquêtes, ces données n'existeraient pas", + "paragrapheAQuoiServentVosReponses": "La plupart des enquêtes auprès des particuliers du service statistique public débute par un ensemble de questions visant à décrire succinctement le foyer (âges, sexes, professions des occupants du logement notamment). Ces questions communes ont été retravaillées pour mieux correspondre aux modes de vie d’aujourd’hui et pour alléger cette partie des enquêtes.\n\n Pour finaliser cette rénovation et préparer au mieux les futures enquêtes qui utiliseront ces questions, l’Insee réalise une enquête sur le cadre de vie en 2023. Cette enquête servira aussi à comparer les réponses fournies selon le mode de collecte proposé aux enquêtés ; en effet, chacun sera sollicité pour répondre soit par internet sur smartphone, soit par internet sur ordinateur, soit par téléphone, soit lors de la visite d’un enquêteur à son domicile.", + "frequenceExtraction": "0 15 16 1/1 * *", + "cheminLivraisonDonnees": "", + "chiffrement": "", + "livraisonDifferentielle": false, + "formatLivraisonDonnees": "", + "mailBoiteFonctionnelle": "dr67-etb54-mission-metallica-multimode@insee.fr", + "referents": [ + { + "nom": "Dupont", + "prenom": "Jean", + "telephone": "0101010102", + "principal": true + }, + { + "nom": "Dupond", + "prenom": "Marie", + "telephone": "0101010103", + "principal": false + } + ], + "champGeographiqueEnquete": "France entière", + "champStatistiqueEnquete": "Tous les majeurs du ménage", + "urlLoiStatistique": "https://www.legifrance.gouv.fr/loda/id/JORFTEXT000000888573", + "urlLoiRGPD": "https://eur-lex.europa.eu/legal-content/FR/TXT/?uri=CELEX%3A32016R0679", + "urlLoiInformatique": "https://www.legifrance.gouv.fr/affichTexte.do?cidTexte=JORFTEXT000000886460" + }, + "lots": [ + { + "id": "1be5512c-1765-4c4d-adbd-48bbca1a3ce4", + "typeEchantillon": "logement", + "modesCollecte": [ + "CAWI" + ] + }, + { + "id": "9dd5a6b7-f9de-48e3-ac19-fc157d8d4c57", + "label": "Lot web - interro 2", + "typeEchantillon": "logement", + "modesCollecte": [ + "CAWI" + ] + } + ] +} diff --git a/src/test/resources/fr/insee/protools/backend/service/context/protools-contexte-platine.json b/src/test/resources/fr/insee/protools/backend/service/context/protools-contexte-platine.json deleted file mode 100644 index 2dcb750c..00000000 --- a/src/test/resources/fr/insee/protools/backend/service/context/protools-contexte-platine.json +++ /dev/null @@ -1,79 +0,0 @@ -{ - "id": "DEM2022X00", - "label": "Enquête démo 2022 - séquence 1", - "contexte": "household", - "metadonnees": { - "annee": 2022, - "periodicite": "X", - "periode": "X00", - "operationId": "DEM2022", - "operationLabelCourt": "operationLabelCourt", - "operationLabelLong": "operationLabelLong", - "serieId": "DEM", - "serieLabelCourt": "serieLabelCourt", - "serieLabelLong": "serieLabelLong", - "portailMesEnquetesOperation": true, - "objectifsCourts": "objectifsCourts", - "objectifsLongs": "objectifsLongs", - "caractereObligatoire": true, - "qualiteStatistique": true, - "testNonLabellise": true, - "anneeVisa": 2022, - "numeroVisa": "2022xxxxxx", - "ministereTutelle": "de l'Économie, des Finances et de la Souveraineté Industrielle et Numérique", - "parutionJo": true, - "dateParutionJo": "2021-12-23", - "responsableOperationnel": "L’Institut national de la statistique et des études économiques (Insee)", - "responsableTraitement": "l'Insee", - "cnisUrl": "http://cnis/DOG2021", - "diffusionUrl": "http://diffusion/DOG2021", - "noticeUrl": "http://notice/DOG2021", - "specimenUrl": "http://specimenUrl/DOG2021", - "proprietaireId": "proprietaireId", - "proprietaireLabel": "proprietaireLabel", - "proprietaireLogo": "proprietaireLogo", - "assistanceNiveau2Id": "assistanceNiveau2Id", - "assistanceNiveau2Label": "assistanceNiveau2Label", - "assistanceNiveau2Tel": "assistanceNiveau2Tel", - "assitanceNiveau2Mail": "assitanceNiveau2Mail", - "asssistanceNiveau2Pays": "asssistanceNiveau2Pays", - "assistanceNiveau2NumeroVoie": "assistanceNiveau2NumeroVoie", - "assistanceNiveau2NomVoie": "rue Kennedy", - "assistanceNiveau2Commune": "assistanceNiveau2Commune", - "assistanceNiveau2CodePostal": "assistanceNiveau2CodePostal" - }, - "partitions": [{ - "id": 1, - "label": "lot hommes", - "dateDebutCollecte": "2023-01-16T14:07:23.001Z", - "dateFinCollecte": "2024-01-16T14:07:23.001Z", - "dateRetour": "2024-01-16T14:07:23.001Z" - }], - "questionnaireModels": [{ - "id": "tic2023a00_web", - "cheminRepertoire": "coleman", - "label": "Super modèle 1", - "requiredNomenclatureIds": [ - "L_DEPNAIS-1-1-0", - "L_PAYSNAIS-1-1-0", - "L_NATIONETR-1-1-0" - ] - }], - "nomenclatures": [ - { - "id": "L_DEPNAIS-1-1-0", - "cheminRepertoire": "DEPNAIS", - "label": "Liste des départements" - }, - { - "id": "L_PAYSNAIS-1-1-0", - "cheminRepertoire": "PAYSNAIS", - "label": "liste des pays" - }, - { - "id": "L_NATIONETR-1-1-0", - "cheminRepertoire": "NATIONETR", - "label": "liste des nationalités" - } - ] -} \ No newline at end of file diff --git a/src/test/resources/fr/insee/protools/backend/service/platine/delegate/expected_post_questionnaire_metadata.json b/src/test/resources/fr/insee/protools/backend/service/platine/delegate/expected_post_questionnaire_metadata.json deleted file mode 100644 index cf57eb9c..00000000 --- a/src/test/resources/fr/insee/protools/backend/service/platine/delegate/expected_post_questionnaire_metadata.json +++ /dev/null @@ -1,67 +0,0 @@ -{ - "value": { - "variables": [ - { - "name": "Enq_LibelleEnquete", - "value": "operationLabelLong" - }, - { - "name": "Enq_ObjectifsCourts", - "value": "objectifsCourts" - }, - { - "name": "Enq_CaractereObligatoire", - "value": true - }, - { - "name": "Enq_NumeroVisa", - "value": "2022xxxxxx" - }, - { - "name": "Enq_MinistereTutelle", - "value": "de l'Économie, des Finances et de la Souveraineté Industrielle et Numérique" - }, - { - "name": "Enq_ParutionJo", - "value": true - }, - { - "name": "Enq_DateParutionJo", - "value": "2021-12-23" - }, - { - "name": "Enq_RespOperationnel", - "value": "L’Institut national de la statistique et des études économiques (Insee)" - }, - { - "name": "Enq_RespTraitement", - "value": "l'Insee" - }, - { - "name": "Enq_AnneeVisa", - "value": 2022 - }, - { - "name": "Enq_QualiteStatistique", - "value": true - }, - { - "name": "Enq_TestNonLabellise", - "value": true - }, - { - "name": "Loi_statistique", - "value": "urlLoiStatistique_val" - }, - { - "name": "Loi_rgpd", - "value": "urlLoiRGPD_val" - }, - { - "name": "Loi_informatique", - "value": "urlLoiInformatique_val" - } - ], - "inseeContext": "household" - } -} \ No newline at end of file diff --git a/src/test/resources/fr/insee/protools/backend/service/platine/delegate/protools-contexte-platine-incorrect-no-campaign-id.json b/src/test/resources/fr/insee/protools/backend/service/platine/delegate/protools-contexte-platine-incorrect-no-campaign-id.json deleted file mode 100644 index 350a307c..00000000 --- a/src/test/resources/fr/insee/protools/backend/service/platine/delegate/protools-contexte-platine-incorrect-no-campaign-id.json +++ /dev/null @@ -1,75 +0,0 @@ -{ - "label": "Enquête démo 2022 - séquence 1", - "contexte": "household", - "metadonnees": { - "annee": 2022, - "periodicite": "X", - "periode": "X00", - "operationId": "DEM2022", - "operationLabelCourt": "operationLabelCourt", - "operationLabelLong": "operationLabelLong", - "serieId": "DEM", - "serieLabelCourt": "serieLabelCourt", - "serieLabelLong": "serieLabelLong", - "objectifsCourts": "Cette enquête permet de connaître précisément ...", - "objectifsLongs": "Cette enquête permet de connaître précisément...", - "caractereObligatoire": true, - "testNonLabellise": true, - "anneeVisa": 2022, - "numeroVisa": "2022xxxxxx", - "ministereTutelle": "de l'Économie, des Finances et de la Souveraineté Industrielle et Numérique", - "parutionJo": true, - "dateParutionJo": "2021-12-23", - "responsableOperationnel": "L’Institut national de la statistique et des études économiques (Insee)", - "responsableTraitement": "l'Insee", - "cnisUrl": "http://cnis/DOG2021", - "diffusionUrl": "http://diffusion/DOG2021", - "noticeUrl": "http://notice/DOG2021", - "specimenUrl": "http://specimenUrl/DOG2021", - "proprietaireId": "proprietaireId", - "proprietaireLabel": "proprietaireLabel", - "proprietaireLogo": "proprietaireLogo", - "assistanceNiveau2Id": "assistanceNiveau2Id", - "assistanceNiveau2Label": "assistanceNiveau2Label", - "assistanceNiveau2Tel": "assistanceNiveau2Tel", - "assitanceNiveau2Mail": "assitanceNiveau2Mail", - "asssistanceNiveau2Pays": "asssistanceNiveau2Pays", - "assistanceNiveau2NumeroVoie": "assistanceNiveau2NumeroVoie", - "assistanceNiveau2NomVoie": "rue Kennedy", - "assistanceNiveau2Commune": "assistanceNiveau2Commune", - "assistanceNiveau2CodePostal": "assistanceNiveau2CodePostal" - }, - "partitions": [{ - "id": 1, - "label": "lot hommes", - "dateDebutCollecte": "2023-01-16T14:07:23.001Z", - "dateFinCollecte": "2024-01-16T14:07:23.001Z", - "dateRetour": "2024-01-16T14:07:23.001Z" - }], - "questionnaireModels": [{ - "id": "tic2023a00_web", - "cheminRepertoire": "coleman", - "label": "Super modèle 1", - "requiredNomenclatureIds": [ - "L_DEPNAIS-1-1-0", - "L_PAYSNAIS-1-1-0", - "L_NATIONETR-1-1-0" - ] - }], - "nomenclatures": [ - { - "id": "L_DEPNAIS-1-1-0", - "cheminRepertoire": " DEPNAIS", - "label": "Liste des départements" - }, - { - "id": "L_PAYSNAIS-1-1-0", - "cheminRepertoire": "PAYSNAIS", - "label": "liste des pays" - }, - { - "id": "L_NATIONETR-1-1-0", - "label": "liste des nationalités" - } - ] -} \ No newline at end of file diff --git a/src/test/resources/fr/insee/protools/backend/service/platine/delegate/protools-contexte-platine-incorrect.json b/src/test/resources/fr/insee/protools/backend/service/platine/delegate/protools-contexte-platine-incorrect.json deleted file mode 100644 index 07b86e75..00000000 --- a/src/test/resources/fr/insee/protools/backend/service/platine/delegate/protools-contexte-platine-incorrect.json +++ /dev/null @@ -1,76 +0,0 @@ -{ - "id": "DEM2022X00", - "label": "Enquête démo 2022 - séquence 1", - "contexte": "household", - "metadonnees": { - "annee": 2022, - "periodicite": "X", - "periode": "X00", - "operationId": "DEM2022", - "operationLabelCourt": "operationLabelCourt", - "operationLabelLong": "operationLabelLong", - "serieId": "DEM", - "serieLabelCourt": "serieLabelCourt", - "serieLabelLong": "serieLabelLong", - "objectifsCourts": "Cette enquête permet de connaître précisément ...", - "objectifsLongs": "Cette enquête permet de connaître précisément...", - "caractereObligatoire": true, - "testNonLabellise": true, - "anneeVisa": 2022, - "numeroVisa": "2022xxxxxx", - "ministereTutelle": "de l'Économie, des Finances et de la Souveraineté Industrielle et Numérique", - "parutionJo": true, - "dateParutionJo": "2021-12-23", - "responsableOperationnel": "L’Institut national de la statistique et des études économiques (Insee)", - "responsableTraitement": "l'Insee", - "cnisUrl": "http://cnis/DOG2021", - "diffusionUrl": "http://diffusion/DOG2021", - "noticeUrl": "http://notice/DOG2021", - "specimenUrl": "http://specimenUrl/DOG2021", - "proprietaireId": "proprietaireId", - "proprietaireLabel": "proprietaireLabel", - "proprietaireLogo": "proprietaireLogo", - "assistanceNiveau2Id": "assistanceNiveau2Id", - "assistanceNiveau2Label": "assistanceNiveau2Label", - "assistanceNiveau2Tel": "assistanceNiveau2Tel", - "assitanceNiveau2Mail": "assitanceNiveau2Mail", - "asssistanceNiveau2Pays": "asssistanceNiveau2Pays", - "assistanceNiveau2NumeroVoie": "assistanceNiveau2NumeroVoie", - "assistanceNiveau2NomVoie": "rue Kennedy", - "assistanceNiveau2Commune": "assistanceNiveau2Commune", - "assistanceNiveau2CodePostal": "assistanceNiveau2CodePostal" - }, - "partitions": [{ - "id": 1, - "label": "lot hommes", - "dateDebutCollecte": "2023-01-16T14:07:23.001Z", - "dateFinCollecte": "2024-01-16T14:07:23.001Z", - "dateRetour": "2024-01-16T14:07:23.001Z" - }], - "questionnaireModels": [{ - "id": "tic2023a00_web", - "cheminRepertoire": "coleman", - "label": "Super modèle 1", - "requiredNomenclatureIds": [ - "L_DEPNAIS-1-1-0", - "L_PAYSNAIS-1-1-0", - "L_NATIONETR-1-1-0" - ] - }], - "nomenclatures": [ - { - "id": "L_DEPNAIS-1-1-0", - "cheminRepertoire": " DEPNAIS", - "label": "Liste des départements" - }, - { - "id": "L_PAYSNAIS-1-1-0", - "cheminRepertoire": "PAYSNAIS", - "label": "liste des pays" - }, - { - "id": "L_NATIONETR-1-1-0", - "label": "liste des nationalités" - } - ] -} \ No newline at end of file diff --git a/src/test/resources/fr/insee/protools/backend/service/platine/delegate/protools-contexte-platine-individu.json b/src/test/resources/fr/insee/protools/backend/service/platine/delegate/protools-contexte-platine-individu.json deleted file mode 100644 index 4e245ed3..00000000 --- a/src/test/resources/fr/insee/protools/backend/service/platine/delegate/protools-contexte-platine-individu.json +++ /dev/null @@ -1,88 +0,0 @@ -{ - "id": "DEM2022X00", - "label": "Enquête démo 2022 - séquence 1", - "contexte": "household", - "metadonnees": { - "annee": 2022, - "periodicite": "X", - "periode": "X00", - "operationId": "DEM2022", - "operationLabelCourt": "operationLabelCourt", - "operationLabelLong": "operationLabelLong", - "serieId": "DEM", - "serieLabelCourt": "serieLabelCourt", - "serieLabelLong": "serieLabelLong", - "portailMesEnquetesOperation": true, - "objectifsCourts": "objectifsCourts", - "objectifsLongs": "objectifsLongs", - "caractereObligatoire": true, - "qualiteStatistique": true, - "testNonLabellise": true, - "anneeVisa": 2022, - "numeroVisa": "2022xxxxxx", - "ministereTutelle": "de l'Économie, des Finances et de la Souveraineté Industrielle et Numérique", - "parutionJo": true, - "dateParutionJo": "2021-12-23", - "responsableOperationnel": "L’Institut national de la statistique et des études économiques (Insee)", - "responsableTraitement": "l'Insee", - "cnisUrl": "http://cnis/DOG2021", - "diffusionUrl": "http://diffusion/DOG2021", - "noticeUrl": "http://notice/DOG2021", - "specimenUrl": "http://specimenUrl/DOG2021", - "proprietaireId": "proprietaireId", - "proprietaireLabel": "proprietaireLabel", - "proprietaireLogo": "proprietaireLogo", - "assistanceNiveau2Id": "assistanceNiveau2Id", - "assistanceNiveau2Label": "assistanceNiveau2Label", - "assistanceNiveau2Tel": "assistanceNiveau2Tel", - "assitanceNiveau2Mail": "assitanceNiveau2Mail", - "asssistanceNiveau2Pays": "asssistanceNiveau2Pays", - "assistanceNiveau2NumeroVoie": "assistanceNiveau2NumeroVoie", - "assistanceNiveau2NomVoie": "rue Kennedy", - "assistanceNiveau2Commune": "assistanceNiveau2Commune", - "assistanceNiveau2CodePostal": "assistanceNiveau2CodePostal", - "urlLoiStatistique": "urlLoiStatistique_val", - "urlLoiRGPD": "urlLoiRGPD_val", - "urlLoiInformatique": "urlLoiInformatique_val" - - }, - "partitions": [{ - "id": 1, - "label": "lot hommes", - "typeEchantillon" : "INDIVIDU", - "dateDebutCollecte": "2023-01-16T14:07:23.001Z", - "dateFinCollecte": "2024-01-16T14:07:23.001Z", - "dateRetour": "2024-01-16T14:07:23.001Z", - "questionnaireModel": "tic2023a00_web", - "quiRepond1": "Qui doit répondre paragraphe 1", - "quiRepond2": "Qui doit répondre paragraphe 2", - "quiRepond3": "Qui doit répondre paragraphe 3" - }], - "questionnaireModels": [{ - "id": "tic2023a00_web", - "cheminRepertoire": "coleman", - "label": "Super modèle 1", - "requiredNomenclatureIds": [ - "L_DEPNAIS-1-1-0", - "L_PAYSNAIS-1-1-0", - "L_NATIONETR-1-1-0" - ] - }], - "nomenclatures": [ - { - "id": "L_DEPNAIS-1-1-0", - "cheminRepertoire": "DEPNAIS", - "label": "Liste des départements" - }, - { - "id": "L_PAYSNAIS-1-1-0", - "cheminRepertoire": "PAYSNAIS", - "label": "liste des pays" - }, - { - "id": "L_NATIONETR-1-1-0", - "cheminRepertoire": "NATIONETR", - "label": "liste des nationalités" - } - ] -} \ No newline at end of file diff --git a/src/test/resources/fr/insee/protools/backend/service/platine/delegate/protools-contexte-platine-logement.json b/src/test/resources/fr/insee/protools/backend/service/platine/delegate/protools-contexte-platine-logement.json deleted file mode 100644 index c7072222..00000000 --- a/src/test/resources/fr/insee/protools/backend/service/platine/delegate/protools-contexte-platine-logement.json +++ /dev/null @@ -1,84 +0,0 @@ -{ - "id": "DEM2022X00", - "label": "Enquête démo 2022 - séquence 1", - "contexte": "household", - "metadonnees": { - "annee": 2022, - "periodicite": "X", - "periode": "X00", - "operationId": "DEM2022", - "operationLabelCourt": "operationLabelCourt", - "operationLabelLong": "operationLabelLong", - "serieId": "DEM", - "serieLabelCourt": "serieLabelCourt", - "serieLabelLong": "serieLabelLong", - "portailMesEnquetesOperation": true, - "objectifsCourts": "objectifsCourts", - "objectifsLongs": "objectifsLongs", - "caractereObligatoire": true, - "qualiteStatistique": true, - "testNonLabellise": true, - "anneeVisa": 2022, - "numeroVisa": "2022xxxxxx", - "ministereTutelle": "de l'Économie, des Finances et de la Souveraineté Industrielle et Numérique", - "parutionJo": true, - "dateParutionJo": "2021-12-23", - "responsableOperationnel": "L’Institut national de la statistique et des études économiques (Insee)", - "responsableTraitement": "l'Insee", - "cnisUrl": "http://cnis/DOG2021", - "diffusionUrl": "http://diffusion/DOG2021", - "noticeUrl": "http://notice/DOG2021", - "specimenUrl": "http://specimenUrl/DOG2021", - "proprietaireId": "proprietaireId", - "proprietaireLabel": "proprietaireLabel", - "proprietaireLogo": "proprietaireLogo", - "assistanceNiveau2Id": "assistanceNiveau2Id", - "assistanceNiveau2Label": "assistanceNiveau2Label", - "assistanceNiveau2Tel": "assistanceNiveau2Tel", - "assitanceNiveau2Mail": "assitanceNiveau2Mail", - "asssistanceNiveau2Pays": "asssistanceNiveau2Pays", - "assistanceNiveau2NumeroVoie": "assistanceNiveau2NumeroVoie", - "assistanceNiveau2NomVoie": "rue Kennedy", - "assistanceNiveau2Commune": "assistanceNiveau2Commune", - "assistanceNiveau2CodePostal": "assistanceNiveau2CodePostal" - }, - "partitions": [{ - "id": 1, - "label": "lot hommes", - "typeEchantillon" : "LOGEMENT", - "dateDebutCollecte": "2023-01-16T14:07:23.001Z", - "dateFinCollecte": "2024-01-16T14:07:23.001Z", - "dateRetour": "2024-01-16T14:07:23.001Z", - "questionnaireModel": "tic2023a00_web", - "quiRepond1": "Qui doit répondre paragraphe 1", - "quiRepond2": "Qui doit répondre paragraphe 2", - "quiRepond3": "Qui doit répondre paragraphe 3" - }], - "questionnaireModels": [{ - "id": "tic2023a00_web", - "cheminRepertoire": "coleman", - "label": "Super modèle 1", - "requiredNomenclatureIds": [ - "L_DEPNAIS-1-1-0", - "L_PAYSNAIS-1-1-0", - "L_NATIONETR-1-1-0" - ] - }], - "nomenclatures": [ - { - "id": "L_DEPNAIS-1-1-0", - "cheminRepertoire": "DEPNAIS", - "label": "Liste des départements" - }, - { - "id": "L_PAYSNAIS-1-1-0", - "cheminRepertoire": "PAYSNAIS", - "label": "liste des pays" - }, - { - "id": "L_NATIONETR-1-1-0", - "cheminRepertoire": "NATIONETR", - "label": "liste des nationalités" - } - ] -} \ No newline at end of file diff --git a/src/test/resources/fr/insee/protools/backend/service/sabiane/delegate/expected_post_questionnaire_metadata.json b/src/test/resources/fr/insee/protools/backend/service/sabiane/delegate/expected_post_questionnaire_metadata.json deleted file mode 100644 index 47609748..00000000 --- a/src/test/resources/fr/insee/protools/backend/service/sabiane/delegate/expected_post_questionnaire_metadata.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "value": { - "variables": [ - { - "name": "Enq_LibelleEnquete", - "value": "Enquête de démo 2022" - } - ], - "inseeContext": "household" - } -} \ No newline at end of file diff --git a/src/test/resources/fr/insee/protools/backend/service/sabiane/delegate/pilotage_expected_post_campaign.json b/src/test/resources/fr/insee/protools/backend/service/sabiane/delegate/pilotage_expected_post_campaign.json deleted file mode 100644 index adec50fa..00000000 --- a/src/test/resources/fr/insee/protools/backend/service/sabiane/delegate/pilotage_expected_post_campaign.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "campaign":"MBG2022X01", - "campaignLabel":"Enquête de démo 2022 - séquence 1", - "visibilities":[ - { - "organizationalUnit":"OU-TEST1", - "collectionStartDate":1673878043001, - "collectionEndDate":1705414043001, - "identificationPhaseStartDate":1673878043001, - "interviewerStartDate":1673878043001, - "managementStartDate":1705414043001, - "endDate":1705414043001 - }, - { - "organizationalUnit":"OU-TEST2", - "collectionStartDate":1673878043001, - "collectionEndDate":1705414043001, - "identificationPhaseStartDate":1673878043001, - "interviewerStartDate":1673878043001, - "managementStartDate":1705414043001, - "endDate":1705414043001 - } - ], - "referents":[ - { - "firstName":"Paul", - "lastName":"Durand", - "phoneNumber":"0101010101", - "role":"PRIMARY" - }, - { - "firstName":"Jean", - "lastName":"Dupont", - "phoneNumber":"0101010102", - "role":"PRIMARY" - }, - { - "firstName":"Léa", - "lastName":"Durand", - "phoneNumber":"0101010103", - "role":"SECONDARY" - } - ], - "email":"blabla@insee.fr", - "identificationConfiguration":"IASCO", - "contactOutcomeConfiguration":"TEL", - "contactAttemptConfiguration":"TEL" -} \ No newline at end of file diff --git a/src/test/resources/fr/insee/protools/backend/service/sabiane/delegate/protools-contexte-sabiane-incorrect.json b/src/test/resources/fr/insee/protools/backend/service/sabiane/delegate/protools-contexte-sabiane-incorrect.json deleted file mode 100644 index 28548ab7..00000000 --- a/src/test/resources/fr/insee/protools/backend/service/sabiane/delegate/protools-contexte-sabiane-incorrect.json +++ /dev/null @@ -1,93 +0,0 @@ -{ - "id": "MBG2022X01", - "label": "Enquête de démo 2022 - séquence 1", - "contexte": "household", - "metadonnees": { - "operationLabelCourt": "Démo 2022", - "ERROR___________operationLabelLong": "Enquête de démo 2022", - "assitanceNiveau2Mail": "blabla@insee.fr", - "reperage": "faf_logement", - "essaisContact": "tel", - "bilanContact": "tel", - "referentsPrincipaux": [ - { - "nom": "Durand", - "prenom": "Paul", - "telephone": "0101010101" - }, - { - "nom": "Dupont", - "prenom": "Jean", - "telephone": "0101010102" - } - ], - "referentsSecondaires": [ - { - "nom": "Durand", - "prenom": "Léa", - "telephone": "0101010103" - } - ] - }, - "partitions": [{ - "id": 59901, - "label": "lot hommes", - "dateDebutCollecte": "2023-01-16T14:07:23.001Z", - "dateFinCollecte": "2023-01-16T14:07:23.001Z", - "dateDebutVisibiliteGestionnaire": "2023-01-16T14:07:23.001Z", - "dateDebutVisibiliteEnqueteur": "2023-01-16T14:07:23.001Z", - "dateDebutReperage": "2023-01-16T14:07:23.001Z", - "dateFinTraitement": "2023-01-16T14:07:23.001Z" - }, - { - "id": 59902, - "label": "lot femmes", - "dateDebutCollecte": "2024-01-16T14:07:23.001Z", - "dateFinCollecte": "2024-01-16T14:07:23.001Z", - "dateDebutVisibiliteGestionnaire": "2024-01-16T14:07:23.001Z", - "dateDebutVisibiliteEnqueteur": "2024-01-16T14:07:23.001Z", - "dateDebutReperage": "2024-01-16T14:07:23.001Z", - "dateFinTraitement": "2024-01-16T14:07:23.001Z" - } - ], - "questionnaireModels": [{ - "id": "tic2023a00_webMBG", - "cheminRepertoire": "coleman", - "label": "Super modèle 1", - "requiredNomenclatureIds": [ - "L_DEPNAIS-1-1-0", - "L_PAYSNAIS-1-1-0", - "L_NATIONETR-1-1-0" - ] - }, - { - "id": "FAM2022X01", - "cheminRepertoire": "sabiane", - "label": "Super modèle 2", - "requiredNomenclatureIds": [ - "L_COMMUNEPASSEE-1-1-0" - ] - }], - "nomenclatures": [ - { - "id": "L_DEPNAIS-1-1-0", - "cheminRepertoire": " DEPNAIS", - "label": "Liste des départements" - }, - { - "id": "L_PAYSNAIS-1-1-0", - "cheminRepertoire": "PAYSNAIS", - "label": "liste des pays" - }, - { - "id": "L_NATIONETR-1-1-0", - "cheminRepertoire": "NATIONETR", - "label": "liste des nationalités" - }, - { - "id": "L_COMMUNEPASSEE-1-1-0", - "cheminRepertoire": "COMMUNEPASSEE", - "label": "liste des communes" - } - ] -} \ No newline at end of file diff --git a/src/test/resources/fr/insee/protools/backend/service/sabiane/delegate/protools-contexte-sabiane.json b/src/test/resources/fr/insee/protools/backend/service/sabiane/delegate/protools-contexte-sabiane.json deleted file mode 100644 index 4c4bc920..00000000 --- a/src/test/resources/fr/insee/protools/backend/service/sabiane/delegate/protools-contexte-sabiane.json +++ /dev/null @@ -1,94 +0,0 @@ -{ - "id": "MBG2022X01", - "label": "Enquête de démo 2022 - séquence 1", - "contexte": "household", - "metadonnees": { - "operationLabelCourt": "Démo 2022", - "operationLabelLong": "Enquête de démo 2022", - "assitanceNiveau2Mail": "blabla@insee.fr", - "reperage": "faf_logement", - "essaisContact": "tel", - "bilanContact": "tel", - "referentsPrincipaux": [ - { - "nom": "Durand", - "prenom": "Paul", - "telephone": "0101010101" - }, - { - "nom": "Dupont", - "prenom": "Jean", - "telephone": "0101010102" - } - ], - "referentsSecondaires": [ - { - "nom": "Durand", - "prenom": "Léa", - "telephone": "0101010103" - } - ], - "sitesGestion": [ "OU-TEST1" , "OU-TEST2" ] - }, - "partitions": [{ - "id": 59901, - "label": "lot hommes", - "dateDebutCollecte": "2023-01-16T14:07:23.001Z", - "dateFinCollecte": "2023-01-16T14:07:23.001Z", - "dateDebutVisibiliteGestionnaire": "2023-01-16T14:07:23.001Z", - "dateDebutVisibiliteEnqueteur": "2023-01-16T14:07:23.001Z", - "dateDebutReperage": "2023-01-16T14:07:23.001Z", - "dateFinTraitement": "2023-01-16T14:07:23.001Z" - }, - { - "id": 59902, - "label": "lot femmes", - "dateDebutCollecte": "2024-01-16T14:07:23.001Z", - "dateFinCollecte": "2024-01-16T14:07:23.001Z", - "dateDebutVisibiliteGestionnaire": "2024-01-16T14:07:23.001Z", - "dateDebutVisibiliteEnqueteur": "2024-01-16T14:07:23.001Z", - "dateDebutReperage": "2024-01-16T14:07:23.001Z", - "dateFinTraitement": "2024-01-16T14:07:23.001Z" - } - ], - "questionnaireModels": [{ - "id": "tic2023a00_webMBG", - "cheminRepertoire": "coleman", - "label": "Super modèle 1", - "requiredNomenclatureIds": [ - "L_DEPNAIS-1-1-0", - "L_PAYSNAIS-1-1-0", - "L_NATIONETR-1-1-0" - ] - }, - { - "id": "FAM2022X01", - "cheminRepertoire": "sabiane", - "label": "Super modèle 2", - "requiredNomenclatureIds": [ - "L_COMMUNEPASSEE-1-1-0" - ] - }], - "nomenclatures": [ - { - "id": "L_DEPNAIS-1-1-0", - "cheminRepertoire": " DEPNAIS", - "label": "Liste des départements" - }, - { - "id": "L_PAYSNAIS-1-1-0", - "cheminRepertoire": "PAYSNAIS", - "label": "liste des pays" - }, - { - "id": "L_NATIONETR-1-1-0", - "cheminRepertoire": "NATIONETR", - "label": "liste des nationalités" - }, - { - "id": "L_COMMUNEPASSEE-1-1-0", - "cheminRepertoire": "COMMUNEPASSEE", - "label": "liste des communes" - } - ] -} \ No newline at end of file diff --git a/src/test/resources/fr/insee/protools/backend/service/utils/data/rem-su-noMainOrSurveyed.json b/src/test/resources/fr/insee/protools/backend/service/utils/data/rem-su-noMainOrSurveyed.json deleted file mode 100644 index 38091cef..00000000 --- a/src/test/resources/fr/insee/protools/backend/service/utils/data/rem-su-noMainOrSurveyed.json +++ /dev/null @@ -1,91 +0,0 @@ -{ - "repositoryId": 3043280, - "externalId": "012797237", - "externalName": null, - "context": "HOUSEHOLD", - "address": { - "streetNumber": "1", - "repetitionIndex": null, - "streetType": null, - "streetName": "RUE DE L INSEE", - "addressSupplement": "BAT DE TEST", - "cityName": "LILLE", - "zipCode": "59000", - "cedexCode": null, - "cedexName": null, - "specialDistribution": null, - "countryCode": null, - "countryName": null, - "locationHelp": { - "cityCode": "31488", - "building": null, - "floor": "00/_", - "staircase": null, - "door": null, - "iris": "0104", - "sector": "up_31488", - "gpsCoordinates": { - "latitude": 43.00000000000000, - "longitude": 1.00000000000000 - }, - "elevator": null, - "cityPriorityDistrict": false - } - }, - "persons": [ - { - "index": 1, - "externalId": "012797237", - "function": null, - "gender": "2", - "firstName": "TOBEFOUND", - "lastName": null, - "birthName": "Nom de test", - "dateOfBirth": "19000101", - "surveyed": false, - "main": false, - "coDeclarant": null, - "phoneNumbers": [ - { - "source": "INITIAL", - "favorite": false, - "number": "0601020304" - } - ], - "emails": [ - { - "source": "INITIAL", - "favorite": false, - "mailAddress": "test@gmail.com" - } - ], - "address": null - } - ], - "otherIdentifier": { - "numfa": null, - "rges": "1", - "ssech": "2", - "cle": null, - "le": null, - "ec": null, - "bs": null, - "nograp": null, - "nolog": null, - "noi": null, - "nole": null, - "autre": null - }, - "additionalInformations": [ - { - "key": "ident_ind_dec", - "value": "012797237" - } - ], - "externals": { - "EXTERNAL": { - "ADMINISTRATION1": "Insee", - "ADMINISTRATION2": "Patate" - } - } -} \ No newline at end of file diff --git a/src/test/resources/fr/insee/protools/backend/service/utils/data/rem-su-test-selection.json b/src/test/resources/fr/insee/protools/backend/service/utils/data/rem-su-test-selection.json deleted file mode 100644 index 9ce5cf24..00000000 --- a/src/test/resources/fr/insee/protools/backend/service/utils/data/rem-su-test-selection.json +++ /dev/null @@ -1,141 +0,0 @@ -{ - "repositoryId": 3043280, - "externalId": "012797237", - "externalName": null, - "context": "HOUSEHOLD", - "address": { - "streetNumber": "1", - "repetitionIndex": null, - "streetType": null, - "streetName": "RUE DE L INSEE", - "addressSupplement": "SupplementAdresse", - "cityName": "Lille", - "zipCode": "59000", - "cedexCode": null, - "cedexName": null, - "specialDistribution": "specialDistribution", - "countryCode": null, - "countryName": null, - "locationHelp": { - "cityCode": "31488", - "building": null, - "floor": "00/_", - "staircase": null, - "door": "door", - "iris": "0104", - "sector": "up_31488", - "cityPriorityDistrict": false - } - }, - "otherIdentifier": { - "numfa": null, - "rges": null, - "ssech": null, - "cle": null, - "le": null, - "ec": null, - "bs": null, - "nograp": null, - "nolog": null, - "noi": null, - "nole": null, - "autre": null - }, - "persons": [ - { - "index": 1, - "externalId": "012797237", - "function": null, - "gender": "2", - "firstName": "firstName1", - "lastName": "lastName1", - "birthName": "Nom de test", - "dateOfBirth": "19800505", - "surveyed": false, - "main": false, - "coDeclarant": null, - "phoneNumbers": [ - { - "source": "INITIAL", - "favorite": false, - "number": "01" - } - ], - "emails": [ - { - "source": "INITIAL", - "favorite": false, - "mailAddress": "test1@gmail.com" - } - ], - "address": null - }, - { - "index": 2, - "externalId": "012797236", - "function": null, - "gender": "2", - "firstName": "firstName2", - "lastName": "lastName2", - "birthName": "Nom de test", - "dateOfBirth": "19800102", - "surveyed": true, - "main": true, - "coDeclarant": null, - "phoneNumbers": [ - { - "source": "INITIAL", - "favorite": false, - "number": "02" - } - ], - "emails": [ - { - "source": "INITIAL", - "favorite": false, - "mailAddress": "test2@gmail.com" - } - ], - "address": null - }, - { - "index": 3, - "externalId": "012797235", - "function": null, - "gender": "2", - "firstName": "firstName3", - "lastName": "lastName3", - "birthName": "Nom de test", - "dateOfBirth": "19800103", - "surveyed": false, - "main": false, - "coDeclarant": null, - "phoneNumbers": [ - { - "source": "INITIAL", - "favorite": false, - "number": "0601020304" - } - ], - "emails": [ - { - "source": "INITIAL", - "favorite": false, - "mailAddress": "test3a@gmail.com" - }, - { - "source": "INITIAL", - "favorite": true, - "mailAddress": "test3b@gmail.com" - } - ], - "address": null - } - ], - "additionalInformations": [ - { - "key": "pole_gestion_opale", - "value": "ID_POLE_GESTION_OPALE" - } - ] -} \ No newline at end of file diff --git a/src/test/resources/fr/insee/protools/backend/service/utils/data/rem-su_1personne.json b/src/test/resources/fr/insee/protools/backend/service/utils/data/rem-su_1personne.json deleted file mode 100644 index af47cb1e..00000000 --- a/src/test/resources/fr/insee/protools/backend/service/utils/data/rem-su_1personne.json +++ /dev/null @@ -1,91 +0,0 @@ -{ - "repositoryId": 3043280, - "externalId": "012797237", - "externalName": null, - "context": "HOUSEHOLD", - "address": { - "streetNumber": "1", - "repetitionIndex": null, - "streetType": null, - "streetName": "RUE DE L INSEE", - "addressSupplement": "BAT DE TEST", - "cityName": "LILLE", - "zipCode": "59000", - "cedexCode": null, - "cedexName": null, - "specialDistribution": null, - "countryCode": null, - "countryName": null, - "locationHelp": { - "cityCode": "31488", - "building": null, - "floor": "00/_", - "staircase": null, - "door": null, - "iris": "0104", - "sector": "up_31488", - "gpsCoordinates": { - "latitude": 43.00000000000000, - "longitude": 1.00000000000000 - }, - "elevator": null, - "cityPriorityDistrict": false - } - }, - "persons": [ - { - "index": 1, - "externalId": "012797237", - "function": null, - "gender": "2", - "firstName": "TOBEFOUND", - "lastName": null, - "birthName": "Nom de test", - "dateOfBirth": "19000101", - "surveyed": true, - "main": true, - "coDeclarant": null, - "phoneNumbers": [ - { - "source": "INITIAL", - "favorite": false, - "number": "0601020304" - } - ], - "emails": [ - { - "source": "INITIAL", - "favorite": false, - "mailAddress": "test@gmail.com" - } - ], - "address": null - } - ], - "otherIdentifier": { - "numfa": null, - "rges": "1", - "ssech": "2", - "cle": null, - "le": null, - "ec": null, - "bs": null, - "nograp": null, - "nolog": null, - "noi": null, - "nole": null, - "autre": null - }, - "additionalInformations": [ - { - "key": "ident_ind_dec", - "value": "012797237" - } - ], - "externals": { - "EXTERNAL": { - "ADMINISTRATION1": "Insee", - "ADMINISTRATION2": "Patate" - } - } -} \ No newline at end of file diff --git a/src/test/resources/fr/insee/protools/backend/service/utils/data/rem-su_3personnes.json b/src/test/resources/fr/insee/protools/backend/service/utils/data/rem-su_3personnes.json deleted file mode 100644 index 2fb3679b..00000000 --- a/src/test/resources/fr/insee/protools/backend/service/utils/data/rem-su_3personnes.json +++ /dev/null @@ -1,147 +0,0 @@ -{ - "repositoryId": 3043280, - "externalId": "012797237", - "externalName": null, - "context": "HOUSEHOLD", - "address": { - "streetNumber": "1", - "repetitionIndex": null, - "streetType": null, - "streetName": "RUE DE L INSEE", - "addressSupplement": "BAT DE TEST", - "cityName": "LILLE", - "zipCode": "59000", - "cedexCode": null, - "cedexName": null, - "specialDistribution": null, - "countryCode": null, - "countryName": null, - "locationHelp": { - "cityCode": "31488", - "building": null, - "floor": "00/_", - "staircase": null, - "door": null, - "iris": "0104", - "sector": "up_31488", - "gpsCoordinates": { - "latitude": 43.00000000000000, - "longitude": 1.00000000000000 - }, - "elevator": null, - "cityPriorityDistrict": false - } - }, - "persons": [ - { - "index": 1, - "externalId": "012797237", - "function": null, - "gender": "2", - "firstName": "PAS_CONTACT1", - "lastName": null, - "birthName": "Nom de test", - "dateOfBirth": "19000101", - "surveyed": false, - "main": false, - "coDeclarant": null, - "phoneNumbers": [ - { - "source": "INITIAL", - "favorite": false, - "number": "0601020304" - } - ], - "emails": [ - { - "source": "INITIAL", - "favorite": false, - "mailAddress": "test@gmail.com" - } - ], - "address": null - }, - { - "index": 2, - "externalId": "012797236", - "function": null, - "gender": "2", - "firstName": "TOBEFOUND", - "lastName": null, - "birthName": "Nom de test", - "dateOfBirth": "19000101", - "surveyed": true, - "main": true, - "coDeclarant": null, - "phoneNumbers": [ - { - "source": "INITIAL", - "favorite": false, - "number": "0601020304" - } - ], - "emails": [ - { - "source": "INITIAL", - "favorite": false, - "mailAddress": "test@gmail.com" - } - ], - "address": null - }, - { - "index": 3, - "externalId": "012797235", - "function": null, - "gender": "2", - "firstName": "PAS_CONTACT2", - "lastName": null, - "birthName": "Nom de test", - "dateOfBirth": "19000101", - "surveyed": false, - "main": false, - "coDeclarant": null, - "phoneNumbers": [ - { - "source": "INITIAL", - "favorite": false, - "number": "0601020304" - } - ], - "emails": [ - { - "source": "INITIAL", - "favorite": false, - "mailAddress": "test@gmail.com" - } - ], - "address": null - } - ], - "otherIdentifier": { - "numfa": null, - "rges": "1", - "ssech": "2", - "cle": null, - "le": null, - "ec": null, - "bs": null, - "nograp": null, - "nolog": null, - "noi": null, - "nole": null, - "autre": null - }, - "additionalInformations": [ - { - "key": "ident_ind_dec", - "value": "012797237" - } - ], - "externals": { - "EXTERNAL": { - "ADMINISTRATION1": "Insee", - "ADMINISTRATION2": "Patate" - } - } -} \ No newline at end of file