diff --git a/.github/workflows/docker.yaml b/.github/workflows/docker.yaml
index c9fe9de1c..d510a114c 100644
--- a/.github/workflows/docker.yaml
+++ b/.github/workflows/docker.yaml
@@ -3,7 +3,8 @@ name: Build snapshot docker image
on:
push:
branches-ignore:
- - main
+ - * # main
+ # turned off for now (needs secrets renewal)
jobs:
build-snapshot:
diff --git a/src/main/java/fr/insee/genesis/controller/exception/ExceptionController.java b/src/main/java/fr/insee/genesis/controller/exception/ExceptionController.java
new file mode 100644
index 000000000..0be8fdb55
--- /dev/null
+++ b/src/main/java/fr/insee/genesis/controller/exception/ExceptionController.java
@@ -0,0 +1,75 @@
+package fr.insee.genesis.controller.exception;
+
+import fr.insee.genesis.exceptions.*;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ProblemDetail;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+
+/**
+ * This controller uses Spring's ControllerAdvice annotation to intercept exceptions.
+ * It implements the RFC 9457 by returning
+ * Spring's ProblemDetail object.
+ */
+@ControllerAdvice
+@Slf4j
+public class ExceptionController {
+
+ // Note: No handler for uncaught Exception.class for now since it breaks soms tests.
+
+ @ExceptionHandler
+ public ProblemDetail handleGenericGenesisException(GenesisException genesisException) {
+ log.error("GenesisException: {}", genesisException.getMessage(), genesisException);
+ return ProblemDetail.forStatusAndDetail(
+ resolveHttpCode(genesisException.getStatus()),
+ genesisException.getMessage());
+ }
+
+ /** Returns the corresponding http status, or 500 if the given code does not match a http status. */
+ private static HttpStatus resolveHttpCode(int statusCode) {
+ HttpStatus httpStatus = HttpStatus.resolve(statusCode);
+ return httpStatus != null ? httpStatus : HttpStatus.INTERNAL_SERVER_ERROR;
+ }
+
+ @ExceptionHandler(InvalidDateIntervalException.class)
+ public ProblemDetail handleInvalidDateIntervalException(InvalidDateIntervalException e) {
+ log.error("InvalidDateIntervalException: {}", e.getMessage());
+ return ProblemDetail.forStatusAndDetail(
+ HttpStatus.BAD_REQUEST,
+ e.getMessage());
+ }
+
+ @ExceptionHandler(ModesConflictException.class)
+ public ProblemDetail handleModesConflictException(ModesConflictException e) {
+ log.error("ModesConflictException: {}", e.getMessage());
+ return ProblemDetail.forStatusAndDetail(
+ HttpStatus.CONFLICT,
+ e.getMessage());
+ }
+
+ @ExceptionHandler(UndefinedModesException.class)
+ public ProblemDetail handleUndefinedModesException(UndefinedModesException e) {
+ log.error("UndefinedModesException: {}", e.getMessage());
+ return ProblemDetail.forStatusAndDetail(
+ HttpStatus.NOT_FOUND,
+ e.getMessage());
+ }
+
+ @ExceptionHandler(UndefinedMetadataException.class)
+ public ProblemDetail handleUndefinedMetadataException(UndefinedMetadataException e) {
+ log.error("UndefinedMetadataException: {}", e.getMessage());
+ return ProblemDetail.forStatusAndDetail(
+ HttpStatus.NOT_FOUND,
+ e.getMessage());
+ }
+
+ @ExceptionHandler(InvalidMetadataException.class)
+ public ProblemDetail handleInvalidMetadataException(InvalidMetadataException e) {
+ log.error("InvalidMetadataException: {}", e.getMessage());
+ return ProblemDetail.forStatusAndDetail(
+ HttpStatus.BAD_REQUEST,
+ e.getMessage());
+ }
+
+}
diff --git a/src/main/java/fr/insee/genesis/controller/rest/responses/InterrogationController.java b/src/main/java/fr/insee/genesis/controller/rest/responses/InterrogationController.java
index 157d38e16..697a377fb 100644
--- a/src/main/java/fr/insee/genesis/controller/rest/responses/InterrogationController.java
+++ b/src/main/java/fr/insee/genesis/controller/rest/responses/InterrogationController.java
@@ -15,6 +15,7 @@
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
+import java.time.Instant;
import java.time.LocalDateTime;
import java.util.List;
@@ -55,17 +56,17 @@ public ResponseEntity> getAllInterrogationIdsByCollectionI
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
@Parameter(
description = "sinceDate",
- schema = @Schema(type = "string", format = "date-time", example = "2026-01-01T00:00:00")
+ schema = @Schema(type = "string", format = "date-time", example = "2026-01-01T00:00:00Z")
)
- LocalDateTime start,
+ Instant start,
@RequestParam("end")
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
@Parameter(
description = "untilDate",
- schema = @Schema(type = "string", format = "date-time", example = "2026-01-31T23:59:59")
+ schema = @Schema(type = "string", format = "date-time", example = "2026-01-31T23:59:59Z")
)
- LocalDateTime end) {
+ Instant end) {
List responses = surveyUnitService.findDistinctInterrogationIdsByCollectionInstrumentIdAndRecordDateBetween(collectionInstrumentId, start,end);
return ResponseEntity.ok(responses);
}
diff --git a/src/main/java/fr/insee/genesis/controller/rest/responses/RawResponseController.java b/src/main/java/fr/insee/genesis/controller/rest/responses/RawResponseController.java
index e692852e3..f79efe4cb 100644
--- a/src/main/java/fr/insee/genesis/controller/rest/responses/RawResponseController.java
+++ b/src/main/java/fr/insee/genesis/controller/rest/responses/RawResponseController.java
@@ -15,6 +15,7 @@
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import jakarta.validation.Valid;
+import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
@@ -43,23 +44,16 @@
@Slf4j
@Controller
+@RequiredArgsConstructor
public class RawResponseController {
private static final String SUCCESS_MESSAGE = "Interrogation %s saved";
private static final String INTERROGATION_ID = "interrogationId";
- public static final String NB_DOCS_WITH_FORMATTED = "%d document(s) processed, including %d FORMATTED after data verification for collectionInstrumentId %s";
- public static final String NB_DOCS = "%d document(s) processed for collectionInstrumentId %s";
+
private final LunaticJsonRawDataApiPort lunaticJsonRawDataApiPort;
private final RawResponseApiPort rawResponseApiPort;
private final RawResponseInputRepository rawRepository;
-
- public RawResponseController(LunaticJsonRawDataApiPort lunaticJsonRawDataApiPort, RawResponseApiPort rawResponseApiPort, RawResponseInputRepository rawRepository) {
- this.lunaticJsonRawDataApiPort = lunaticJsonRawDataApiPort;
- this.rawResponseApiPort = rawResponseApiPort;
- this.rawRepository = rawRepository;
- }
-
@Operation(summary = "Save lunatic json data from one interrogation in Genesis Database")
@PutMapping(path = "/responses/raw/lunatic-json/save")
@PreAuthorize("hasRole('COLLECT_PLATFORM')")
@@ -118,11 +112,8 @@ public ResponseEntity processRawResponses(
log.info("Try to process raw responses for collectionInstrumentId {} and {} interrogationIds", collectionInstrumentId, interrogationIdList.size());
List errors = new ArrayList<>();
try {
- DataProcessResult result = rawResponseApiPort.processRawResponses(collectionInstrumentId, interrogationIdList, errors);
- return result.formattedDataCount() == 0 ?
- ResponseEntity.ok(NB_DOCS.formatted(result.dataCount(), collectionInstrumentId))
- : ResponseEntity.ok(NB_DOCS_WITH_FORMATTED
- .formatted(result.dataCount(), result.formattedDataCount(), collectionInstrumentId));
+ DataProcessResult result = rawResponseApiPort.processRawResponsesByInterrogationIds(collectionInstrumentId, interrogationIdList, errors);
+ return ResponseEntity.ok(result.message(collectionInstrumentId));
} catch (GenesisException e) {
return ResponseEntity.status(e.getStatus()).body(e.getMessage());
}
@@ -140,11 +131,8 @@ public ResponseEntity processRawResponsesByCollectionInstrumentId(
) {
log.info("Try to process raw responses for collectionInstrumentId {}", collectionInstrumentId);
try {
- DataProcessResult result = rawResponseApiPort.processRawResponses(collectionInstrumentId);
- return result.formattedDataCount() == 0 ?
- ResponseEntity.ok(NB_DOCS.formatted(result.dataCount(), collectionInstrumentId))
- : ResponseEntity.ok(NB_DOCS_WITH_FORMATTED
- .formatted(result.dataCount(), result.formattedDataCount(), collectionInstrumentId));
+ DataProcessResult result = rawResponseApiPort.processRawResponsesByInterrogationIds(collectionInstrumentId);
+ return ResponseEntity.ok(result.message(collectionInstrumentId));
} catch (GenesisException e) {
return ResponseEntity.status(e.getStatus()).body(e.getMessage());
}
@@ -183,7 +171,7 @@ public ResponseEntity getJsonRawData(
@RequestParam("campaignName") String campaignName,
@RequestParam(value = "mode") Mode modeSpecified
) {
- List data = lunaticJsonRawDataApiPort.getRawData(campaignName, modeSpecified, List.of(interrogationId));
+ List data = lunaticJsonRawDataApiPort.getRawDataByQuestionnaireId(campaignName, modeSpecified, List.of(interrogationId));
return ResponseEntity.ok(data.getFirst());
}
@@ -201,7 +189,7 @@ public ResponseEntity processJsonRawData(
List errors = new ArrayList<>();
try {
- DataProcessResult result = lunaticJsonRawDataApiPort.processRawData(campaignName, interrogationIdList, errors);
+ DataProcessResult result = lunaticJsonRawDataApiPort.processRawDataByInterrogationIds(campaignName, interrogationIdList, errors);
return result.formattedDataCount() == 0 ?
ResponseEntity.ok("%d document(s) processed".formatted(result.dataCount()))
: ResponseEntity.ok("%d document(s) processed, including %d FORMATTED after data verification"
diff --git a/src/main/java/fr/insee/genesis/controller/rest/responses/RawResponseReprocessController.java b/src/main/java/fr/insee/genesis/controller/rest/responses/RawResponseReprocessController.java
new file mode 100644
index 000000000..2f9d87250
--- /dev/null
+++ b/src/main/java/fr/insee/genesis/controller/rest/responses/RawResponseReprocessController.java
@@ -0,0 +1,102 @@
+package fr.insee.genesis.controller.rest.responses;
+
+import fr.insee.genesis.domain.model.surveyunit.rawdata.DataProcessResult;
+import fr.insee.genesis.domain.model.surveyunit.rawdata.RawDataModelType;
+import fr.insee.genesis.domain.ports.api.ReprocessRawResponseApiPort;
+import fr.insee.genesis.exceptions.GenesisException;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.format.annotation.DateTimeFormat;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+import java.time.Instant;
+
+@Controller
+@RequiredArgsConstructor
+@Slf4j
+public class RawResponseReprocessController {
+
+ private final ReprocessRawResponseApiPort reprocessRawResponseApiPort;
+
+ @Operation(summary = "Reprocess raw response of a collection instrument.")
+ @PostMapping(path = "/raw-responses/{collectionInstrumentId}/reprocess")
+ @PreAuthorize("hasRole('ADMIN')")
+ public ResponseEntity reProcessRawResponsesByCollectionInstrumentId(
+ @Parameter(
+ description = "Id of the collection instrument (old questionnaireId)",
+ example = "ENQTEST2025X00")
+ @PathVariable("collectionInstrumentId")
+ String collectionInstrumentId,
+
+ @Parameter(
+ description = "Extract since",
+ schema = @Schema(type = "string", format = "date-time", example = "2026-01-01T00:00:00Z")
+ )
+ @RequestParam(value = "sinceDate", required = false)
+ @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
+ Instant sinceDate,
+
+ @Parameter(
+ description = "Extract until",
+ schema = @Schema(type = "string", format = "date-time", example = "2026-02-02T00:00:00Z")
+ )
+ @RequestParam(value = "endDate", required = false)
+ @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
+ Instant endDate
+ ) throws GenesisException {
+
+ DataProcessResult result = reprocessRawResponseApiPort.reprocessRawResponses(
+ RawDataModelType.FILIERE,
+ collectionInstrumentId,
+ sinceDate,
+ endDate);
+
+ return ResponseEntity.ok(result.message(collectionInstrumentId));
+ }
+
+ @Operation(summary = "Reprocess Lunatic raw data for a questionnaire model. " +
+ "**Note**: Lunatic raw data is the legacy format of raw responses.")
+ @PostMapping(path = "/responses/raw/lunatic-json/{questionnaireId}/reprocess")
+ @PreAuthorize("hasRole('ADMIN')")
+ public ResponseEntity reProcessJsonRawDataByQuestionnaireId(
+ @Parameter(
+ description = "Questionnaire model id (old name for collection instrument id).",
+ example = "ENQTEST2025X00")
+ @PathVariable("questionnaireId")
+ String collectionInstrumentId, // 'questionnaireId' is the legacy name for 'collectionInstrumentId'
+
+ @Parameter(
+ description = "Extract since",
+ schema = @Schema(type = "string", format = "date-time", example = "2026-01-01T00:00:00Z")
+ )
+ @RequestParam(value = "sinceDate", required = false)
+ @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
+ Instant sinceDate,
+
+ @Parameter(
+ description = "Extract until",
+ schema = @Schema(type = "string", format = "date-time", example = "2026-02-02T00:00:00Z")
+ )
+ @RequestParam(value = "endDate", required = false)
+ @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
+ Instant endDate
+ ) throws GenesisException {
+
+ DataProcessResult result = reprocessRawResponseApiPort.reprocessRawResponses(
+ RawDataModelType.LEGACY,
+ collectionInstrumentId,
+ sinceDate,
+ endDate);
+
+ return ResponseEntity.ok(result.message(collectionInstrumentId));
+ }
+
+}
diff --git a/src/main/java/fr/insee/genesis/controller/utils/ControllerUtils.java b/src/main/java/fr/insee/genesis/controller/utils/ControllerUtils.java
index 83051a4e1..00398e9f5 100644
--- a/src/main/java/fr/insee/genesis/controller/utils/ControllerUtils.java
+++ b/src/main/java/fr/insee/genesis/controller/utils/ControllerUtils.java
@@ -1,16 +1,18 @@
package fr.insee.genesis.controller.utils;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
+import fr.insee.genesis.domain.model.surveyunit.Mode;
+import fr.insee.genesis.exceptions.ModesConflictException;
+import fr.insee.genesis.exceptions.UndefinedModesException;
+import fr.insee.genesis.infrastructure.utils.FileUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
-import fr.insee.genesis.domain.model.surveyunit.Mode;
-import fr.insee.genesis.exceptions.GenesisException;
-import fr.insee.genesis.infrastructure.utils.FileUtils;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+// Note: this class should be moved in the domain service layer.
@Component
@Slf4j
@@ -23,25 +25,23 @@ public ControllerUtils(FileUtils fileUtils) {
this.fileUtils = fileUtils;
}
-
/**
* If a mode is specified, we treat only this mode.
- * If no mode is specified, we treat all modes in the campaign.
+ * If no mode is specified, we treat all modes in the questionnaireId.
* If no mode is specified and no specs are found, we return an error
- * @param campaign campaign id to get modes
+ * @param questionnaireId questionnaireId id to get modes
* @param modeSpecified a Mode to use, null if we want all modes available
* @return a list with the mode in modeSpecified or all modes if null
- * @throws GenesisException if error in specs structure
*/
- public List getModesList(String campaign, Mode modeSpecified) throws GenesisException {
+ public List getModesList(String questionnaireId, Mode modeSpecified) {
if (modeSpecified != null){
return Collections.singletonList(modeSpecified);
}
List modes = new ArrayList<>();
- String specFolder = fileUtils.getSpecFolder(campaign);
+ String specFolder = fileUtils.getSpecFolder(questionnaireId);
List modeSpecFolders = fileUtils.listFolders(specFolder);
if (modeSpecFolders.isEmpty()) {
- throw new GenesisException(404, "No specification folder found " + specFolder);
+ throw new UndefinedModesException("No specification folder found " + specFolder);
}
for(String modeSpecFolder : modeSpecFolders){
if(Mode.getEnumFromModeName(modeSpecFolder) == null) {
@@ -51,9 +51,18 @@ public List getModesList(String campaign, Mode modeSpecified) throws Genes
modes.add(Mode.getEnumFromModeName(modeSpecFolder));
}
if (modes.contains(Mode.F2F) && modes.contains(Mode.TEL)) {
- throw new GenesisException(409, "Cannot treat simultaneously TEL and FAF modes");
+ throw new ModesConflictException("Cannot treat simultaneously TEL and FAF modes");
}
return modes;
}
+ /**
+ * Returns the applicable modes for the collection instrument with the given identifier.
+ * @param collectionInstrumentId Collection instrument identifier.
+ * @return A list of modes.
+ */
+ public List getModesList(String collectionInstrumentId) {
+ return getModesList(collectionInstrumentId, null);
+ }
+
}
diff --git a/src/main/java/fr/insee/genesis/domain/model/context/DataProcessingContextModel.java b/src/main/java/fr/insee/genesis/domain/model/context/DataProcessingContextModel.java
index d0a147469..20775dca2 100644
--- a/src/main/java/fr/insee/genesis/domain/model/context/DataProcessingContextModel.java
+++ b/src/main/java/fr/insee/genesis/domain/model/context/DataProcessingContextModel.java
@@ -17,18 +17,22 @@
@NoArgsConstructor
@AllArgsConstructor
public class DataProcessingContextModel {
+
+ /** (Added to the class only to remove a warning) */
@Id
- private ObjectId id; //Used to remove warning
+ private ObjectId id;
@Deprecated(forRemoval = true)
private String partitionId;
- private String collectionInstrumentId; //QuestionnaireId
+ /** New name of legacy 'questionnaireId' property. */
+ private String collectionInstrumentId;
private LocalDateTime lastExecution;
List kraftwerkExecutionScheduleList;
+ /** Determines if some review service must be called during the process. */
boolean withReview;
public ScheduleDto toScheduleDto(){
@@ -39,4 +43,5 @@ public ScheduleDto toScheduleDto(){
.kraftwerkExecutionScheduleList(kraftwerkExecutionScheduleList)
.build();
}
+
}
diff --git a/src/main/java/fr/insee/genesis/domain/model/surveyunit/rawdata/DataProcessResult.java b/src/main/java/fr/insee/genesis/domain/model/surveyunit/rawdata/DataProcessResult.java
index b8191dd03..e7eccec1c 100644
--- a/src/main/java/fr/insee/genesis/domain/model/surveyunit/rawdata/DataProcessResult.java
+++ b/src/main/java/fr/insee/genesis/domain/model/surveyunit/rawdata/DataProcessResult.java
@@ -4,5 +4,31 @@
import java.util.List;
-public record DataProcessResult(int dataCount, int formattedDataCount, List errors) {
+public record DataProcessResult(
+ int dataCount,
+ int formattedDataCount,
+ List errors) {
+
+ public String message(String collectionInstrumentId) {
+ return String.format("%s%s%s.",
+ interrogationCountMessage(dataCount),
+ formattedCountMessage(formattedDataCount),
+ collectionIdMessage(collectionInstrumentId));
+ }
+
+ private static String interrogationCountMessage(int processedInterrogationsCount) {
+ boolean plural = processedInterrogationsCount > 1;
+ return "%d interrogation%s processed".formatted(processedInterrogationsCount, plural ? "s" : "");
+ }
+
+ private static String collectionIdMessage(String collectionInstrumentId) {
+ return " for collectionInstrumentId '%s'".formatted(collectionInstrumentId);
+ }
+
+ private static String formattedCountMessage(int formattedCount) {
+ if (formattedCount == 0)
+ return "";
+ return " (including %d FORMATTED after data verification)".formatted(formattedCount);
+ }
+
}
diff --git a/src/main/java/fr/insee/genesis/domain/model/surveyunit/rawdata/RawDataModelType.java b/src/main/java/fr/insee/genesis/domain/model/surveyunit/rawdata/RawDataModelType.java
index adb8a88cd..9ecc12db9 100644
--- a/src/main/java/fr/insee/genesis/domain/model/surveyunit/rawdata/RawDataModelType.java
+++ b/src/main/java/fr/insee/genesis/domain/model/surveyunit/rawdata/RawDataModelType.java
@@ -1,5 +1,20 @@
package fr.insee.genesis.domain.model.surveyunit.rawdata;
+/** Format of raw data to be imported into the data storage. */
public enum RawDataModelType {
- DEFAULT, FILIERE
+
+ /** Legacy format of raw data ('Lunatic'). */
+ LEGACY,
+
+ /** 'Filière' raw response model. */
+ FILIERE;
+
+ @Override
+ public String toString() {
+ return switch (this) {
+ case LEGACY -> "LEGACY (Lunatic)";
+ case FILIERE -> "FILIERE raw responses";
+ };
+ }
+
}
diff --git a/src/main/java/fr/insee/genesis/domain/ports/api/LunaticJsonRawDataApiPort.java b/src/main/java/fr/insee/genesis/domain/ports/api/LunaticJsonRawDataApiPort.java
index 2031d80d7..8d3629ab3 100644
--- a/src/main/java/fr/insee/genesis/domain/ports/api/LunaticJsonRawDataApiPort.java
+++ b/src/main/java/fr/insee/genesis/domain/ports/api/LunaticJsonRawDataApiPort.java
@@ -11,8 +11,8 @@
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
-import java.time.LocalDateTime;
import java.time.Instant;
+import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -20,9 +20,8 @@
public interface LunaticJsonRawDataApiPort {
void save(LunaticJsonRawDataModel rawData);
- List getRawData(String campaignName, Mode mode, List interrogationIdList);
List getRawDataByQuestionnaireId(String questionnaireId, Mode mode, List interrogationIdList);
- List convertRawData(List rawData, VariablesMap variablesMap);
+
List getUnprocessedDataIds();
Set getUnprocessedDataQuestionnaireIds();
void updateProcessDates(List surveyUnitModels);
@@ -33,8 +32,7 @@ public interface LunaticJsonRawDataApiPort {
List getRawDataByInterrogationId(String interrogationId);
- @Deprecated(since = "1.13.0")
- DataProcessResult processRawData(String campaignName, List interrogationIdList, List errors) throws GenesisException;
+ DataProcessResult processRawDataByInterrogationIds(String campaignName, List interrogationIdList, List errors) throws GenesisException;
DataProcessResult processRawData(String collectionInstrumentId) throws GenesisException;
diff --git a/src/main/java/fr/insee/genesis/domain/ports/api/RawResponseApiPort.java b/src/main/java/fr/insee/genesis/domain/ports/api/RawResponseApiPort.java
index 464295a8f..2e070f44d 100644
--- a/src/main/java/fr/insee/genesis/domain/ports/api/RawResponseApiPort.java
+++ b/src/main/java/fr/insee/genesis/domain/ports/api/RawResponseApiPort.java
@@ -1,7 +1,5 @@
package fr.insee.genesis.domain.ports.api;
-import fr.insee.bpm.metadata.model.VariablesMap;
-import fr.insee.genesis.domain.model.surveyunit.Mode;
import fr.insee.genesis.domain.model.surveyunit.SurveyUnitModel;
import fr.insee.genesis.domain.model.surveyunit.rawdata.DataProcessResult;
import fr.insee.genesis.domain.model.surveyunit.rawdata.RawResponseModel;
@@ -16,11 +14,9 @@
public interface RawResponseApiPort {
- List getRawResponses(String collectionInstrumentId, Mode mode, List interrogationIdList);
- List getRawResponsesByInterrogationID(String interrogationId);
- DataProcessResult processRawResponses(String collectionInstrumentId, List interrogationIdList, List errors) throws GenesisException;
- DataProcessResult processRawResponses(String collectionInstrumentId) throws GenesisException;
- List convertRawResponse(List rawResponses, VariablesMap variablesMap);
+ DataProcessResult processRawResponsesByInterrogationIds(String collectionInstrumentId, List interrogationIdList, List errors) throws GenesisException;
+ DataProcessResult processRawResponsesByInterrogationIds(String collectionInstrumentId) throws GenesisException;
+
List getUnprocessedCollectionInstrumentIds();
void updateProcessDates(List surveyUnitModels);
Page findRawResponseDataByCampaignIdAndDate(String campaignId, Instant startDate, Instant endDate, Pageable pageable);
diff --git a/src/main/java/fr/insee/genesis/domain/ports/api/ReprocessRawResponseApiPort.java b/src/main/java/fr/insee/genesis/domain/ports/api/ReprocessRawResponseApiPort.java
new file mode 100644
index 000000000..c379ed637
--- /dev/null
+++ b/src/main/java/fr/insee/genesis/domain/ports/api/ReprocessRawResponseApiPort.java
@@ -0,0 +1,26 @@
+package fr.insee.genesis.domain.ports.api;
+
+import fr.insee.genesis.domain.model.surveyunit.rawdata.DataProcessResult;
+import fr.insee.genesis.domain.model.surveyunit.rawdata.RawDataModelType;
+import fr.insee.genesis.exceptions.GenesisException;
+
+import java.time.Instant;
+
+public interface ReprocessRawResponseApiPort {
+
+ /**
+ * Reprocesses raw data of the collection that correspond to the given identifier.
+ * An optional date interval can be given to reprocess a subset of the collection.
+ * @param rawDataModelType {@link RawDataModelType}
+ * @param collectionInstrumentId Collection instrument identifier.
+ * @param sinceDate Start of the date interval.
+ * @param endDate End of the date interval.
+ * @return Data processing result record.
+ * @see DataProcessResult
+ */
+ DataProcessResult reprocessRawResponses(
+ RawDataModelType rawDataModelType,
+ String collectionInstrumentId, Instant sinceDate, Instant endDate)
+ throws GenesisException;
+
+}
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 7362cc512..77769696d 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,16 +1,13 @@
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.QuestionnaireWithCampaign;
-import fr.insee.genesis.controller.dto.SurveyUnitDto;
-import fr.insee.genesis.controller.dto.SurveyUnitInputDto;
-import fr.insee.genesis.controller.dto.SurveyUnitSimplifiedDto;
+import fr.insee.genesis.controller.dto.*;
import fr.insee.genesis.domain.model.surveyunit.InterrogationId;
import fr.insee.genesis.domain.model.surveyunit.Mode;
import fr.insee.genesis.domain.model.surveyunit.SurveyUnitModel;
import fr.insee.genesis.exceptions.GenesisException;
+import java.time.Instant;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Set;
@@ -52,7 +49,7 @@ List findSimplifiedByCollectionInstrumentIdAndInterroga
List findDistinctInterrogationIdsByQuestionnaireIdAndDateAfter(String questionnaireId, LocalDateTime since);
- List findDistinctInterrogationIdsByCollectionInstrumentIdAndRecordDateBetween(String collectionInstrumentId, LocalDateTime start, LocalDateTime end);
+ List findDistinctInterrogationIdsByCollectionInstrumentIdAndRecordDateBetween(String collectionInstrumentId, Instant start, Instant end);
//========= OPTIMISATIONS PERFS (START) ==========
long countResponsesByCollectionInstrumentId(String questionnaireId);
@@ -73,6 +70,11 @@ List findDistinctPageableInterrogationIdsByQuestionnaireId(Stri
Long deleteByCollectionInstrumentId(String collectionInstrumentId);
+ Long deleteByQuestionnaireIdAndInterrogationIds(
+ String questionnaireId,
+ Set interrogationIds
+ );
+
long countResponses();
Set findQuestionnaireIdsByCampaignId(String campaignId);
diff --git a/src/main/java/fr/insee/genesis/domain/ports/spi/LunaticJsonRawDataPersistencePort.java b/src/main/java/fr/insee/genesis/domain/ports/spi/LunaticJsonRawDataPersistencePort.java
index e8bbadb3a..cc2f355e9 100644
--- a/src/main/java/fr/insee/genesis/domain/ports/spi/LunaticJsonRawDataPersistencePort.java
+++ b/src/main/java/fr/insee/genesis/domain/ports/spi/LunaticJsonRawDataPersistencePort.java
@@ -14,12 +14,12 @@
public interface LunaticJsonRawDataPersistencePort {
void save(LunaticJsonRawDataModel rawData);
- List findRawData(String campaignName, Mode mode, List interrogationIdList);
List findRawDataByQuestionnaireId(String questionnaireId, Mode mode, List interrogationIdList);
Page findRawDataByQuestionnaireId(String questionnaireId, Pageable pageable);
List findRawDataByInterrogationID(String interrogationId);
List getAllUnprocessedData();
void updateProcessDates(String campaignId, Set interrogationIds);
+
Set findDistinctQuestionnaireIds();
Set findDistinctQuestionnaireIdsByNullProcessDate();
Set findModesByQuestionnaire(String questionnaireId);
@@ -31,4 +31,5 @@ public interface LunaticJsonRawDataPersistencePort {
boolean existsByInterrogationId(String interrogationId);
long countDistinctInterrogationIdsByQuestionnaireId(String questionnaireId);
+
}
diff --git a/src/main/java/fr/insee/genesis/domain/ports/spi/RawResponsePersistencePort.java b/src/main/java/fr/insee/genesis/domain/ports/spi/RawResponsePersistencePort.java
index 649d942ae..c8db17a73 100644
--- a/src/main/java/fr/insee/genesis/domain/ports/spi/RawResponsePersistencePort.java
+++ b/src/main/java/fr/insee/genesis/domain/ports/spi/RawResponsePersistencePort.java
@@ -21,8 +21,7 @@ public interface RawResponsePersistencePort {
Page findByCampaignIdAndDate(String campaignId, Instant startDate, Instant endDate, Pageable pageable);
long countByCollectionInstrumentId(String collectionInstrumentId);
Set findDistinctCollectionInstrumentIds();
- long countDistinctInterrogationIdsByCollectionInstrumentId(String collectionInstrumentId);
Page findByCollectionInstrumentId(String collectionInstrumentId, Pageable pageable);
-
boolean existsByInterrogationId(String interrogationId);
+
}
diff --git a/src/main/java/fr/insee/genesis/domain/ports/spi/RawResponseReprocessPersistencePort.java b/src/main/java/fr/insee/genesis/domain/ports/spi/RawResponseReprocessPersistencePort.java
new file mode 100644
index 000000000..8560faa10
--- /dev/null
+++ b/src/main/java/fr/insee/genesis/domain/ports/spi/RawResponseReprocessPersistencePort.java
@@ -0,0 +1,16 @@
+package fr.insee.genesis.domain.ports.spi;
+
+import java.time.Instant;
+import java.util.Set;
+
+public interface RawResponseReprocessPersistencePort {
+
+ Set findProcessedInterrogationIdsByCollectionInstrumentId(
+ String collectionInstrumentId);
+
+ Set findProcessedInterrogationIdsByCollectionInstrumentIdAndRecordDateBetween(
+ String collectionInstrumentId, Instant sinceDate, Instant endDate);
+
+ void resetProcessDates(String collectionInstrumentId, Set interrogationIds);
+
+}
diff --git a/src/main/java/fr/insee/genesis/domain/ports/spi/RawResponseReprocessPersistenceRouter.java b/src/main/java/fr/insee/genesis/domain/ports/spi/RawResponseReprocessPersistenceRouter.java
new file mode 100644
index 000000000..ed77a8981
--- /dev/null
+++ b/src/main/java/fr/insee/genesis/domain/ports/spi/RawResponseReprocessPersistenceRouter.java
@@ -0,0 +1,9 @@
+package fr.insee.genesis.domain.ports.spi;
+
+import fr.insee.genesis.domain.model.surveyunit.rawdata.RawDataModelType;
+
+public interface RawResponseReprocessPersistenceRouter {
+
+ RawResponseReprocessPersistencePort resolve(RawDataModelType rawDataModelType);
+
+}
diff --git a/src/main/java/fr/insee/genesis/domain/ports/spi/SurveyUnitPersistencePort.java b/src/main/java/fr/insee/genesis/domain/ports/spi/SurveyUnitPersistencePort.java
index 0629b3029..9e3b952ca 100644
--- a/src/main/java/fr/insee/genesis/domain/ports/spi/SurveyUnitPersistencePort.java
+++ b/src/main/java/fr/insee/genesis/domain/ports/spi/SurveyUnitPersistencePort.java
@@ -2,6 +2,7 @@
import fr.insee.genesis.domain.model.surveyunit.SurveyUnitModel;
+import java.time.Instant;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Set;
@@ -34,8 +35,8 @@ public interface SurveyUnitPersistencePort {
List findInterrogationIdsByCollectionInstrumentIdAndRecordDateBetween(
String collectionInstrumentId,
- LocalDateTime start,
- LocalDateTime end
+ Instant start,
+ Instant end
);
//======== OPTIMISATIONS PERFS (START) ========
@@ -52,6 +53,16 @@ List findInterrogationIdsByCollectionInstrumentIdAndRecordDateB
Long deleteByCollectionInstrumentId(String collectionInstrumentId);
+ Long deleteByCollectionInstrumentIdAndInterrogationIds(
+ String collectionInstrumentId,
+ Set interrogationIds
+ );
+
+ Long deleteByQuestionnaireIdAndInterrogationIds(
+ String questionnaireId,
+ Set interrogationIds
+ );
+
long count();
Set findQuestionnaireIdsByCampaignId(String campaignId);
diff --git a/src/main/java/fr/insee/genesis/domain/service/metadata/QuestionnaireMetadataService.java b/src/main/java/fr/insee/genesis/domain/service/metadata/QuestionnaireMetadataService.java
index 2e254a87c..898466d49 100644
--- a/src/main/java/fr/insee/genesis/domain/service/metadata/QuestionnaireMetadataService.java
+++ b/src/main/java/fr/insee/genesis/domain/service/metadata/QuestionnaireMetadataService.java
@@ -45,7 +45,7 @@ public MetadataModel find(String collectionInstrumentId, Mode mode) throws Genes
}
@Override
- public MetadataModel loadAndSaveIfNotExists(String campaignName, String collectionInstrumentId, Mode mode, FileUtils fileUtils,
+ public MetadataModel loadAndSaveIfNotExists(String questionnaireId, String collectionInstrumentId, Mode mode, FileUtils fileUtils,
List errors) throws GenesisException {
List questionnaireMetadataModels =
questionnaireMetadataPersistencePort.find(collectionInstrumentId.toUpperCase(), mode);
diff --git a/src/main/java/fr/insee/genesis/domain/service/rawdata/LunaticJsonRawDataService.java b/src/main/java/fr/insee/genesis/domain/service/rawdata/LunaticJsonRawDataService.java
index 15abc3e2d..c2d46af52 100644
--- a/src/main/java/fr/insee/genesis/domain/service/rawdata/LunaticJsonRawDataService.java
+++ b/src/main/java/fr/insee/genesis/domain/service/rawdata/LunaticJsonRawDataService.java
@@ -2,7 +2,6 @@
import fr.insee.bpm.metadata.model.MetadataModel;
import fr.insee.bpm.metadata.model.VariablesMap;
-import fr.insee.genesis.Constants;
import fr.insee.genesis.configuration.Config;
import fr.insee.genesis.controller.dto.rawdata.LunaticJsonRawDataUnprocessedDto;
import fr.insee.genesis.controller.utils.ControllerUtils;
@@ -11,20 +10,15 @@
import fr.insee.genesis.domain.model.surveyunit.GroupedInterrogation;
import fr.insee.genesis.domain.model.surveyunit.Mode;
import fr.insee.genesis.domain.model.surveyunit.SurveyUnitModel;
-import fr.insee.genesis.domain.model.surveyunit.VariableModel;
import fr.insee.genesis.domain.model.surveyunit.rawdata.DataProcessResult;
import fr.insee.genesis.domain.model.surveyunit.rawdata.LunaticJsonRawDataModel;
-import fr.insee.genesis.domain.model.surveyunit.rawdata.RawDataModelType;
import fr.insee.genesis.domain.ports.api.LunaticJsonRawDataApiPort;
import fr.insee.genesis.domain.ports.spi.DataProcessingContextPersistancePort;
import fr.insee.genesis.domain.ports.spi.LunaticJsonRawDataPersistencePort;
-import fr.insee.genesis.domain.ports.spi.SurveyUnitQualityToolPort;
-import fr.insee.genesis.domain.service.context.DataProcessingContextService;
import fr.insee.genesis.domain.service.metadata.QuestionnaireMetadataService;
-import fr.insee.genesis.domain.service.surveyunit.SurveyUnitQualityService;
+import fr.insee.genesis.domain.service.surveyunit.SurveyUnitQualityToolService;
import fr.insee.genesis.domain.service.surveyunit.SurveyUnitService;
-import fr.insee.genesis.domain.utils.GroupUtils;
-import fr.insee.genesis.domain.utils.JsonUtils;
+import fr.insee.genesis.domain.utils.LunaticJsonRawDataConverter;
import fr.insee.genesis.exceptions.GenesisError;
import fr.insee.genesis.exceptions.GenesisException;
import fr.insee.genesis.infrastructure.utils.FileUtils;
@@ -33,21 +27,16 @@
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
-import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
-import java.io.IOException;
-import java.math.BigDecimal;
import java.time.Instant;
import java.time.LocalDateTime;
import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
-import static fr.insee.genesis.domain.service.rawdata.RawResponseService.processCollectedVariable;
+
@Service
@Slf4j
@@ -56,9 +45,7 @@ public class LunaticJsonRawDataService implements LunaticJsonRawDataApiPort {
private final ControllerUtils controllerUtils;
private final QuestionnaireMetadataService metadataService;
private final SurveyUnitService surveyUnitService;
- private final SurveyUnitQualityService surveyUnitQualityService;
- private final SurveyUnitQualityToolPort surveyUnitQualityToolPort;
- private final DataProcessingContextService dataProcessingContextService;
+ private final SurveyUnitQualityToolService surveyUnitQualityToolService;
private final FileUtils fileUtils;
private final Config config;
@@ -68,26 +55,23 @@ public class LunaticJsonRawDataService implements LunaticJsonRawDataApiPort {
private final DataProcessingContextPersistancePort dataProcessingContextPersistancePort;
@Autowired
- public LunaticJsonRawDataService(LunaticJsonRawDataPersistencePort lunaticJsonRawDataNewPersistencePort,
- ControllerUtils controllerUtils,
- QuestionnaireMetadataService metadataService,
- SurveyUnitService surveyUnitService,
- SurveyUnitQualityService surveyUnitQualityService,
- FileUtils fileUtils,
- DataProcessingContextService dataProcessingContextService,
- SurveyUnitQualityToolPort surveyUnitQualityToolPort,
- Config config,
- DataProcessingContextPersistancePort dataProcessingContextPersistancePort
+ public LunaticJsonRawDataService(
+ LunaticJsonRawDataPersistencePort lunaticJsonRawDataNewPersistencePort,
+ ControllerUtils controllerUtils,
+ QuestionnaireMetadataService metadataService,
+ SurveyUnitService surveyUnitService,
+ FileUtils fileUtils,
+ SurveyUnitQualityToolService surveyUnitQualityToolService,
+ Config config,
+ DataProcessingContextPersistancePort dataProcessingContextPersistancePort
) {
this.controllerUtils = controllerUtils;
this.metadataService = metadataService;
this.surveyUnitService = surveyUnitService;
- this.surveyUnitQualityService = surveyUnitQualityService;
+ this.surveyUnitQualityToolService = surveyUnitQualityToolService;
this.fileUtils = fileUtils;
this.lunaticJsonRawDataPersistencePort = lunaticJsonRawDataNewPersistencePort;
this.dataProcessingContextPersistancePort = dataProcessingContextPersistancePort;
- this.surveyUnitQualityToolPort = surveyUnitQualityToolPort;
- this.dataProcessingContextService = dataProcessingContextService;
this.config = config;
}
@@ -97,273 +81,91 @@ public void save(LunaticJsonRawDataModel rawData) {
}
@Override
- public List getRawData(String campaignName, Mode mode, List interrogationIdList) {
- return lunaticJsonRawDataPersistencePort.findRawData(campaignName, mode, interrogationIdList);
+ public List getRawDataByQuestionnaireId(
+ String questionnaireId, Mode mode, List interrogationIdList
+ ) {
+ return lunaticJsonRawDataPersistencePort.findRawDataByQuestionnaireId(
+ questionnaireId, mode, interrogationIdList);
}
@Override
- public List getRawDataByQuestionnaireId(String questionnaireId, Mode mode, List interrogationIdList) {
- return lunaticJsonRawDataPersistencePort.findRawDataByQuestionnaireId(questionnaireId, mode, interrogationIdList);
- }
-
- @Override
public List getRawDataByInterrogationId(String interrogationId) {
return lunaticJsonRawDataPersistencePort.findRawDataByInterrogationID(interrogationId);
}
@Override
- @Deprecated(since = "1.13.0")
- public DataProcessResult processRawData(String campaignName, List interrogationIdList, List errors) throws GenesisException {
- int dataCount=0;
- int formattedDataCount=0;
- DataProcessingContextModel dataProcessingContext =
- dataProcessingContextService.getContextByCollectionInstrumentId(campaignName);
- List modesList = controllerUtils.getModesList(campaignName, null);
- for (Mode mode : modesList) {
- //Load and save metadata into database, throw exception if none
- VariablesMap variablesMap = getVariablesMap(campaignName, mode, errors);
- int totalBatchs = Math.ceilDiv(interrogationIdList.size() , config.getRawDataProcessingBatchSize());
- int batchNumber = 1;
- List interrogationIdListForMode = new ArrayList<>(interrogationIdList);
- while(!interrogationIdListForMode.isEmpty()){
- log.info("Processing raw data batch {}/{}", batchNumber, totalBatchs);
- int maxIndex = Math.min(interrogationIdListForMode.size(), config.getRawDataProcessingBatchSize());
- List interrogationIdToProcess = interrogationIdListForMode.subList(0, maxIndex);
-
- List rawData = getRawData(campaignName, mode, interrogationIdToProcess);
-
- List surveyUnitModels = convertRawData(
- rawData,
- variablesMap
- );
-
- //Save converted data
- surveyUnitQualityService.verifySurveyUnits(surveyUnitModels, variablesMap);
- surveyUnitService.saveSurveyUnits(surveyUnitModels);
-
- //Update process dates
- updateProcessDates(surveyUnitModels);
-
- //Increment data count
- dataCount += surveyUnitModels.size();
- formattedDataCount += surveyUnitModels.stream()
- .filter(surveyUnitModel -> surveyUnitModel.getState().equals(DataState.FORMATTED))
- .toList()
- .size();
-
- //Send processed ids grouped by questionnaire (if review activated)
- if(dataProcessingContext != null && dataProcessingContext.isWithReview()) {
- sendProcessedIdsToQualityTool(surveyUnitModels);
- }
-
- //Remove processed ids from list
- interrogationIdListForMode = interrogationIdListForMode.subList(maxIndex, interrogationIdListForMode.size());
+ public DataProcessResult processRawData(String questionnaireId) throws GenesisException {
+ List interrogationIds = lunaticJsonRawDataPersistencePort
+ .findUnprocessedInterrogationIdsByCollectionInstrumentId(questionnaireId)
+ .stream()
+ .toList();
- batchNumber++;
- }
- }
- return new DataProcessResult(dataCount, formattedDataCount, errors);
+ return processRawDataByInterrogationIds(questionnaireId, interrogationIds, new ArrayList<>());
}
@Override
- public DataProcessResult processRawData(String questionnaireId) throws GenesisException {
- int dataCount=0;
- int formattedDataCount=0;
- DataProcessingContextModel dataProcessingContext =
- dataProcessingContextService.getContextByCollectionInstrumentId(questionnaireId);
- List errors = new ArrayList<>();
+ public DataProcessResult processRawDataByInterrogationIds(
+ String questionnaireId,
+ List interrogationIdList,
+ List errors
+ ) throws GenesisException {
- List modesList = controllerUtils.getModesList(questionnaireId, null);
- for (Mode mode : modesList) {
- //Load and save metadata into database, throw exception if none
- VariablesMap variablesMap = getVariablesMap(questionnaireId, mode, errors);
- Set interrogationIds =
- lunaticJsonRawDataPersistencePort.findUnprocessedInterrogationIdsByCollectionInstrumentId(questionnaireId);
+ List modes = controllerUtils.getModesList(questionnaireId, null);
+ boolean resolveWithReviewValue = surveyUnitQualityToolService.resolveWithReviewValue(questionnaireId);
- int totalBatchs = Math.ceilDiv(interrogationIds.size() , config.getRawDataProcessingBatchSize());
- int batchNumber = 1;
- List interrogationIdListForMode = new ArrayList<>(interrogationIds);
- while(!interrogationIdListForMode.isEmpty()){
- log.info("Processing raw data batch {}/{}", batchNumber, totalBatchs);
-
- int maxIndex = Math.min(interrogationIdListForMode.size(), config.getRawDataProcessingBatchSize());
- List surveyUnitModels = getConvertedSurveyUnits(
- questionnaireId,
- mode,
- interrogationIdListForMode,
- maxIndex,
- variablesMap
- );
-
- //Save converted data
- surveyUnitQualityService.verifySurveyUnits(surveyUnitModels, variablesMap);
- surveyUnitService.saveSurveyUnits(surveyUnitModels);
-
- //Update process dates
- updateProcessDates(surveyUnitModels);
-
- //Increment data count
- dataCount += surveyUnitModels.size();
- formattedDataCount += surveyUnitModels.stream()
- .filter(surveyUnitModel -> surveyUnitModel.getState().equals(DataState.FORMATTED))
- .toList()
- .size();
-
- //Send processed ids grouped by questionnaire (if review activated)
- if(dataProcessingContext != null && dataProcessingContext.isWithReview()) {
- sendProcessedIdsToQualityTool(surveyUnitModels);
- }
+ int batchSize = config.getRawDataProcessingBatchSize();
+ int totalBatches = Math.ceilDiv(interrogationIdList.size(), batchSize);
+ int dataCount = 0;
+ int formattedDataCount = 0;
- //Remove processed ids from list
- interrogationIdListForMode = interrogationIdListForMode.subList(maxIndex, interrogationIdListForMode.size());
- batchNumber++;
- }
- }
- return new DataProcessResult(dataCount, formattedDataCount, errors);
- }
+ for (Mode mode : modes) {
+ VariablesMap variablesMap = getVariablesMap(questionnaireId, mode, errors);
+ List interrogationIdListForMode = new ArrayList<>(interrogationIdList);
+ int batchNumber = 1;
- private VariablesMap getVariablesMap(String questionnaireId, Mode mode, List errors) throws GenesisException {
- VariablesMap variablesMap = metadataService.loadAndSaveIfNotExists(questionnaireId, questionnaireId, mode, fileUtils,
- errors).getVariables();
- if (variablesMap == null) {
- throw new GenesisException(400,
- "Error during metadata parsing for mode %s :%n%s"
- .formatted(mode, errors.getLast().getMessage())
- );
- }
- return variablesMap;
- }
+ while (!interrogationIdListForMode.isEmpty()) {
+ log.info("Processing raw data batch {}/{}", batchNumber, totalBatches);
- private List getConvertedSurveyUnits(String questionnaireId, Mode mode, List interrogationIdListForMode, int maxIndex, VariablesMap variablesMap) {
- List interrogationIdToProcess = interrogationIdListForMode.subList(0, maxIndex);
- List rawData = getRawDataByQuestionnaireId(questionnaireId, mode, interrogationIdToProcess);
- return convertRawData(
- rawData,
- variablesMap
- );
- }
+ int maxIndex = Math.min(interrogationIdListForMode.size(), batchSize);
+ List batch = interrogationIdListForMode.subList(0, maxIndex);
- private void sendProcessedIdsToQualityTool(List surveyUnitModels) {
- try {
- ResponseEntity