Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import fr.insee.genesis.controller.dto.InterrogationBatchResponse;
import fr.insee.genesis.controller.rest.CommonApiResponse;
import fr.insee.genesis.controller.utils.DateTimeUtils;
import fr.insee.genesis.domain.model.surveyunit.InterrogationId;
import fr.insee.genesis.domain.model.surveyunit.InterrogationInfo;
import fr.insee.genesis.domain.ports.api.SurveyUnitApiPort;
Expand Down Expand Up @@ -61,14 +62,27 @@ public ResponseEntity<InterrogationBatchResponse> getAllInterrogationIdsByQuesti
)
@RequestParam(value = "since", required = false)
Instant since,
@RequestParam(value = "localSinceDate", required = false)
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
@Parameter(description = "Filter interrogations to those recorded strictly after the given timestamp (Europe/Paris timezone)",
schema = @Schema(type = "string", format = "date-time", example = "2026-02-02T01:00:00"))
LocalDateTime localSinceDate,
@RequestParam(value = "until", required = false)
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
@Parameter(
description = "Filter interrogations to those recorded before the given timestamp or at the same time (ISO-8601 UTC format).",
schema = @Schema(type = "string", format = "date-time", example = "2026-01-31T23:59:59Z")
)
Instant until) {
List<InterrogationInfo> idsInfo = surveyUnitService.searchInterrogations(collectionInstrumentId, since, until);
Instant until,
@RequestParam(value = "localUntilDate", required = false)
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
@Parameter(description = "Filter interrogations to those recorded before the given timestamp or at the same time (Europe/Paris timezone)",
schema = @Schema(type = "string", format = "date-time", example = "2026-04-02T01:00:00"))
LocalDateTime localUntilDate) {

Instant resolvedSinceDate = DateTimeUtils.resolveInstant(since, localSinceDate);
Instant resolvedEndDate = DateTimeUtils.resolveInstant(until, localUntilDate);
List<InterrogationInfo> idsInfo = surveyUnitService.searchInterrogations(collectionInstrumentId, resolvedSinceDate, resolvedEndDate);
InterrogationBatchResponse response = buildInterrogationBatchResponse(idsInfo);
return ResponseEntity.ok(response);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package fr.insee.genesis.controller.rest.responses;

import fr.insee.genesis.controller.dto.rawdata.LunaticJsonRawDataUnprocessedDto;
import fr.insee.genesis.controller.utils.DateTimeUtils;
import fr.insee.genesis.domain.model.surveyunit.Mode;
import fr.insee.genesis.domain.model.surveyunit.rawdata.DataProcessResult;
import fr.insee.genesis.domain.model.surveyunit.rawdata.LunaticJsonRawDataModel;
Expand All @@ -14,6 +15,7 @@
import fr.insee.modelefiliere.RawResponseDto;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
Expand Down Expand Up @@ -199,15 +201,44 @@ public ResponseEntity<Map<String, List<String>>> getProcessedDataIdsSinceHours(
@PreAuthorize("hasRole('USER_BATCH_GENERIC')")
public ResponseEntity<PagedModel<LunaticJsonRawDataModel>> getLunaticJsonRawDataModelFromJsonBody(
@PathVariable String campaignId,
@RequestParam(value = "startDate", required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) Instant startDate,
@RequestParam(value = "endDate", required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) Instant endDate,
@RequestParam(value = "startDate", required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
@Parameter(description = "Start date in UTC", example = "2026-02-02T00:00:00Z")
Instant startDate,
@RequestParam(value = "localStartDate", required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
@Parameter(description = "Extract since in Europe/Paris timezone", schema = @Schema(type = "string", format = "date-time", example = "2026-02-02T01:00:00"))
LocalDateTime localStartDate,
@RequestParam(value = "endDate", required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
@Parameter(description = "End date in UTC", example = "2026-02-02T00:00:00Z")
Instant endDate,
@RequestParam(value = "localEndDate", required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
@Parameter(description = "Extract until in Europe/Paris timezone", schema = @Schema(type = "string", format = "date-time", example = "2026-02-02T01:00:00"))
LocalDateTime localEndDate,
@RequestParam(value = "page", defaultValue = "0") int page,
@RequestParam(value = "size", defaultValue = "1000") int size
) {
log.info("Try to read raw JSONs for campaign {}, with startDate={} and endDate={} - page={} - size={}", campaignId, startDate, endDate,page,size);
Instant resolvedStartDate = DateTimeUtils.resolveInstant(startDate, localStartDate);
Instant resolvedEndDate = DateTimeUtils.resolveInstant(endDate, localEndDate);
log.info(
"Try to read raw JSONs for campaign {} with startDateUtc={} startDateLocal={} endDateUtc={} endDateLocal={} - page={} - size={}",
campaignId,
resolvedStartDate,
DateTimeUtils.toFranceDateTime(resolvedStartDate),
resolvedEndDate,
DateTimeUtils.toFranceDateTime(resolvedEndDate),
page,
size
);
Pageable pageable = PageRequest.of(page, size);
Page<LunaticJsonRawDataModel> rawResponses = lunaticJsonRawDataApiPort.findRawDataByCampaignIdAndDate(campaignId, startDate, endDate, pageable);
log.info("rawResponses, lunatic-json for campaign {}, with startDate={} and endDate={} ={}", campaignId, startDate, endDate,rawResponses.getContent().size());
Page<LunaticJsonRawDataModel> rawResponses = lunaticJsonRawDataApiPort.findRawDataByCampaignIdAndDate(campaignId, resolvedStartDate, resolvedEndDate, pageable);
log.info(
"rawResponses, lunatic-json for campaign {} with startDateUtc={} startDateLocal={} endDateUtc={} endDateLocal={} count={}",
campaignId,
resolvedStartDate,
DateTimeUtils.toFranceDateTime(resolvedStartDate),
resolvedEndDate,
DateTimeUtils.toFranceDateTime(resolvedEndDate),
rawResponses.getContent().size()
);
return ResponseEntity.status(HttpStatus.OK).body(new PagedModel<>(rawResponses));
}

Expand Down Expand Up @@ -256,15 +287,41 @@ public ResponseEntity<Void> existsLunaticJsonByInterrogationId(@PathVariable Str
@PreAuthorize("hasRole('USER_BATCH_GENERIC')")
public ResponseEntity<PagedModel<RawResponseModel>> getRawResponsesFromJsonBody(
@PathVariable String campaignId,
@RequestParam(value = "startDate", required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) Instant startDate,
@RequestParam(value = "endDate", required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) Instant endDate,
@RequestParam(value = "startDate", required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
@Parameter(description = "Start date in UTC", example = "2026-02-02T00:00:00Z")
Instant startDate,
@RequestParam(value = "localStartDate", required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
@Parameter(description = "Extract since in Europe/Paris timezone", schema = @Schema(type = "string", format = "date-time", example = "2026-02-02T01:00:00"))
LocalDateTime localStartDate,
@RequestParam(value = "endDate", required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
@Parameter(description = "End date in UTC", example = "2026-04-02T00:00:00Z")
Instant endDate,
@RequestParam(value = "localEndDate", required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
@Parameter(description = "Extract until in Europe/Paris timezone", schema = @Schema(type = "string", format = "date-time", example = "2026-02-02T01:00:00"))
LocalDateTime localEndDate,
@RequestParam(value = "page", defaultValue = "0") int page,
@RequestParam(value = "size", defaultValue = "1000") int size
) {
log.info("Try to read raw lunatic JSONs for campaign {}, with startDate={} and endDate={} - page={} - size={}", campaignId, startDate, endDate,page,size);
Instant resolvedStartDate = DateTimeUtils.resolveInstant(startDate, localStartDate);
Instant resolvedEndDate = DateTimeUtils.resolveInstant(endDate, localEndDate);
log.info("Try to read raw JSONs for campaign {} with startDateUtc={} startDateLocal={} endDateUtc={} endDateLocal={} - page={} - size={}",
campaignId,
resolvedStartDate,
DateTimeUtils.toFranceDateTime(resolvedStartDate),
resolvedEndDate,
DateTimeUtils.toFranceDateTime(resolvedEndDate),
page,
size
);
Pageable pageable = PageRequest.of(page, size);
Page<RawResponseModel> rawResponses = rawResponseApiPort.findRawResponseDataByCampaignIdAndDate(campaignId, startDate, endDate, pageable);
log.info("rawResponses for campaign {}, with startDate={} and endDate={} ={}",campaignId, startDate, endDate, rawResponses.getContent().size());
Page<RawResponseModel> rawResponses = rawResponseApiPort.findRawResponseDataByCampaignIdAndDate(campaignId, resolvedStartDate, resolvedEndDate, pageable);
log.info("rawResponses for campaign {},with startDateUtc={} startDateLocal={} endDateUtc={} endDateLocal={} count={}",
campaignId,
resolvedStartDate,
DateTimeUtils.toFranceDateTime(resolvedStartDate),
resolvedEndDate,
DateTimeUtils.toFranceDateTime(resolvedEndDate),
rawResponses.getContent().size());
return ResponseEntity.status(HttpStatus.OK).body(new PagedModel<>(rawResponses));
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package fr.insee.genesis.controller.rest.responses;

import fr.insee.genesis.controller.utils.DateTimeUtils;
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;
Expand All @@ -18,6 +19,7 @@
import org.springframework.web.bind.annotation.RequestParam;

import java.time.Instant;
import java.time.LocalDateTime;

@Controller
@RequiredArgsConstructor
Expand All @@ -44,20 +46,33 @@ public ResponseEntity<String> reProcessRawResponsesByCollectionInstrumentId(
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
Instant sinceDate,

@RequestParam(value = "localSinceDate", required = false)
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
@Parameter(description = "Extract since in Europe/Paris timezone", schema = @Schema(type = "string", format = "date-time", example = "2026-02-02T01:00:00"))
LocalDateTime localSinceDate,

@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
Instant endDate,

@RequestParam(value = "localEndDate", required = false)
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
@Parameter(description = "Extract until in Europe/Paris timezone", schema = @Schema(type = "string", format = "date-time", example = "2026-02-02T01:00:00"))
LocalDateTime localEndDate
) throws GenesisException {

Instant resolvedSinceDate = DateTimeUtils.resolveInstant(sinceDate, localSinceDate);
Instant resolvedEndDate = DateTimeUtils.resolveInstant(endDate, localEndDate);

DataProcessResult result = reprocessRawResponseApiPort.reprocessRawResponses(
RawDataModelType.FILIERE,
collectionInstrumentId,
sinceDate,
endDate);
resolvedSinceDate,
resolvedEndDate);

return ResponseEntity.ok(result.message(collectionInstrumentId));
}
Expand All @@ -81,20 +96,33 @@ public ResponseEntity<String> reProcessJsonRawDataByQuestionnaireId(
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
Instant sinceDate,

@RequestParam(value = "localSinceDate", required = false)
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
@Parameter(description = "Extract since in Europe/Paris timezone", schema = @Schema(type = "string", format = "date-time", example = "2026-02-02T01:00:00"))
LocalDateTime localSinceDate,

@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
Instant endDate,

@RequestParam(value = "localEndDate", required = false)
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
@Parameter(description = "Extract until in Europe/Paris timezone", schema = @Schema(type = "string", format = "date-time", example = "2026-02-02T01:00:00"))
LocalDateTime localEndDate
) throws GenesisException {

Instant resolvedSinceDate = DateTimeUtils.resolveInstant(sinceDate, localSinceDate);
Instant resolvedEndDate = DateTimeUtils.resolveInstant(endDate, localEndDate);

DataProcessResult result = reprocessRawResponseApiPort.reprocessRawResponses(
RawDataModelType.LEGACY,
collectionInstrumentId,
sinceDate,
endDate);
resolvedSinceDate,
resolvedEndDate);

return ResponseEntity.ok(result.message(collectionInstrumentId));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import fr.insee.genesis.controller.utils.AuthUtils;
import fr.insee.genesis.controller.utils.ControllerUtils;
import fr.insee.genesis.controller.utils.DataTransformer;
import fr.insee.genesis.controller.utils.DateTimeUtils;
import fr.insee.genesis.domain.model.context.DataProcessingContextModel;
import fr.insee.genesis.domain.model.surveyunit.InterrogationId;
import fr.insee.genesis.domain.model.surveyunit.Mode;
Expand All @@ -39,6 +40,7 @@
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
Expand Down Expand Up @@ -420,13 +422,27 @@ public ResponseEntity<List<SurveyUnitSimplifiedDto>> searchResponses(
schema = @Schema(type = "string", format = "date-time", example = "2026-01-01T00:00:00Z")
)
@RequestParam(value = "recordedBefore", required = false) Instant recordedBefore,
@Parameter(
description = "Filter responses recorded before or at the same time of the given timestamp in Europe/Paris local time",
schema = @Schema(
type = "string",
format = "date-time",
example = "2026-01-01T01:00:00"
)
)
@RequestParam(value = "localRecordedBefore", required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
LocalDateTime localRecordedBefore,
@RequestBody List<InterrogationId> interrogationIds)
{
Instant resolvedRecordedBefore = DateTimeUtils.resolveInstant(
recordedBefore,
localRecordedBefore
);
return ResponseEntity.ok(
surveyUnitService.findSimplifiedList(
collectionInstrumentId,
interrogationIds,
recordedBefore
resolvedRecordedBefore
)
);
}
Expand Down
43 changes: 43 additions & 0 deletions src/main/java/fr/insee/genesis/controller/utils/DateTimeUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package fr.insee.genesis.controller.utils;

import fr.insee.genesis.exceptions.InvalidDateIntervalException;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;

public final class DateTimeUtils {

private static final ZoneId FRANCE_ZONE = ZoneId.of("Europe/Paris");

private DateTimeUtils() {
}

public static Instant resolveInstant(
Instant utcDate,
LocalDateTime localDate
) {
if (utcDate != null && localDate != null) {
throw new InvalidDateIntervalException(
"Use either UTC date or local date, not both"
);
}

if (localDate != null) {
return localDate
.atZone(FRANCE_ZONE)
.toInstant();
}

return utcDate;
}

public static ZonedDateTime toFranceDateTime(Instant instant) {
if (instant == null) {
return null;
}

return instant.atZone(FRANCE_ZONE);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ void getAllInterrogationIdsByQuestionnaire_date_test() {
interrogationController.getAllInterrogationIdsByQuestionnaire(
TestConstants.DEFAULT_COLLECTION_INSTRUMENT_ID,
since,
null
null,
null,null
);

//THEN
Expand Down
Loading
Loading