Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
48495ec
Add Perret writing service
alexisszmundy Dec 27, 2024
1479298
Add tests + get user identifier
alexisszmundy Dec 27, 2024
77d2b3c
Fix variable state dto hour format
alexisszmundy Dec 27, 2024
dd7dada
external variables management
alexisszmundy Dec 27, 2024
a82dddf
Renamed userIdentifier by modifiedBy
alexisszmundy Dec 27, 2024
e8e5173
Update SurveyUnitModelTest.java
alexisszmundy Dec 30, 2024
cf3141a
Refactor
alicela Jan 21, 2025
4674f00
refactor: Removed TODOs
alexisszmundy Jan 21, 2025
1e325a9
build: Update maven.yml
alexisszmundy Jan 21, 2025
a7d7a1c
build: Update maven.yml
alexisszmundy Jan 21, 2025
dccbd54
Refactor
alicela Jan 21, 2025
cba0fae
Merge branch 'devEditedVariableWrite' of https://github.com/InseeFr/G…
alicela Jan 21, 2025
9d63884
refactor: change suDtos
alexisszmundy Jan 21, 2025
670a78a
build: Update maven.yml
alexisszmundy Jan 21, 2025
d5b86ea
build: Update maven.yml
alexisszmundy Jan 21, 2025
1bc7c5b
ci: Update maven.yml
alexisszmundy Jan 21, 2025
5d8ff81
ci: Update maven.yml
alexisszmundy Jan 21, 2025
5dbcaed
ci: Update maven.yml
alexisszmundy Jan 21, 2025
c5e5419
ci: revert
alexisszmundy Jan 21, 2025
e1fdb10
Refactor : use different Dtos to import changes in Genesis
loichenninger Jan 22, 2025
bd54a18
Merge branch 'main' into devEditedVariableWrite
alexisszmundy Jan 23, 2025
01a5f3e
Merge branch 'main' into devEditedVariableWrite
alexisszmundy Jan 23, 2025
e984033
fix(tests): Update MainDefinitions with right constructor
alexisszmundy Jan 23, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/maven.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/fr/insee/genesis/Constants.java
Original file line number Diff line number Diff line change
Expand Up @@ -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 = "";
Expand Down
3 changes: 3 additions & 0 deletions src/main/java/fr/insee/genesis/configuration/Config.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
Original file line number Diff line number Diff line change
@@ -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<VariableInputDto> collectedVariables;

}
Original file line number Diff line number Diff line change
@@ -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;
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Original file line number Diff line number Diff line change
@@ -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;

}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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" )
Expand All @@ -73,20 +76,24 @@ public class ResponseController {
private final LunaticJsonRawDataApiPort lunaticJsonRawDataApiPort;
private final FileUtils fileUtils;
private final ControllerUtils controllerUtils;
private final AuthUtils authUtils;


public ResponseController(SurveyUnitApiPort surveyUnitService,
SurveyUnitQualityService surveyUnitQualityService,
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
Expand Down Expand Up @@ -230,7 +237,7 @@ public ResponseEntity<Object> saveResponsesFromAllCampaignFolders(){
try {
List<Mode> 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());
Expand Down Expand Up @@ -360,6 +367,62 @@ public ResponseEntity<List<SurveyUnitSimplified>> getLatestForUEList(@RequestPar
return ResponseEntity.ok(results);
}

@Operation(summary = "Save edited variables",
description = "Save edited variables document into database")
@PostMapping(path = "/save-edited")
public ResponseEntity<Object> saveEditedVariables(
@RequestBody SurveyUnitInputDto surveyUnitInputDto
){
//Parse metadata
//Try to look for DDI first, if no DDI found looks for lunatic components
List<GenesisError> 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<String> absentCollectedVariableNames =
surveyUnitQualityService.checkVariablesPresentInMetadata(surveyUnitInputDto.getCollectedVariables(),
variablesMap);
// List<String> 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<SurveyUnitModel> 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

/**
Expand Down Expand Up @@ -579,10 +642,9 @@ private ResponseEntity<Object> 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();
}

Expand Down
33 changes: 33 additions & 0 deletions src/main/java/fr/insee/genesis/controller/utils/AuthUtils.java
Original file line number Diff line number Diff line change
@@ -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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ public class SurveyUnitModel {
private List<CollectedVariable> collectedVariables;
private List<Variable> externalVariables;

private String modifiedBy;

public SurveyUnitModel(String idUE, Mode mode) {
this.idUE = idUE;
this.mode = mode;
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -48,4 +51,8 @@ public interface SurveyUnitApiPort {
List<CampaignWithQuestionnaire> findCampaignsWithQuestionnaires();

List<QuestionnaireWithCampaign> findQuestionnairesWithCampaigns();
}

List<SurveyUnitModel> parseEditedVariables(SurveyUnitInputDto surveyUnitInputDto,
String userIdentifier,
VariablesMap variablesMap) throws GenesisException;
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,39 @@
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;

/**
* This service is used to ensure data quality processes
*/
@Service
public class SurveyUnitQualityService {
public void verifySurveyUnits(List<SurveyUnitModel> suDtos, VariablesMap variablesMap) {
DataVerifier.verifySurveyUnits(suDtos,variablesMap);
public void verifySurveyUnits(List<SurveyUnitModel> 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 <strong>absent</strong> in metadata
*/
public List<String> checkVariablesPresentInMetadata(List<VariableInputDto> variableInputDtos, VariablesMap variablesMap) {
List<String> absentVariableNames = new ArrayList<>();

for(VariableInputDto variableInputDto : variableInputDtos){
if(!variablesMap.hasVariable(variableInputDto.getVariableName())){
absentVariableNames.add(variableInputDto.getVariableName());
}
}

return absentVariableNames;
}
}
Loading
Loading