diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index eb05930b..68631252 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -42,7 +42,7 @@ jobs: cd .. - name: Build Genesis with Maven - run: mvn -B package --file pom.xml + run: mvn clean package -B --file pom.xml # Optional: Uploads the full dependency graph to GitHub to improve the quality of Dependabot alerts this repository can receive - name: Update dependency graph diff --git a/src/main/java/fr/insee/genesis/Constants.java b/src/main/java/fr/insee/genesis/Constants.java index f1711c2e..bdcbff19 100644 --- a/src/main/java/fr/insee/genesis/Constants.java +++ b/src/main/java/fr/insee/genesis/Constants.java @@ -47,8 +47,8 @@ public class Constants { // Data extraction parameters - public static final int BATCH_SIZE = 100; //TODO Adapt to avoid OutOfMemoryException - public static final String DIFFRENTIAL_DATA_FOLDER_NAME = "differential/data"; + public static final int BATCH_SIZE = 100; //Adapt to avoid OutOfMemoryException + public static final String DIFFERENTIAL_DATA_FOLDER_NAME = "differential/data"; // Kraftwerk service path parameters public static final String KRAFTWERK_MAIN_ENDPOINT = ""; diff --git a/src/main/java/fr/insee/genesis/configuration/Config.java b/src/main/java/fr/insee/genesis/configuration/Config.java index ed5812e4..f3e83444 100644 --- a/src/main/java/fr/insee/genesis/configuration/Config.java +++ b/src/main/java/fr/insee/genesis/configuration/Config.java @@ -20,6 +20,9 @@ public class Config { @Value("${fr.insee.genesis.sourcefolder.specifications}") private String specFolderSource; + @Value("${fr.insee.genesis.authentication}") + private String authType; + @Value("${fr.insee.genesis.oidc.auth-server-url}") private String authServerUrl; diff --git a/src/main/java/fr/insee/genesis/controller/dto/SurveyUnitInputDto.java b/src/main/java/fr/insee/genesis/controller/dto/SurveyUnitInputDto.java new file mode 100644 index 00000000..ba234c4c --- /dev/null +++ b/src/main/java/fr/insee/genesis/controller/dto/SurveyUnitInputDto.java @@ -0,0 +1,19 @@ +package fr.insee.genesis.controller.dto; + +import fr.insee.genesis.domain.model.surveyunit.Mode; +import lombok.Builder; +import lombok.Data; + +import java.util.List; + +@Builder +@Data +public class SurveyUnitInputDto { + + private String surveyUnitId; + private String campaignId; + private Mode mode; + private String idQuestionnaire; + private List collectedVariables; + +} diff --git a/src/main/java/fr/insee/genesis/controller/dto/VariableInputDto.java b/src/main/java/fr/insee/genesis/controller/dto/VariableInputDto.java new file mode 100644 index 00000000..b75dc7c2 --- /dev/null +++ b/src/main/java/fr/insee/genesis/controller/dto/VariableInputDto.java @@ -0,0 +1,17 @@ +package fr.insee.genesis.controller.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Builder; +import lombok.Data; + +import java.util.List; + +@Builder +@Data +public class VariableInputDto { + private String variableName; + private String idLoop; + + @JsonProperty("newVariableState") + private VariableStateInputDto variableStateInputDto; +} diff --git a/src/main/java/fr/insee/genesis/controller/dto/VariableStateDto.java b/src/main/java/fr/insee/genesis/controller/dto/VariableStateDto.java index 4d8625f7..cee2115c 100644 --- a/src/main/java/fr/insee/genesis/controller/dto/VariableStateDto.java +++ b/src/main/java/fr/insee/genesis/controller/dto/VariableStateDto.java @@ -14,6 +14,6 @@ public class VariableStateDto { private boolean active; private String value; - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd/MM/yyyy hh:mm:ss.SSS") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd/MM/yyyy HH:mm:ss.SSS") private LocalDateTime date; } diff --git a/src/main/java/fr/insee/genesis/controller/dto/VariableStateInputDto.java b/src/main/java/fr/insee/genesis/controller/dto/VariableStateInputDto.java new file mode 100644 index 00000000..1e3e4739 --- /dev/null +++ b/src/main/java/fr/insee/genesis/controller/dto/VariableStateInputDto.java @@ -0,0 +1,15 @@ +package fr.insee.genesis.controller.dto; + +import fr.insee.genesis.domain.model.surveyunit.DataState; +import lombok.Builder; +import lombok.Data; + +@Builder +@Data +public class VariableStateInputDto { + + private DataState state; + + private String value; + +} diff --git a/src/main/java/fr/insee/genesis/controller/rest/responses/ResponseController.java b/src/main/java/fr/insee/genesis/controller/rest/responses/ResponseController.java index cc6fdcaa..40b6c82e 100644 --- a/src/main/java/fr/insee/genesis/controller/rest/responses/ResponseController.java +++ b/src/main/java/fr/insee/genesis/controller/rest/responses/ResponseController.java @@ -9,11 +9,13 @@ import fr.insee.genesis.controller.adapter.LunaticXmlAdapter; import fr.insee.genesis.controller.dto.SurveyUnitDto; import fr.insee.genesis.controller.dto.SurveyUnitId; +import fr.insee.genesis.controller.dto.SurveyUnitInputDto; import fr.insee.genesis.controller.dto.SurveyUnitSimplified; import fr.insee.genesis.controller.sources.xml.LunaticXmlCampaign; import fr.insee.genesis.controller.sources.xml.LunaticXmlDataParser; import fr.insee.genesis.controller.sources.xml.LunaticXmlDataSequentialParser; import fr.insee.genesis.controller.sources.xml.LunaticXmlSurveyUnit; +import fr.insee.genesis.controller.utils.AuthUtils; import fr.insee.genesis.controller.utils.ControllerUtils; import fr.insee.genesis.domain.model.surveyunit.CollectedVariable; import fr.insee.genesis.domain.model.surveyunit.Mode; @@ -54,6 +56,7 @@ import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; import java.util.stream.Stream; @RequestMapping(path = "/responses" ) @@ -73,6 +76,7 @@ public class ResponseController { private final LunaticJsonRawDataApiPort lunaticJsonRawDataApiPort; private final FileUtils fileUtils; private final ControllerUtils controllerUtils; + private final AuthUtils authUtils; public ResponseController(SurveyUnitApiPort surveyUnitService, @@ -80,13 +84,16 @@ public ResponseController(SurveyUnitApiPort surveyUnitService, LunaticXmlRawDataApiPort lunaticXmlRawDataApiPort, LunaticJsonRawDataApiPort lunaticJsonRawDataApiPort, FileUtils fileUtils, - ControllerUtils controllerUtils) { + ControllerUtils controllerUtils, + AuthUtils authUtils + ) { this.surveyUnitService = surveyUnitService; this.surveyUnitQualityService = surveyUnitQualityService; this.lunaticXmlRawDataApiPort = lunaticXmlRawDataApiPort; this.lunaticJsonRawDataApiPort = lunaticJsonRawDataApiPort; this.fileUtils = fileUtils; this.controllerUtils = controllerUtils; + this.authUtils = authUtils; } //SAVE @@ -230,7 +237,7 @@ public ResponseEntity saveResponsesFromAllCampaignFolders(){ try { List modesList = controllerUtils.getModesList(campaignName, null); //modeSpecified null = all modes for (Mode currentMode : modesList) { - processCampaignWithMode(campaignName, currentMode, errors, Constants.DIFFRENTIAL_DATA_FOLDER_NAME); + processCampaignWithMode(campaignName, currentMode, errors, Constants.DIFFERENTIAL_DATA_FOLDER_NAME); } }catch (NoDataException nde){ log.warn(nde.getMessage()); @@ -360,6 +367,62 @@ public ResponseEntity> getLatestForUEList(@RequestPar return ResponseEntity.ok(results); } + @Operation(summary = "Save edited variables", + description = "Save edited variables document into database") + @PostMapping(path = "/save-edited") + public ResponseEntity saveEditedVariables( + @RequestBody SurveyUnitInputDto surveyUnitInputDto + ){ + //Parse metadata + //Try to look for DDI first, if no DDI found looks for lunatic components + List errors = new ArrayList<>(); + VariablesMap variablesMap = readMetadatas(surveyUnitInputDto.getCampaignId(), surveyUnitInputDto.getMode(), errors, true); + if(variablesMap == null){ + log.warn("Can't find DDI, trying with lunatic..."); + variablesMap = readMetadatas(surveyUnitInputDto.getCampaignId(), surveyUnitInputDto.getMode(), errors, false); + if(variablesMap == null){ + return ResponseEntity.status(404).body(errors.getLast().getMessage()); + } + } + + //Check if input edited variables are in metadatas + List absentCollectedVariableNames = + surveyUnitQualityService.checkVariablesPresentInMetadata(surveyUnitInputDto.getCollectedVariables(), + variablesMap); +// List absentExternalVariableNames = +// surveyUnitQualityService.checkVariablesPresentInMetadata(surveyUnitInputDto.getExternalVariables(), +// variablesMap); + if (!absentCollectedVariableNames.isEmpty()) { + String absentVariables = String.join("\n", absentCollectedVariableNames); + return ResponseEntity.badRequest().body( + String.format("The following variables are absent in metadatas : %n%s", absentVariables) + ); + } + + //Fetch user identifier from OIDC token + String userIdentifier = authUtils.getIDEP(); + + + //Create surveyUnitModel for each STATE received (Quality tool could send variables with another STATE than EDITED) + List surveyUnitModels; + try{ + surveyUnitModels = surveyUnitService.parseEditedVariables( + surveyUnitInputDto, + userIdentifier, + variablesMap + ); + }catch (GenesisException e){ + return ResponseEntity.status(e.getStatus()).body(e.getMessage()); + } + + //Check data with dataverifier (might create a FORCED document) + surveyUnitQualityService.verifySurveyUnits(surveyUnitModels, variablesMap); + + //Save documents + surveyUnitService.saveSurveyUnits(surveyUnitModels); + return ResponseEntity.ok(SUCCESS_MESSAGE); + } + //Utilities /** @@ -579,10 +642,9 @@ private ResponseEntity processXmlFileSequentially(Path filepath, Mode mo su = parser.readNextSurveyUnit(); } - log.info("Saved {} survey units updates", suCount); + log.info("Saved {} survey units updates from Xml file {}", suCount, filepath.getFileName()); } - log.info("File {} processed", filepath.getFileName()); return ResponseEntity.ok().build(); } diff --git a/src/main/java/fr/insee/genesis/controller/utils/AuthUtils.java b/src/main/java/fr/insee/genesis/controller/utils/AuthUtils.java new file mode 100644 index 00000000..e91f1823 --- /dev/null +++ b/src/main/java/fr/insee/genesis/controller/utils/AuthUtils.java @@ -0,0 +1,33 @@ +package fr.insee.genesis.controller.utils; + +import fr.insee.genesis.configuration.Config; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Component; + +import java.util.Optional; + +@Component +public class AuthUtils { + private final Config config; + + @Autowired + public AuthUtils(Config config){ + this.config = config; + } + + /** + * Extract IDEP from OIDC token + * @return the IDEP from the OIDC if the app uses OIDC auth, null otherwise + */ + public String getIDEP() { + if ("OIDC".equals(config.getAuthType())) { + return Optional.ofNullable(SecurityContextHolder.getContext().getAuthentication()) + .map(Authentication::getName) + .map(name -> name.substring(name.lastIndexOf(":") + 1)) + .orElse(null); + } + return null; + } +} diff --git a/src/main/java/fr/insee/genesis/domain/model/surveyunit/SurveyUnitModel.java b/src/main/java/fr/insee/genesis/domain/model/surveyunit/SurveyUnitModel.java index ee04645b..48cad798 100644 --- a/src/main/java/fr/insee/genesis/domain/model/surveyunit/SurveyUnitModel.java +++ b/src/main/java/fr/insee/genesis/domain/model/surveyunit/SurveyUnitModel.java @@ -29,6 +29,8 @@ public class SurveyUnitModel { private List collectedVariables; private List externalVariables; + private String modifiedBy; + public SurveyUnitModel(String idUE, Mode mode) { this.idUE = idUE; this.mode = mode; diff --git a/src/main/java/fr/insee/genesis/domain/ports/api/SurveyUnitApiPort.java b/src/main/java/fr/insee/genesis/domain/ports/api/SurveyUnitApiPort.java index 29a5def5..f7a4d79e 100644 --- a/src/main/java/fr/insee/genesis/domain/ports/api/SurveyUnitApiPort.java +++ b/src/main/java/fr/insee/genesis/domain/ports/api/SurveyUnitApiPort.java @@ -1,11 +1,14 @@ package fr.insee.genesis.domain.ports.api; +import fr.insee.bpm.metadata.model.VariablesMap; import fr.insee.genesis.controller.dto.CampaignWithQuestionnaire; import fr.insee.genesis.controller.dto.SurveyUnitDto; +import fr.insee.genesis.controller.dto.SurveyUnitInputDto; import fr.insee.genesis.domain.model.surveyunit.Mode; import fr.insee.genesis.controller.dto.QuestionnaireWithCampaign; import fr.insee.genesis.domain.model.surveyunit.SurveyUnitModel; import fr.insee.genesis.controller.dto.SurveyUnitId; +import fr.insee.genesis.exceptions.GenesisException; import java.util.List; import java.util.Set; @@ -48,4 +51,8 @@ public interface SurveyUnitApiPort { List findCampaignsWithQuestionnaires(); List findQuestionnairesWithCampaigns(); -} + + List parseEditedVariables(SurveyUnitInputDto surveyUnitInputDto, + String userIdentifier, + VariablesMap variablesMap) throws GenesisException; +} \ No newline at end of file diff --git a/src/main/java/fr/insee/genesis/domain/service/surveyunit/SurveyUnitQualityService.java b/src/main/java/fr/insee/genesis/domain/service/surveyunit/SurveyUnitQualityService.java index d821b17d..dcf8ce7e 100644 --- a/src/main/java/fr/insee/genesis/domain/service/surveyunit/SurveyUnitQualityService.java +++ b/src/main/java/fr/insee/genesis/domain/service/surveyunit/SurveyUnitQualityService.java @@ -1,10 +1,13 @@ package fr.insee.genesis.domain.service.surveyunit; +import fr.insee.genesis.controller.dto.VariableDto; +import fr.insee.genesis.controller.dto.VariableInputDto; import fr.insee.genesis.domain.model.surveyunit.SurveyUnitModel; import fr.insee.genesis.domain.utils.DataVerifier; import fr.insee.bpm.metadata.model.VariablesMap; import org.springframework.stereotype.Service; +import java.util.ArrayList; import java.util.List; /** @@ -12,7 +15,25 @@ */ @Service public class SurveyUnitQualityService { - public void verifySurveyUnits(List suDtos, VariablesMap variablesMap) { - DataVerifier.verifySurveyUnits(suDtos,variablesMap); + public void verifySurveyUnits(List surveyUnitModels, VariablesMap variablesMap) { + DataVerifier.verifySurveyUnits(surveyUnitModels,variablesMap); + } + + /** + * Checks + * @param variableInputDtos input variables to check + * @param variablesMap BPM Questionnaire metadata to use for checking + * @return A list of variables that are absent in metadata + */ + public List checkVariablesPresentInMetadata(List variableInputDtos, VariablesMap variablesMap) { + List absentVariableNames = new ArrayList<>(); + + for(VariableInputDto variableInputDto : variableInputDtos){ + if(!variablesMap.hasVariable(variableInputDto.getVariableName())){ + absentVariableNames.add(variableInputDto.getVariableName()); + } + } + + return absentVariableNames; } } diff --git a/src/main/java/fr/insee/genesis/domain/service/surveyunit/SurveyUnitService.java b/src/main/java/fr/insee/genesis/domain/service/surveyunit/SurveyUnitService.java index e44ae9e7..689f8e84 100644 --- a/src/main/java/fr/insee/genesis/domain/service/surveyunit/SurveyUnitService.java +++ b/src/main/java/fr/insee/genesis/domain/service/surveyunit/SurveyUnitService.java @@ -1,15 +1,34 @@ package fr.insee.genesis.domain.service.surveyunit; -import fr.insee.genesis.controller.dto.*; -import fr.insee.genesis.domain.model.surveyunit.*; +import fr.insee.bpm.metadata.model.VariablesMap; +import fr.insee.genesis.controller.dto.CampaignWithQuestionnaire; +import fr.insee.genesis.controller.dto.QuestionnaireWithCampaign; +import fr.insee.genesis.controller.dto.SurveyUnitDto; +import fr.insee.genesis.controller.dto.SurveyUnitId; +import fr.insee.genesis.controller.dto.SurveyUnitInputDto; +import fr.insee.genesis.controller.dto.VariableDto; +import fr.insee.genesis.controller.dto.VariableInputDto; +import fr.insee.genesis.controller.dto.VariableStateDto; +import fr.insee.genesis.domain.model.surveyunit.CollectedVariable; +import fr.insee.genesis.domain.model.surveyunit.DataState; +import fr.insee.genesis.domain.model.surveyunit.IdLoopTuple; +import fr.insee.genesis.domain.model.surveyunit.Mode; +import fr.insee.genesis.domain.model.surveyunit.SurveyUnitModel; +import fr.insee.genesis.domain.model.surveyunit.Variable; import fr.insee.genesis.domain.ports.api.SurveyUnitApiPort; import fr.insee.genesis.domain.ports.spi.SurveyUnitPersistencePort; +import fr.insee.genesis.domain.utils.LoopIdentifier; +import fr.insee.genesis.exceptions.GenesisException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; import java.time.LocalDateTime; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; import java.util.stream.Stream; @Service @@ -24,8 +43,8 @@ public SurveyUnitService(SurveyUnitPersistencePort surveyUnitPersistencePort) { } @Override - public void saveSurveyUnits(List suDtos) { - surveyUnitPersistencePort.saveAll(suDtos); + public void saveSurveyUnits(List surveyUnitModels) { + surveyUnitPersistencePort.saveAll(surveyUnitModels); } @Override @@ -216,6 +235,62 @@ public List findQuestionnairesWithCampaigns() { return questionnaireWithCampaignList; } + @Override + public List parseEditedVariables( + SurveyUnitInputDto surveyUnitInputDto, + String userIdentifier, + VariablesMap variablesMap + ) throws GenesisException { + + List statesReceived = surveyUnitInputDto.getCollectedVariables().stream() + .map(colVar -> colVar.getVariableStateInputDto().getState()) + .distinct() + .toList(); + + if (statesReceived.contains(DataState.COLLECTED)){ + throw new GenesisException(400,"You can not persist in database a new value with the state COLLECTED"); + } + + List surveyUnitModels = new ArrayList<>(); + + for (DataState state : statesReceived){ + SurveyUnitModel surveyUnitModel = SurveyUnitModel.builder() + .idCampaign(surveyUnitInputDto.getCampaignId()) + .mode(surveyUnitInputDto.getMode()) + .idQuest(surveyUnitInputDto.getIdQuestionnaire()) + .idUE(surveyUnitInputDto.getSurveyUnitId()) + .state(state) + .recordDate(LocalDateTime.now()) + .collectedVariables(new ArrayList<>()) + .externalVariables(new ArrayList<>()) + .modifiedBy(userIdentifier) + .build(); + + //Keep only variable dtos who has the corresponding state + List editedCollectedVariables = surveyUnitInputDto.getCollectedVariables().stream() + .filter(colVar -> colVar.getVariableStateInputDto().getState() == state).toList(); + + //Collected variables management + for(VariableInputDto editedVariableDto : editedCollectedVariables){ + CollectedVariable collectedVariable = CollectedVariable.collectedVariableBuilder() + .idVar(editedVariableDto.getVariableName()) + .values(new ArrayList<>()) + .idParent(LoopIdentifier.getRelatedVariableName(editedVariableDto.getVariableName(), variablesMap)) + .idLoop(editedVariableDto.getIdLoop()) + .build(); + + collectedVariable.getValues().add(editedVariableDto.getVariableStateInputDto().getValue()); + + surveyUnitModel.getCollectedVariables().add(collectedVariable); + + } + surveyUnitModels.add(surveyUnitModel); + } + + return surveyUnitModels; + } + + //Utils private static List getDistinctsModes(List surveyUnitModels) { List sources = new ArrayList<>(); surveyUnitModels.forEach(surveyUnitDto -> sources.add(surveyUnitDto.getMode())); diff --git a/src/main/java/fr/insee/genesis/infrastructure/document/surveyunit/SurveyUnitDocument.java b/src/main/java/fr/insee/genesis/infrastructure/document/surveyunit/SurveyUnitDocument.java index f4b0f562..924f0dc5 100644 --- a/src/main/java/fr/insee/genesis/infrastructure/document/surveyunit/SurveyUnitDocument.java +++ b/src/main/java/fr/insee/genesis/infrastructure/document/surveyunit/SurveyUnitDocument.java @@ -23,4 +23,5 @@ public class SurveyUnitDocument { private LocalDateTime fileDate; private List collectedVariables; private List externalVariables; + private String modifiedBy; } diff --git a/src/test/java/cucumber/functional_tests/MainDefinitions.java b/src/test/java/cucumber/functional_tests/MainDefinitions.java index 95deef9c..8c60292d 100644 --- a/src/test/java/cucumber/functional_tests/MainDefinitions.java +++ b/src/test/java/cucumber/functional_tests/MainDefinitions.java @@ -10,6 +10,7 @@ import fr.insee.genesis.controller.sources.xml.LunaticXmlCampaign; import fr.insee.genesis.controller.sources.xml.LunaticXmlDataParser; import fr.insee.genesis.controller.sources.xml.LunaticXmlSurveyUnit; +import fr.insee.genesis.controller.utils.AuthUtils; import fr.insee.genesis.controller.utils.ControllerUtils; import fr.insee.genesis.domain.model.surveyunit.CollectedVariable; import fr.insee.genesis.domain.model.surveyunit.DataState; @@ -60,7 +61,8 @@ public class MainDefinitions { new LunaticXmlRawDataService(new LunaticXmlPersistanceStub()), new LunaticJsonRawDataService(new LunaticJsonPersistanceStub()), new FileUtils(config), - new ControllerUtils(new FileUtils(config)) + new ControllerUtils(new FileUtils(config)), + new AuthUtils(config) ); List surveyUnitModels; @@ -91,12 +93,12 @@ public void get_dtos(String fileName, String ddiName) throws IOException, Parser ddiFilePath.toFile().toURI().toURL().toString(), new FileInputStream(ddiFilePath.toFile()) ).getVariables(); - List suDtos = new ArrayList<>(); + List surveyUnitModels1 = new ArrayList<>(); for (LunaticXmlSurveyUnit su : campaign.getSurveyUnits()) { - suDtos.addAll(LunaticXmlAdapter.convert(su, variablesMap, campaign.getIdCampaign(), Mode.WEB)); + surveyUnitModels1.addAll(LunaticXmlAdapter.convert(su, variablesMap, campaign.getIdCampaign(), Mode.WEB)); } - surveyUnitQualityService.verifySurveyUnits(suDtos,variablesMap); - surveyUnitModels = suDtos; + surveyUnitQualityService.verifySurveyUnits(surveyUnitModels1,variablesMap); + surveyUnitModels = surveyUnitModels1; } } diff --git a/src/test/java/fr/insee/genesis/controller/rest/responses/ResponseControllerTest.java b/src/test/java/fr/insee/genesis/controller/rest/responses/ResponseControllerTest.java index 77dbdeac..702cf86e 100644 --- a/src/test/java/fr/insee/genesis/controller/rest/responses/ResponseControllerTest.java +++ b/src/test/java/fr/insee/genesis/controller/rest/responses/ResponseControllerTest.java @@ -2,9 +2,14 @@ import cucumber.TestConstants; import fr.insee.genesis.Constants; +import fr.insee.genesis.configuration.Config; import fr.insee.genesis.controller.dto.SurveyUnitDto; import fr.insee.genesis.controller.dto.SurveyUnitId; +import fr.insee.genesis.controller.dto.SurveyUnitInputDto; import fr.insee.genesis.controller.dto.SurveyUnitSimplified; +import fr.insee.genesis.controller.dto.VariableInputDto; +import fr.insee.genesis.controller.dto.VariableStateInputDto; +import fr.insee.genesis.controller.utils.AuthUtils; import fr.insee.genesis.controller.utils.ControllerUtils; import fr.insee.genesis.domain.model.surveyunit.DataState; import fr.insee.genesis.domain.model.surveyunit.Mode; @@ -25,6 +30,7 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.springframework.http.HttpStatusCode; import org.springframework.http.ResponseEntity; import org.springframework.util.FileSystemUtils; @@ -48,6 +54,8 @@ class ResponseControllerTest { //Constants static final String DEFAULT_ID_UE = "TESTIDUE"; static final String DEFAULT_ID_QUEST = "TESTIDQUESTIONNAIRE"; + static final String ID_CAMPAIGN_WITH_DDI = "SAMPLETEST-PARADATA-v1"; + static final String ID_QUEST_WITH_DDI = "SAMPLETEST-PARADATA-v1"; @BeforeAll static void init() { @@ -60,7 +68,8 @@ static void init() { lunaticJsonPersistanceStub = new LunaticJsonPersistanceStub(); LunaticJsonRawDataApiPort lunaticJsonRawDataApiPort = new LunaticJsonRawDataService(lunaticJsonPersistanceStub); - FileUtils fileUtils = new FileUtils(new ConfigStub()); + Config config = new ConfigStub(); + FileUtils fileUtils = new FileUtils(config); responseControllerStatic = new ResponseController( surveyUnitApiPort , new SurveyUnitQualityService() @@ -68,6 +77,7 @@ static void init() { , lunaticJsonRawDataApiPort , fileUtils , new ControllerUtils(fileUtils) + , new AuthUtils(config) ); surveyUnitIdList = new ArrayList<>(); @@ -376,6 +386,206 @@ void getLatestByStatesSurveyDataTest(){ .isTrue(); } + @Test + void saveEditedTest() { + //GIVEN + surveyUnitPersistencePortStub.getMongoStub().clear(); + String campaignId = ID_CAMPAIGN_WITH_DDI; + String idQuest = ID_QUEST_WITH_DDI; + String idVar = "PRENOM_C"; + String idLoop = "BOUCLE_VAL_ANNAISS_1"; + String editedValue = "TESTPRENOMEDITED"; + + List newVariables = new ArrayList<>(); + VariableInputDto variableInputDto = VariableInputDto.builder() + .variableName(idVar) + .idLoop(idLoop) + .build(); + + variableInputDto.setVariableStateInputDto(VariableStateInputDto.builder() + .state(DataState.EDITED) + .value(editedValue) + .build()); + + newVariables.add(variableInputDto); + + SurveyUnitInputDto surveyUnitInputDto = SurveyUnitInputDto.builder() + .campaignId(campaignId) + .mode(Mode.WEB) + .idQuestionnaire(idQuest) + .surveyUnitId(DEFAULT_ID_UE) + .collectedVariables(newVariables) + .build(); + //WHEN + responseControllerStatic.saveEditedVariables(surveyUnitInputDto); + + //THEN + Assertions.assertThat(surveyUnitPersistencePortStub.getMongoStub()).hasSize(1); + Assertions.assertThat(surveyUnitPersistencePortStub.getMongoStub().getFirst().getIdCampaign()).isEqualTo(campaignId); + Assertions.assertThat(surveyUnitPersistencePortStub.getMongoStub().getFirst().getIdQuest()).isEqualTo(idQuest); + Assertions.assertThat(surveyUnitPersistencePortStub.getMongoStub().getFirst().getMode()).isEqualTo(Mode.WEB); + Assertions.assertThat(surveyUnitPersistencePortStub.getMongoStub().getFirst().getState()).isEqualTo(DataState.EDITED); + Assertions.assertThat(surveyUnitPersistencePortStub.getMongoStub().getFirst().getFileDate()).isNull(); + Assertions.assertThat(surveyUnitPersistencePortStub.getMongoStub().getFirst().getRecordDate()).isNotNull(); + Assertions.assertThat(surveyUnitPersistencePortStub.getMongoStub().getFirst().getExternalVariables()).isEmpty(); + + Assertions.assertThat(surveyUnitPersistencePortStub.getMongoStub().getFirst().getCollectedVariables()).hasSize(1); + Assertions.assertThat(surveyUnitPersistencePortStub.getMongoStub().getFirst().getCollectedVariables().getFirst().getIdVar()).isEqualTo(idVar); + Assertions.assertThat(surveyUnitPersistencePortStub.getMongoStub().getFirst().getCollectedVariables().getFirst().getIdLoop()).isEqualTo(idLoop); + Assertions.assertThat(surveyUnitPersistencePortStub.getMongoStub().getFirst().getCollectedVariables().getFirst().getIdParent()).isEqualTo(Constants.ROOT_GROUP_NAME); + Assertions.assertThat(surveyUnitPersistencePortStub.getMongoStub().getFirst().getCollectedVariables().getFirst().getValues()).hasSize(1); + Assertions.assertThat(surveyUnitPersistencePortStub.getMongoStub().getFirst().getCollectedVariables().getFirst().getValues().getFirst()).isEqualTo(editedValue); + + Assertions.assertThat(surveyUnitPersistencePortStub.getMongoStub().getFirst().getModifiedBy()).isNull(); + } + + @Test + void saveEditedTest_Forced() { + //GIVEN + surveyUnitPersistencePortStub.getMongoStub().clear(); + String campaignId = ID_CAMPAIGN_WITH_DDI; + String idQuest = ID_QUEST_WITH_DDI; + String idVar = "PRENOM_C"; + String idVar2 = "NB_SOEURS"; + String idLoop = "BOUCLE_VAL_ANNAISS_1"; + String editedValue = "NOT A INT"; + + //Variable 1 + List newVariables = new ArrayList<>(); + VariableInputDto variableInputDto = VariableInputDto.builder() + .variableName(idVar) + .idLoop(idLoop) + .variableStateInputDto(VariableStateInputDto.builder() + .state(DataState.EDITED) + .value(editedValue) + .build()) + .build(); + newVariables.add(variableInputDto); + + //Variable 2 + VariableInputDto variableInputDto2 = VariableInputDto.builder() + .variableName(idVar2) + .idLoop(idLoop) + .variableStateInputDto(VariableStateInputDto.builder() + .state(DataState.EDITED) + .value(editedValue) + .build()) + .build(); + newVariables.add(variableInputDto2); + + SurveyUnitInputDto surveyUnitInputDto = SurveyUnitInputDto.builder() + .campaignId(campaignId) + .mode(Mode.WEB) + .idQuestionnaire(idQuest) + .surveyUnitId(DEFAULT_ID_UE) + .collectedVariables(newVariables) + .build(); + + //WHEN + responseControllerStatic.saveEditedVariables(surveyUnitInputDto); + + //THEN + //EDITED document assertions + Assertions.assertThat(surveyUnitPersistencePortStub.getMongoStub()).hasSize(2); + Assertions.assertThat(surveyUnitPersistencePortStub.getMongoStub().getFirst().getIdCampaign()).isEqualTo(campaignId); + Assertions.assertThat(surveyUnitPersistencePortStub.getMongoStub().getFirst().getIdQuest()).isEqualTo(idQuest); + Assertions.assertThat(surveyUnitPersistencePortStub.getMongoStub().getFirst().getState()).isEqualTo(DataState.EDITED); + Assertions.assertThat(surveyUnitPersistencePortStub.getMongoStub().getFirst().getMode()).isEqualTo(Mode.WEB); + Assertions.assertThat(surveyUnitPersistencePortStub.getMongoStub().getFirst().getFileDate()).isNull(); + Assertions.assertThat(surveyUnitPersistencePortStub.getMongoStub().getFirst().getRecordDate()).isNotNull(); + Assertions.assertThat(surveyUnitPersistencePortStub.getMongoStub().getFirst().getExternalVariables()).isEmpty(); + + Assertions.assertThat(surveyUnitPersistencePortStub.getMongoStub().getFirst().getCollectedVariables()).hasSize(2); + Assertions.assertThat(surveyUnitPersistencePortStub.getMongoStub().getFirst().getCollectedVariables().getFirst().getIdVar()).isEqualTo(idVar); + Assertions.assertThat(surveyUnitPersistencePortStub.getMongoStub().getFirst().getCollectedVariables().getFirst().getIdLoop()).isEqualTo(idLoop); + Assertions.assertThat(surveyUnitPersistencePortStub.getMongoStub().getFirst().getCollectedVariables().getFirst().getIdParent()).isEqualTo(Constants.ROOT_GROUP_NAME); + Assertions.assertThat(surveyUnitPersistencePortStub.getMongoStub().getFirst().getCollectedVariables().getFirst().getValues()).hasSize(1); + Assertions.assertThat(surveyUnitPersistencePortStub.getMongoStub().getFirst().getCollectedVariables().getFirst().getValues().getFirst()).isEqualTo(editedValue); + Assertions.assertThat(surveyUnitPersistencePortStub.getMongoStub().getFirst().getModifiedBy()).isNull(); + + //FORCED document assertions + Assertions.assertThat(surveyUnitPersistencePortStub.getMongoStub().getLast().getIdCampaign()).isEqualTo(campaignId); + Assertions.assertThat(surveyUnitPersistencePortStub.getMongoStub().getLast().getIdQuest()).isEqualTo(idQuest); + Assertions.assertThat(surveyUnitPersistencePortStub.getMongoStub().getLast().getState()).isEqualTo(DataState.FORCED); + Assertions.assertThat(surveyUnitPersistencePortStub.getMongoStub().getLast().getMode()).isEqualTo(Mode.WEB); + Assertions.assertThat(surveyUnitPersistencePortStub.getMongoStub().getLast().getFileDate()).isNull(); + Assertions.assertThat(surveyUnitPersistencePortStub.getMongoStub().getLast().getRecordDate()).isNotNull(); + Assertions.assertThat(surveyUnitPersistencePortStub.getMongoStub().getLast().getExternalVariables()).isEmpty(); + + Assertions.assertThat(surveyUnitPersistencePortStub.getMongoStub().getLast().getCollectedVariables()).hasSize(1); + Assertions.assertThat(surveyUnitPersistencePortStub.getMongoStub().getLast().getCollectedVariables().getFirst().getIdVar()).isEqualTo(idVar2); + Assertions.assertThat(surveyUnitPersistencePortStub.getMongoStub().getLast().getCollectedVariables().getFirst().getIdLoop()).isEqualTo(idLoop); + Assertions.assertThat(surveyUnitPersistencePortStub.getMongoStub().getLast().getCollectedVariables().getFirst().getIdParent()).isEqualTo(Constants.ROOT_GROUP_NAME); + Assertions.assertThat(surveyUnitPersistencePortStub.getMongoStub().getLast().getCollectedVariables().getFirst().getValues()).hasSize(1); + Assertions.assertThat(surveyUnitPersistencePortStub.getMongoStub().getLast().getCollectedVariables().getFirst().getValues().getFirst()).isNotNull().isEmpty(); + Assertions.assertThat(surveyUnitPersistencePortStub.getMongoStub().getLast().getModifiedBy()).isNull(); + } + @Test + void saveEditedTest_No_Metadata_Error() { + //GIVEN + surveyUnitPersistencePortStub.getMongoStub().clear(); + String campaignId = "TEST"; + String idVar = "PRENOM_C"; + String idLoop = "BOUCLE_VAL_ANNAISS_1"; + String editedValue = "TESTVALUE"; + + //Variable 1 + List newVariables = new ArrayList<>(); + VariableInputDto variableInputDto = VariableInputDto.builder() + .variableName(idVar) + .idLoop(idLoop) + .variableStateInputDto(VariableStateInputDto.builder() + .state(DataState.EDITED) + .value(editedValue) + .build()) + .build(); + newVariables.add(variableInputDto); + + SurveyUnitInputDto surveyUnitInputDto = SurveyUnitInputDto.builder() + .campaignId(campaignId) + .mode(Mode.WEB) + .idQuestionnaire(DEFAULT_ID_QUEST) + .surveyUnitId(DEFAULT_ID_UE) + .collectedVariables(newVariables) + .build(); + + Assertions.assertThat( + responseControllerStatic.saveEditedVariables( + surveyUnitInputDto + ).getStatusCode() + ).isEqualTo(HttpStatusCode.valueOf(404)); + } + + @Test + void saveTest_With_Collected_State_Error(){ + //GIVEN + surveyUnitPersistencePortStub.getMongoStub().clear(); + String idVar = "PRENOM_C"; + String idLoop = "BOUCLE_VAL_ANNAISS_1"; + String editedValue = "TESTVALUE"; + + //Variable 1 + List newVariables = new ArrayList<>(); + VariableInputDto variableInputDto = VariableInputDto.builder() + .variableName(idVar) + .idLoop(idLoop) + .variableStateInputDto(VariableStateInputDto.builder() + .state(DataState.COLLECTED) //Collected instead of EDITED + .value(editedValue) + .build()) + .build(); + newVariables.add(variableInputDto); + + SurveyUnitInputDto surveyUnitInputDto = SurveyUnitInputDto.builder() + .campaignId(ID_CAMPAIGN_WITH_DDI) + .mode(Mode.WEB) + .idQuestionnaire(DEFAULT_ID_QUEST) + .surveyUnitId(DEFAULT_ID_UE) + .collectedVariables(newVariables) + .build(); + + Assertions.assertThat(responseControllerStatic.saveEditedVariables(surveyUnitInputDto).getStatusCode()).isEqualTo(HttpStatusCode.valueOf(400)); + } } diff --git a/src/test/java/fr/insee/genesis/domain/model/surveyunit/SurveyUnitModelTest.java b/src/test/java/fr/insee/genesis/domain/model/surveyunit/SurveyUnitModelTest.java index 2ef657d0..7e99578f 100644 --- a/src/test/java/fr/insee/genesis/domain/model/surveyunit/SurveyUnitModelTest.java +++ b/src/test/java/fr/insee/genesis/domain/model/surveyunit/SurveyUnitModelTest.java @@ -37,7 +37,7 @@ public void toJSONTest() throws JsonProcessingException { objectMapper.findAndRegisterModules(); Assertions.assertEquals( - objectMapper.readTree("{\"idQuest\":\"TESTIDQUEST\",\"idCampaign\":\"TESTIDCAMPAIGN\",\"idUE\":\"TESTIDUE\",\"state\":\"COLLECTED\",\"mode\":\"WEB\",\"recordDate\":\"2000-01-01T12:00\",\"fileDate\":\"2000-01-01T12:00\",\"collectedVariables\":[{\"idVar\":\"TESTIDVAR\",\"values\":[\"V1\",\"V2\"],\"idLoop\":\"TESTIDLOOP\",\"idParent\":\"TESTIDPARENT\"}],\"externalVariables\":[{\"idVar\":\"TESTIDVAR\",\"values\":[\"V1\",\"V2\"]}]}"), + objectMapper.readTree("{\"idQuest\":\"TESTIDQUEST\",\"idCampaign\":\"TESTIDCAMPAIGN\",\"idUE\":\"TESTIDUE\",\"state\":\"COLLECTED\",\"mode\":\"WEB\",\"recordDate\":\"2000-01-01T12:00\",\"fileDate\":\"2000-01-01T12:00\",\"collectedVariables\":[{\"idVar\":\"TESTIDVAR\",\"values\":[\"V1\",\"V2\"],\"idLoop\":\"TESTIDLOOP\",\"idParent\":\"TESTIDPARENT\"}],\"externalVariables\":[{\"idVar\":\"TESTIDVAR\",\"values\":[\"V1\",\"V2\"]}], \"modifiedBy\": null}"), objectMapper.readTree(objectMapper.writeValueAsString(surveyUnitModel)) ); } diff --git a/src/test/java/fr/insee/genesis/stubs/ConfigStub.java b/src/test/java/fr/insee/genesis/stubs/ConfigStub.java index 11c79ee4..6d4f1c0c 100644 --- a/src/test/java/fr/insee/genesis/stubs/ConfigStub.java +++ b/src/test/java/fr/insee/genesis/stubs/ConfigStub.java @@ -27,4 +27,9 @@ public String getSpecFolderSource() { @Override public String getLogFolder(){return LOG_FOLDER;} + + @Override + public String getAuthType() { + return "NONE"; + } }