Add runtime tachograph parity validation
This commit is contained in:
parent
e68047feab
commit
471726c4cc
|
|
@ -294,3 +294,60 @@ This prevents unrelated vehicle events from being copied into a driver result si
|
|||
|
||||
`parameters` take precedence in the tachograph profile. The compatibility endpoint maps these values to `expandVehicleEvents` and `vehicleExpansionPaddingMinutes`.
|
||||
|
||||
|
||||
## Tachograph parity validation
|
||||
|
||||
A validation endpoint is available to compare the legacy tachograph file-session Esper endpoint with the generic runtime event-processing profile:
|
||||
|
||||
```http
|
||||
POST /api/eventhub/runtime-processing/event-processing/validation/tachograph-parity
|
||||
```
|
||||
|
||||
This endpoint runs both paths for the selected session(s) and driver(s):
|
||||
|
||||
```text
|
||||
legacy file-session path
|
||||
/api/eventhub/tachograph-file-sessions/{sessionId}/drivers/{driverKey}/processing/esper-events
|
||||
|
||||
runtime event-processing path
|
||||
/api/eventhub/runtime-processing/event-processing
|
||||
profileKey = tachograph-driver-esper-v1
|
||||
```
|
||||
|
||||
Example request:
|
||||
|
||||
```json
|
||||
{
|
||||
"sessionId": "{{sessionId}}",
|
||||
"driverKey": "{{driverKey}}",
|
||||
"occurredFrom": "2026-05-01T00:00:00Z",
|
||||
"occurredTo": "2026-05-31T23:59:59Z",
|
||||
"expandVehicleEvents": true,
|
||||
"vehicleExpansionPaddingMinutes": 15,
|
||||
"significantDrivingMinutes": 3,
|
||||
"minimumRestPeriodMinutes": 720,
|
||||
"includeDebug": true
|
||||
}
|
||||
```
|
||||
|
||||
For multiple uploaded tachograph sessions, use `sessionIds` or `compositeSessionId`. The validation service resolves the selected drivers, executes the generic runtime profile, then compares count-level parity per driver.
|
||||
|
||||
Compared categories include:
|
||||
|
||||
```text
|
||||
activityIntervals
|
||||
drivingIntervals
|
||||
drivingInterruptionIntervals
|
||||
drivingInterruptionVehicleChangeIntervals
|
||||
dailyWeeklyRestCandidateIntervals
|
||||
dailyWeeklyRestCandidateCoverageIntervals
|
||||
unclassifiedDailyWeeklyRestCandidateCoverageIntervals
|
||||
potentialHomeOvernightStayIntervals
|
||||
potentialInVehicleOvernightStayIntervals
|
||||
potentialInVehicleTripIntervals
|
||||
vehicleUsageIntervals
|
||||
vuCardAbsentIntervals
|
||||
supportGeoEvents
|
||||
```
|
||||
|
||||
For a single session, this is a direct parity check against the original file-session endpoint. For multiple sessions, the reference side is the sum of the individual file-session endpoint results per driver; runtime processing may intentionally deduplicate or merge across session boundaries, so differences should be reviewed with the debug/audit output.
|
||||
|
|
|
|||
|
|
@ -159,6 +159,36 @@
|
|||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Validate tachograph profile parity - single session",
|
||||
"request": {
|
||||
"method": "POST",
|
||||
"header": [
|
||||
{
|
||||
"key": "Content-Type",
|
||||
"value": "application/json"
|
||||
}
|
||||
],
|
||||
"url": {
|
||||
"raw": "{{baseUrl}}/api/eventhub/runtime-processing/event-processing/validation/tachograph-parity",
|
||||
"host": [
|
||||
"{{baseUrl}}"
|
||||
],
|
||||
"path": [
|
||||
"api",
|
||||
"eventhub",
|
||||
"runtime-processing",
|
||||
"event-processing",
|
||||
"validation",
|
||||
"tachograph-parity"
|
||||
]
|
||||
},
|
||||
"body": {
|
||||
"mode": "raw",
|
||||
"raw": "{\n \"sessionId\": \"{{sessionId}}\",\n \"driverKey\": \"{{driverKey}}\",\n \"occurredFrom\": \"2026-05-01T00:00:00Z\",\n \"occurredTo\": \"2026-05-31T23:59:59Z\",\n \"expandVehicleEvents\": true,\n \"vehicleExpansionPaddingMinutes\": 15,\n \"significantDrivingMinutes\": 3,\n \"minimumRestPeriodMinutes\": 720,\n \"includeDebug\": true\n}"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -7,6 +7,9 @@ import at.procon.eventhub.processing.eventprocessing.RuntimeEventProcessingServi
|
|||
import at.procon.eventhub.processing.eventprocessing.dto.RuntimeEventProcessingApiRequest;
|
||||
import at.procon.eventhub.processing.eventprocessing.dto.RuntimeEventProcessingResultDto;
|
||||
import at.procon.eventhub.processing.eventprocessing.dto.RuntimeEventProcessingProfileDescriptorDto;
|
||||
import at.procon.eventhub.processing.eventprocessing.validation.RuntimeTachographParityValidationApiRequest;
|
||||
import at.procon.eventhub.processing.eventprocessing.validation.RuntimeTachographParityValidationResultDto;
|
||||
import at.procon.eventhub.processing.eventprocessing.validation.RuntimeTachographParityValidationService;
|
||||
import at.procon.eventhub.processing.model.UnifiedRuntimeEventBundle;
|
||||
import at.procon.eventhub.processing.service.UnifiedRuntimeDerivedProjectionService;
|
||||
import at.procon.eventhub.processing.service.UnifiedRuntimeDriverTimelineService;
|
||||
|
|
@ -31,13 +34,25 @@ public class UnifiedRuntimeProcessingController {
|
|||
private final UnifiedRuntimeDerivedProjectionService runtimeDerivedProjectionService;
|
||||
private final UnifiedRuntimeTachographEsperScopeProcessingService tachographEsperScopeProcessingService;
|
||||
private final RuntimeEventProcessingService runtimeEventProcessingService;
|
||||
private final RuntimeTachographParityValidationService tachographParityValidationService;
|
||||
|
||||
public UnifiedRuntimeProcessingController(
|
||||
UnifiedRuntimeEventAssemblyService eventAssemblyService,
|
||||
UnifiedRuntimeDriverTimelineService runtimeDriverTimelineService,
|
||||
UnifiedRuntimeDerivedProjectionService runtimeDerivedProjectionService
|
||||
) {
|
||||
this(eventAssemblyService, runtimeDriverTimelineService, runtimeDerivedProjectionService, null, null);
|
||||
this(eventAssemblyService, runtimeDriverTimelineService, runtimeDerivedProjectionService, null, null, null);
|
||||
}
|
||||
|
||||
public UnifiedRuntimeProcessingController(
|
||||
UnifiedRuntimeEventAssemblyService eventAssemblyService,
|
||||
UnifiedRuntimeDriverTimelineService runtimeDriverTimelineService,
|
||||
UnifiedRuntimeDerivedProjectionService runtimeDerivedProjectionService,
|
||||
UnifiedRuntimeTachographEsperScopeProcessingService tachographEsperScopeProcessingService,
|
||||
RuntimeEventProcessingService runtimeEventProcessingService
|
||||
) {
|
||||
this(eventAssemblyService, runtimeDriverTimelineService, runtimeDerivedProjectionService,
|
||||
tachographEsperScopeProcessingService, runtimeEventProcessingService, null);
|
||||
}
|
||||
|
||||
@Autowired
|
||||
|
|
@ -46,13 +61,15 @@ public class UnifiedRuntimeProcessingController {
|
|||
UnifiedRuntimeDriverTimelineService runtimeDriverTimelineService,
|
||||
UnifiedRuntimeDerivedProjectionService runtimeDerivedProjectionService,
|
||||
UnifiedRuntimeTachographEsperScopeProcessingService tachographEsperScopeProcessingService,
|
||||
RuntimeEventProcessingService runtimeEventProcessingService
|
||||
RuntimeEventProcessingService runtimeEventProcessingService,
|
||||
RuntimeTachographParityValidationService tachographParityValidationService
|
||||
) {
|
||||
this.eventAssemblyService = eventAssemblyService;
|
||||
this.runtimeDriverTimelineService = runtimeDriverTimelineService;
|
||||
this.runtimeDerivedProjectionService = runtimeDerivedProjectionService;
|
||||
this.tachographEsperScopeProcessingService = tachographEsperScopeProcessingService;
|
||||
this.runtimeEventProcessingService = runtimeEventProcessingService;
|
||||
this.tachographParityValidationService = tachographParityValidationService;
|
||||
}
|
||||
|
||||
@PostMapping("/driver-events")
|
||||
|
|
@ -94,6 +111,17 @@ public class UnifiedRuntimeProcessingController {
|
|||
return ResponseEntity.ok(runtimeEventProcessingService.process(request));
|
||||
}
|
||||
|
||||
|
||||
@PostMapping("/event-processing/validation/tachograph-parity")
|
||||
public ResponseEntity<RuntimeTachographParityValidationResultDto> validateTachographParity(
|
||||
@RequestBody RuntimeTachographParityValidationApiRequest request
|
||||
) {
|
||||
if (tachographParityValidationService == null) {
|
||||
throw new IllegalStateException("Runtime tachograph parity validation service is not configured.");
|
||||
}
|
||||
return ResponseEntity.ok(tachographParityValidationService.validate(request));
|
||||
}
|
||||
|
||||
@PostMapping("/tachograph/esper-processing")
|
||||
public ResponseEntity<UnifiedRuntimeTachographEsperScopeResultDto> runTachographEsperProcessing(
|
||||
@RequestBody UnifiedRuntimeProcessingApiRequest request
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
package at.procon.eventhub.processing.eventprocessing.validation;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public record RuntimeTachographDriverParityResultDto(
|
||||
String driverKey,
|
||||
String status,
|
||||
String referenceMode,
|
||||
int referenceSessionCount,
|
||||
boolean runtimePartitionPresent,
|
||||
List<RuntimeTachographParityCategoryComparisonDto> comparisons,
|
||||
List<String> notes,
|
||||
List<String> warnings
|
||||
) {
|
||||
public RuntimeTachographDriverParityResultDto {
|
||||
comparisons = comparisons == null ? List.of() : List.copyOf(comparisons);
|
||||
notes = notes == null ? List.of() : List.copyOf(notes);
|
||||
warnings = warnings == null ? List.of() : List.copyOf(warnings);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
package at.procon.eventhub.processing.eventprocessing.validation;
|
||||
|
||||
public record RuntimeTachographParityCategoryComparisonDto(
|
||||
String category,
|
||||
int fileSessionCount,
|
||||
int runtimeCount,
|
||||
boolean equal
|
||||
) {
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
package at.procon.eventhub.processing.eventprocessing.validation;
|
||||
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
public record RuntimeTachographParityValidationApiRequest(
|
||||
UUID sessionId,
|
||||
List<UUID> sessionIds,
|
||||
UUID compositeSessionId,
|
||||
String driverKey,
|
||||
Set<String> driverKeys,
|
||||
Boolean includeAllDrivers,
|
||||
OffsetDateTime occurredFrom,
|
||||
OffsetDateTime occurredTo,
|
||||
Boolean expandVehicleEvents,
|
||||
Integer vehicleExpansionPaddingMinutes,
|
||||
Integer significantDrivingMinutes,
|
||||
Integer minimumRestPeriodMinutes,
|
||||
Boolean includeDebug
|
||||
) {
|
||||
public RuntimeTachographParityValidationApiRequest {
|
||||
sessionIds = sessionIds == null ? List.of() : List.copyOf(sessionIds);
|
||||
driverKeys = driverKeys == null ? Set.of() : Set.copyOf(driverKeys);
|
||||
vehicleExpansionPaddingMinutes = vehicleExpansionPaddingMinutes == null
|
||||
? null
|
||||
: Math.max(0, vehicleExpansionPaddingMinutes);
|
||||
significantDrivingMinutes = significantDrivingMinutes == null ? null : Math.max(1, significantDrivingMinutes);
|
||||
minimumRestPeriodMinutes = minimumRestPeriodMinutes == null ? null : Math.max(1, minimumRestPeriodMinutes);
|
||||
}
|
||||
|
||||
public Set<String> requestedDriverKeys() {
|
||||
LinkedHashSet<String> result = new LinkedHashSet<>();
|
||||
if (driverKey != null && !driverKey.isBlank()) {
|
||||
result.add(driverKey.trim());
|
||||
}
|
||||
driverKeys.stream()
|
||||
.filter(value -> value != null && !value.isBlank())
|
||||
.map(String::trim)
|
||||
.forEach(result::add);
|
||||
return Set.copyOf(result);
|
||||
}
|
||||
|
||||
public boolean includeAllDriversOrDefault() {
|
||||
return includeAllDrivers == null ? requestedDriverKeys().isEmpty() : includeAllDrivers;
|
||||
}
|
||||
|
||||
public boolean expandVehicleEventsOrDefault() {
|
||||
return expandVehicleEvents == null || expandVehicleEvents;
|
||||
}
|
||||
|
||||
public boolean includeDebugOrDefault() {
|
||||
return includeDebug != null && includeDebug;
|
||||
}
|
||||
|
||||
public int vehicleExpansionPaddingMinutesOrDefault() {
|
||||
return vehicleExpansionPaddingMinutes == null ? 0 : Math.max(0, vehicleExpansionPaddingMinutes);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
package at.procon.eventhub.processing.eventprocessing.validation;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public record RuntimeTachographParityValidationResultDto(
|
||||
String profileKey,
|
||||
String status,
|
||||
List<UUID> sessionIds,
|
||||
int selectedDriverCount,
|
||||
Map<String, RuntimeTachographDriverParityResultDto> driverResults,
|
||||
List<String> notes,
|
||||
List<String> warnings
|
||||
) {
|
||||
public RuntimeTachographParityValidationResultDto {
|
||||
sessionIds = sessionIds == null ? List.of() : List.copyOf(sessionIds);
|
||||
driverResults = driverResults == null ? Map.of() : Map.copyOf(new LinkedHashMap<>(driverResults));
|
||||
notes = notes == null ? List.of() : List.copyOf(notes);
|
||||
warnings = warnings == null ? List.of() : List.copyOf(warnings);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,388 @@
|
|||
package at.procon.eventhub.processing.eventprocessing.validation;
|
||||
|
||||
import at.procon.eventhub.processing.dto.UnifiedRuntimeDerivedProjectionResultDto;
|
||||
import at.procon.eventhub.processing.dto.UnifiedRuntimeProcessingApiRequest;
|
||||
import at.procon.eventhub.processing.eventprocessing.RuntimeEventProcessingService;
|
||||
import at.procon.eventhub.processing.eventprocessing.dto.RuntimeEventPartitioningApiRequest;
|
||||
import at.procon.eventhub.processing.eventprocessing.dto.RuntimeEventProcessingApiRequest;
|
||||
import at.procon.eventhub.processing.eventprocessing.dto.RuntimeEventProcessingPartitionResultDto;
|
||||
import at.procon.eventhub.processing.eventprocessing.dto.RuntimeEventProcessingResultDto;
|
||||
import at.procon.eventhub.processing.eventprocessing.partition.RuntimeEventPartitioningStrategy;
|
||||
import at.procon.eventhub.processing.eventprocessing.profile.TachographDriverEsperRuntimeEventProcessingProfile;
|
||||
import at.procon.eventhub.processing.model.UnifiedEventSourceFamily;
|
||||
import at.procon.eventhub.processing.model.UnifiedRuntimeEventBackend;
|
||||
import at.procon.eventhub.tachographfilesession.dto.TachographEsperDriverProcessingResultDto;
|
||||
import at.procon.eventhub.tachographfilesession.dto.TachographEsperEventsProcessingRequest;
|
||||
import at.procon.eventhub.tachographfilesession.model.TachographCompositeSession;
|
||||
import at.procon.eventhub.tachographfilesession.model.TachographFileSession;
|
||||
import at.procon.eventhub.tachographfilesession.service.TachographCompositeSessionNotFoundException;
|
||||
import at.procon.eventhub.tachographfilesession.service.TachographCompositeSessionRepository;
|
||||
import at.procon.eventhub.tachographfilesession.service.TachographFileSessionNotFoundException;
|
||||
import at.procon.eventhub.tachographfilesession.service.TachographFileSessionProcessingService;
|
||||
import at.procon.eventhub.tachographfilesession.service.TachographFileSessionRepository;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class RuntimeTachographParityValidationService {
|
||||
|
||||
private final TachographFileSessionRepository fileSessionRepository;
|
||||
private final TachographCompositeSessionRepository compositeSessionRepository;
|
||||
private final TachographFileSessionProcessingService fileSessionProcessingService;
|
||||
private final RuntimeEventProcessingService runtimeEventProcessingService;
|
||||
|
||||
public RuntimeTachographParityValidationService(
|
||||
TachographFileSessionRepository fileSessionRepository,
|
||||
TachographCompositeSessionRepository compositeSessionRepository,
|
||||
TachographFileSessionProcessingService fileSessionProcessingService,
|
||||
RuntimeEventProcessingService runtimeEventProcessingService
|
||||
) {
|
||||
this.fileSessionRepository = fileSessionRepository;
|
||||
this.compositeSessionRepository = compositeSessionRepository;
|
||||
this.fileSessionProcessingService = fileSessionProcessingService;
|
||||
this.runtimeEventProcessingService = runtimeEventProcessingService;
|
||||
}
|
||||
|
||||
public RuntimeTachographParityValidationResultDto validate(RuntimeTachographParityValidationApiRequest request) {
|
||||
RuntimeTachographParityValidationApiRequest effectiveRequest = request == null
|
||||
? new RuntimeTachographParityValidationApiRequest(null, List.of(), null, null, Set.of(), true,
|
||||
null, null, true, 0, null, null, false)
|
||||
: request;
|
||||
List<UUID> sessionIds = resolveSessionIds(effectiveRequest);
|
||||
Set<String> driverKeys = resolveDriverKeys(effectiveRequest, sessionIds);
|
||||
if (driverKeys.isEmpty()) {
|
||||
throw new IllegalArgumentException("No driver keys could be resolved for tachograph parity validation.");
|
||||
}
|
||||
|
||||
RuntimeEventProcessingResultDto runtimeResult = runtimeEventProcessingService.process(genericRuntimeRequest(
|
||||
effectiveRequest,
|
||||
sessionIds,
|
||||
driverKeys
|
||||
));
|
||||
|
||||
LinkedHashMap<String, RuntimeTachographDriverParityResultDto> driverResults = new LinkedHashMap<>();
|
||||
List<String> warnings = new ArrayList<>(runtimeResult.warnings());
|
||||
for (String driverKey : driverKeys) {
|
||||
RuntimeTachographDriverParityResultDto driverResult = compareDriver(
|
||||
effectiveRequest,
|
||||
sessionIds,
|
||||
driverKey,
|
||||
runtimeResult
|
||||
);
|
||||
driverResults.put(driverKey, driverResult);
|
||||
warnings.addAll(driverResult.warnings());
|
||||
}
|
||||
|
||||
String status = driverResults.values().stream().allMatch(result -> "EQUAL".equals(result.status()))
|
||||
? "EQUAL"
|
||||
: "DIFFERENT";
|
||||
List<String> notes = new ArrayList<>(runtimeResult.notes());
|
||||
notes.add("Validation compares the legacy tachograph file-session esper-events path with the generic runtime event-processing profile '"
|
||||
+ TachographDriverEsperRuntimeEventProcessingProfile.PROFILE_KEY + "'.");
|
||||
if (sessionIds.size() > 1) {
|
||||
notes.add("For multiple sessions, file-session reference counts are summed per driver. Runtime processing may intentionally merge or deduplicate intervals across session boundaries, so category differences need domain review.");
|
||||
}
|
||||
|
||||
return new RuntimeTachographParityValidationResultDto(
|
||||
TachographDriverEsperRuntimeEventProcessingProfile.PROFILE_KEY,
|
||||
status,
|
||||
sessionIds,
|
||||
driverResults.size(),
|
||||
driverResults,
|
||||
notes,
|
||||
warnings
|
||||
);
|
||||
}
|
||||
|
||||
private RuntimeTachographDriverParityResultDto compareDriver(
|
||||
RuntimeTachographParityValidationApiRequest request,
|
||||
List<UUID> sessionIds,
|
||||
String driverKey,
|
||||
RuntimeEventProcessingResultDto runtimeResult
|
||||
) {
|
||||
RuntimeProjectionCounts runtimeCounts = runtimeCounts(runtimeResult, driverKey);
|
||||
ReferenceProjectionCounts referenceCounts = referenceCounts(request, sessionIds, driverKey);
|
||||
List<RuntimeTachographParityCategoryComparisonDto> comparisons = comparisons(referenceCounts.counts(), runtimeCounts.counts());
|
||||
boolean runtimePresent = runtimeCounts.present();
|
||||
boolean referencePresent = referenceCounts.referenceSessionCount() > 0;
|
||||
boolean allEqual = comparisons.stream().allMatch(RuntimeTachographParityCategoryComparisonDto::equal);
|
||||
|
||||
String status;
|
||||
if (!referencePresent) {
|
||||
status = "REFERENCE_MISSING";
|
||||
} else if (!runtimePresent) {
|
||||
status = "RUNTIME_MISSING";
|
||||
} else if (allEqual) {
|
||||
status = "EQUAL";
|
||||
} else {
|
||||
status = "DIFFERENT";
|
||||
}
|
||||
|
||||
List<String> notes = new ArrayList<>();
|
||||
notes.add("Reference mode: " + referenceCounts.referenceMode() + ".");
|
||||
notes.add("Reference session count: " + referenceCounts.referenceSessionCount() + ".");
|
||||
if (sessionIds.size() > 1) {
|
||||
notes.add("Reference counts are summed from individual file-session endpoint results for this driver.");
|
||||
}
|
||||
List<String> warnings = new ArrayList<>();
|
||||
if (!referencePresent) {
|
||||
warnings.add("Driver " + driverKey + " was not found in any selected tachograph file session.");
|
||||
}
|
||||
if (!runtimePresent) {
|
||||
warnings.add("Generic runtime event-processing profile did not return a partition for driver " + driverKey + ".");
|
||||
}
|
||||
if (runtimePresent && referencePresent && !allEqual) {
|
||||
warnings.add("Runtime result differs from file-session reference result for driver " + driverKey + ".");
|
||||
}
|
||||
return new RuntimeTachographDriverParityResultDto(
|
||||
driverKey,
|
||||
status,
|
||||
referenceCounts.referenceMode(),
|
||||
referenceCounts.referenceSessionCount(),
|
||||
runtimePresent,
|
||||
comparisons,
|
||||
notes,
|
||||
warnings
|
||||
);
|
||||
}
|
||||
|
||||
private RuntimeEventProcessingApiRequest genericRuntimeRequest(
|
||||
RuntimeTachographParityValidationApiRequest request,
|
||||
List<UUID> sessionIds,
|
||||
Set<String> driverKeys
|
||||
) {
|
||||
UnifiedRuntimeProcessingApiRequest scope = new UnifiedRuntimeProcessingApiRequest(
|
||||
null,
|
||||
sessionIds,
|
||||
null,
|
||||
null,
|
||||
Set.of(UnifiedEventSourceFamily.TACHOGRAPH_FILE_SESSION),
|
||||
UnifiedRuntimeEventBackend.SOURCE_DB,
|
||||
null,
|
||||
driverKeys,
|
||||
request.includeAllDriversOrDefault(),
|
||||
null,
|
||||
false,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
request.occurredFrom(),
|
||||
request.occurredTo(),
|
||||
request.expandVehicleEventsOrDefault(),
|
||||
request.vehicleExpansionPaddingMinutesOrDefault(),
|
||||
request.significantDrivingMinutes(),
|
||||
request.minimumRestPeriodMinutes()
|
||||
);
|
||||
RuntimeEventPartitioningApiRequest partitioning = new RuntimeEventPartitioningApiRequest(
|
||||
RuntimeEventPartitioningStrategy.DRIVER,
|
||||
null,
|
||||
request.includeAllDriversOrDefault(),
|
||||
driverKeys,
|
||||
request.includeAllDriversOrDefault(),
|
||||
null,
|
||||
false,
|
||||
request.expandVehicleEventsOrDefault(),
|
||||
request.vehicleExpansionPaddingMinutesOrDefault(),
|
||||
request.includeDebugOrDefault()
|
||||
);
|
||||
Map<String, Object> parameters = new LinkedHashMap<>();
|
||||
if (request.significantDrivingMinutes() != null) {
|
||||
parameters.put("significantDrivingMinutes", request.significantDrivingMinutes());
|
||||
}
|
||||
if (request.minimumRestPeriodMinutes() != null) {
|
||||
parameters.put("minimumRestPeriodMinutes", request.minimumRestPeriodMinutes());
|
||||
}
|
||||
parameters.put("attachVehicleOnlyEvents", request.expandVehicleEventsOrDefault());
|
||||
parameters.put("vehicleEvidencePaddingMinutes", request.vehicleExpansionPaddingMinutesOrDefault());
|
||||
parameters.put("includePartitionDebug", request.includeDebugOrDefault());
|
||||
return new RuntimeEventProcessingApiRequest(
|
||||
TachographDriverEsperRuntimeEventProcessingProfile.PROFILE_KEY,
|
||||
scope,
|
||||
partitioning,
|
||||
parameters
|
||||
);
|
||||
}
|
||||
|
||||
private List<UUID> resolveSessionIds(RuntimeTachographParityValidationApiRequest request) {
|
||||
LinkedHashSet<UUID> result = new LinkedHashSet<>();
|
||||
if (request.sessionId() != null) {
|
||||
result.add(request.sessionId());
|
||||
}
|
||||
result.addAll(request.sessionIds());
|
||||
if (request.compositeSessionId() != null) {
|
||||
TachographCompositeSession compositeSession = compositeSessionRepository.find(request.compositeSessionId())
|
||||
.orElseThrow(() -> new TachographCompositeSessionNotFoundException(request.compositeSessionId()));
|
||||
result.addAll(compositeSession.memberSessionIds());
|
||||
}
|
||||
if (result.isEmpty()) {
|
||||
throw new IllegalArgumentException("sessionId, sessionIds, or compositeSessionId is required for tachograph parity validation.");
|
||||
}
|
||||
result.forEach(this::requireFileSession);
|
||||
return List.copyOf(result);
|
||||
}
|
||||
|
||||
private Set<String> resolveDriverKeys(RuntimeTachographParityValidationApiRequest request, List<UUID> sessionIds) {
|
||||
LinkedHashSet<String> result = new LinkedHashSet<>(request.requestedDriverKeys());
|
||||
if (request.includeAllDriversOrDefault() || result.isEmpty()) {
|
||||
for (UUID sessionId : sessionIds) {
|
||||
result.addAll(requireFileSession(sessionId).driversByKey().keySet());
|
||||
}
|
||||
}
|
||||
return Set.copyOf(result);
|
||||
}
|
||||
|
||||
private TachographFileSession requireFileSession(UUID sessionId) {
|
||||
return fileSessionRepository.find(sessionId)
|
||||
.orElseThrow(() -> new TachographFileSessionNotFoundException(sessionId));
|
||||
}
|
||||
|
||||
private ReferenceProjectionCounts referenceCounts(
|
||||
RuntimeTachographParityValidationApiRequest request,
|
||||
List<UUID> sessionIds,
|
||||
String driverKey
|
||||
) {
|
||||
ProjectionCounts aggregate = ProjectionCounts.empty();
|
||||
int referenceSessionCount = 0;
|
||||
TachographEsperEventsProcessingRequest fileSessionRequest = new TachographEsperEventsProcessingRequest(
|
||||
request.occurredFrom(),
|
||||
request.occurredTo(),
|
||||
request.significantDrivingMinutes(),
|
||||
request.minimumRestPeriodMinutes()
|
||||
);
|
||||
for (UUID sessionId : sessionIds) {
|
||||
TachographFileSession session = requireFileSession(sessionId);
|
||||
if (!session.driversByKey().containsKey(driverKey)) {
|
||||
continue;
|
||||
}
|
||||
TachographEsperDriverProcessingResultDto projection = fileSessionProcessingService.getEsperDriverProcessingResults(
|
||||
sessionId,
|
||||
driverKey,
|
||||
fileSessionRequest
|
||||
);
|
||||
aggregate = aggregate.plus(ProjectionCounts.from(projection));
|
||||
referenceSessionCount++;
|
||||
}
|
||||
String referenceMode = sessionIds.size() == 1 ? "SINGLE_FILE_SESSION" : "SUM_OF_FILE_SESSION_RESULTS";
|
||||
return new ReferenceProjectionCounts(aggregate, referenceMode, referenceSessionCount);
|
||||
}
|
||||
|
||||
private RuntimeProjectionCounts runtimeCounts(RuntimeEventProcessingResultDto runtimeResult, String driverKey) {
|
||||
RuntimeEventProcessingPartitionResultDto partitionResult = runtimeResult.partitionResults().get(driverKey);
|
||||
if (partitionResult == null) {
|
||||
return new RuntimeProjectionCounts(ProjectionCounts.empty(), false);
|
||||
}
|
||||
Object result = partitionResult.result();
|
||||
if (result instanceof UnifiedRuntimeDerivedProjectionResultDto projectionResult) {
|
||||
return new RuntimeProjectionCounts(ProjectionCounts.from(projectionResult.projection()), projectionResult.projection() != null);
|
||||
}
|
||||
return new RuntimeProjectionCounts(ProjectionCounts.empty(), false);
|
||||
}
|
||||
|
||||
private List<RuntimeTachographParityCategoryComparisonDto> comparisons(
|
||||
ProjectionCounts reference,
|
||||
ProjectionCounts runtime
|
||||
) {
|
||||
return List.of(
|
||||
comparison("activityIntervals", reference.activityIntervalCount(), runtime.activityIntervalCount()),
|
||||
comparison("drivingIntervals", reference.drivingIntervalCount(), runtime.drivingIntervalCount()),
|
||||
comparison("drivingInterruptionIntervals", reference.drivingInterruptionIntervalCount(), runtime.drivingInterruptionIntervalCount()),
|
||||
comparison("drivingInterruptionVehicleChangeIntervals", reference.drivingInterruptionVehicleChangeIntervalCount(), runtime.drivingInterruptionVehicleChangeIntervalCount()),
|
||||
comparison("dailyWeeklyRestCandidateIntervals", reference.dailyWeeklyRestCandidateIntervalCount(), runtime.dailyWeeklyRestCandidateIntervalCount()),
|
||||
comparison("dailyWeeklyRestCandidateCoverageIntervals", reference.dailyWeeklyRestCandidateCoverageIntervalCount(), runtime.dailyWeeklyRestCandidateCoverageIntervalCount()),
|
||||
comparison("unclassifiedDailyWeeklyRestCandidateCoverageIntervals", reference.unclassifiedDailyWeeklyRestCandidateCoverageIntervalCount(), runtime.unclassifiedDailyWeeklyRestCandidateCoverageIntervalCount()),
|
||||
comparison("potentialHomeOvernightStayIntervals", reference.potentialHomeOvernightStayIntervalCount(), runtime.potentialHomeOvernightStayIntervalCount()),
|
||||
comparison("potentialInVehicleOvernightStayIntervals", reference.potentialInVehicleOvernightStayIntervalCount(), runtime.potentialInVehicleOvernightStayIntervalCount()),
|
||||
comparison("potentialInVehicleTripIntervals", reference.potentialInVehicleTripIntervalCount(), runtime.potentialInVehicleTripIntervalCount()),
|
||||
comparison("vehicleUsageIntervals", reference.vehicleUsageIntervalCount(), runtime.vehicleUsageIntervalCount()),
|
||||
comparison("vuCardAbsentIntervals", reference.vuCardAbsentIntervalCount(), runtime.vuCardAbsentIntervalCount()),
|
||||
comparison("supportGeoEvents", reference.supportGeoEventCount(), runtime.supportGeoEventCount())
|
||||
);
|
||||
}
|
||||
|
||||
private RuntimeTachographParityCategoryComparisonDto comparison(String category, int fileSessionCount, int runtimeCount) {
|
||||
return new RuntimeTachographParityCategoryComparisonDto(
|
||||
category,
|
||||
fileSessionCount,
|
||||
runtimeCount,
|
||||
fileSessionCount == runtimeCount
|
||||
);
|
||||
}
|
||||
|
||||
private record ReferenceProjectionCounts(
|
||||
ProjectionCounts counts,
|
||||
String referenceMode,
|
||||
int referenceSessionCount
|
||||
) {
|
||||
}
|
||||
|
||||
private record RuntimeProjectionCounts(
|
||||
ProjectionCounts counts,
|
||||
boolean present
|
||||
) {
|
||||
}
|
||||
|
||||
private record ProjectionCounts(
|
||||
int activityIntervalCount,
|
||||
int drivingIntervalCount,
|
||||
int drivingInterruptionIntervalCount,
|
||||
int drivingInterruptionVehicleChangeIntervalCount,
|
||||
int dailyWeeklyRestCandidateIntervalCount,
|
||||
int dailyWeeklyRestCandidateCoverageIntervalCount,
|
||||
int unclassifiedDailyWeeklyRestCandidateCoverageIntervalCount,
|
||||
int potentialHomeOvernightStayIntervalCount,
|
||||
int potentialInVehicleOvernightStayIntervalCount,
|
||||
int potentialInVehicleTripIntervalCount,
|
||||
int vehicleUsageIntervalCount,
|
||||
int vuCardAbsentIntervalCount,
|
||||
int supportGeoEventCount
|
||||
) {
|
||||
static ProjectionCounts empty() {
|
||||
return new ProjectionCounts(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
static ProjectionCounts from(TachographEsperDriverProcessingResultDto projection) {
|
||||
if (projection == null) {
|
||||
return empty();
|
||||
}
|
||||
return new ProjectionCounts(
|
||||
projection.activityIntervalCount(),
|
||||
projection.drivingIntervalCount(),
|
||||
projection.drivingInterruptionIntervalCount(),
|
||||
projection.drivingInterruptionVehicleChangeIntervalCount(),
|
||||
projection.dailyWeeklyRestCandidateIntervalCount(),
|
||||
projection.dailyWeeklyRestCandidateCoverageIntervalCount(),
|
||||
projection.unclassifiedDailyWeeklyRestCandidateCoverageIntervalCount(),
|
||||
projection.potentialHomeOvernightStayIntervalCount(),
|
||||
projection.potentialInVehicleOvernightStayIntervalCount(),
|
||||
projection.potentialInVehicleTripIntervalCount(),
|
||||
projection.vehicleUsageIntervalCount(),
|
||||
projection.vuCardAbsentIntervalCount(),
|
||||
projection.supportGeoEventCount()
|
||||
);
|
||||
}
|
||||
|
||||
ProjectionCounts plus(ProjectionCounts other) {
|
||||
return new ProjectionCounts(
|
||||
activityIntervalCount + other.activityIntervalCount,
|
||||
drivingIntervalCount + other.drivingIntervalCount,
|
||||
drivingInterruptionIntervalCount + other.drivingInterruptionIntervalCount,
|
||||
drivingInterruptionVehicleChangeIntervalCount + other.drivingInterruptionVehicleChangeIntervalCount,
|
||||
dailyWeeklyRestCandidateIntervalCount + other.dailyWeeklyRestCandidateIntervalCount,
|
||||
dailyWeeklyRestCandidateCoverageIntervalCount + other.dailyWeeklyRestCandidateCoverageIntervalCount,
|
||||
unclassifiedDailyWeeklyRestCandidateCoverageIntervalCount + other.unclassifiedDailyWeeklyRestCandidateCoverageIntervalCount,
|
||||
potentialHomeOvernightStayIntervalCount + other.potentialHomeOvernightStayIntervalCount,
|
||||
potentialInVehicleOvernightStayIntervalCount + other.potentialInVehicleOvernightStayIntervalCount,
|
||||
potentialInVehicleTripIntervalCount + other.potentialInVehicleTripIntervalCount,
|
||||
vehicleUsageIntervalCount + other.vehicleUsageIntervalCount,
|
||||
vuCardAbsentIntervalCount + other.vuCardAbsentIntervalCount,
|
||||
supportGeoEventCount + other.supportGeoEventCount
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -21,6 +21,10 @@ import at.procon.eventhub.processing.eventprocessing.dto.RuntimeEventProcessingR
|
|||
import at.procon.eventhub.processing.eventprocessing.dto.RuntimeEventProcessingProfileDescriptorDto;
|
||||
import at.procon.eventhub.processing.eventprocessing.dto.RuntimeEventProcessingPartitionResultDto;
|
||||
import at.procon.eventhub.processing.eventprocessing.partition.RuntimeEventPartitioningStrategy;
|
||||
import at.procon.eventhub.processing.eventprocessing.validation.RuntimeTachographDriverParityResultDto;
|
||||
import at.procon.eventhub.processing.eventprocessing.validation.RuntimeTachographParityCategoryComparisonDto;
|
||||
import at.procon.eventhub.processing.eventprocessing.validation.RuntimeTachographParityValidationResultDto;
|
||||
import at.procon.eventhub.processing.eventprocessing.validation.RuntimeTachographParityValidationService;
|
||||
import at.procon.eventhub.processing.model.UnifiedDiscoveredVehicleRef;
|
||||
import at.procon.eventhub.processing.model.UnifiedEventSourceFamily;
|
||||
import at.procon.eventhub.processing.model.UnifiedRuntimeEventBackend;
|
||||
|
|
@ -447,6 +451,71 @@ class UnifiedRuntimeProcessingControllerTest {
|
|||
.andExpect(jsonPath("$.notes[0]").value("generic adapter"));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void validatesTachographParityViaRuntimeApi() throws Exception {
|
||||
UnifiedRuntimeEventAssemblyService eventAssemblyService = org.mockito.Mockito.mock(UnifiedRuntimeEventAssemblyService.class);
|
||||
UnifiedRuntimeDriverTimelineService timelineService = org.mockito.Mockito.mock(UnifiedRuntimeDriverTimelineService.class);
|
||||
UnifiedRuntimeDerivedProjectionService derivedProjectionService = org.mockito.Mockito.mock(UnifiedRuntimeDerivedProjectionService.class);
|
||||
RuntimeEventProcessingService runtimeEventProcessingService = org.mockito.Mockito.mock(RuntimeEventProcessingService.class);
|
||||
RuntimeTachographParityValidationService parityValidationService = org.mockito.Mockito.mock(RuntimeTachographParityValidationService.class);
|
||||
MockMvc mockMvc = MockMvcBuilders.standaloneSetup(new UnifiedRuntimeProcessingController(
|
||||
eventAssemblyService,
|
||||
timelineService,
|
||||
derivedProjectionService,
|
||||
null,
|
||||
runtimeEventProcessingService,
|
||||
parityValidationService
|
||||
))
|
||||
.setMessageConverters(new MappingJackson2HttpMessageConverter(objectMapper))
|
||||
.setControllerAdvice(new UnifiedRuntimeProcessingExceptionHandler())
|
||||
.build();
|
||||
|
||||
UUID sessionId = UUID.randomUUID();
|
||||
when(parityValidationService.validate(any()))
|
||||
.thenReturn(new RuntimeTachographParityValidationResultDto(
|
||||
"tachograph-driver-esper-v1",
|
||||
"EQUAL",
|
||||
List.of(sessionId),
|
||||
1,
|
||||
Map.of("12:123", new RuntimeTachographDriverParityResultDto(
|
||||
"12:123",
|
||||
"EQUAL",
|
||||
"SINGLE_FILE_SESSION",
|
||||
1,
|
||||
true,
|
||||
List.of(new RuntimeTachographParityCategoryComparisonDto(
|
||||
"activityIntervals",
|
||||
2,
|
||||
2,
|
||||
true
|
||||
)),
|
||||
List.of("validated"),
|
||||
List.of()
|
||||
)),
|
||||
List.of("validation complete"),
|
||||
List.of()
|
||||
));
|
||||
|
||||
mockMvc.perform(post("/api/eventhub/runtime-processing/event-processing/validation/tachograph-parity")
|
||||
.contentType("application/json")
|
||||
.content("""
|
||||
{
|
||||
"sessionId": "%s",
|
||||
"driverKey": "12:123",
|
||||
"occurredFrom": "2026-05-01T08:00:00Z",
|
||||
"occurredTo": "2026-05-01T10:00:00Z",
|
||||
"includeDebug": true
|
||||
}
|
||||
""".formatted(sessionId)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.profileKey").value("tachograph-driver-esper-v1"))
|
||||
.andExpect(jsonPath("$.status").value("EQUAL"))
|
||||
.andExpect(jsonPath("$.driverResults['12:123'].status").value("EQUAL"))
|
||||
.andExpect(jsonPath("$.driverResults['12:123'].comparisons[0].category").value("activityIntervals"))
|
||||
.andExpect(jsonPath("$.driverResults['12:123'].comparisons[0].equal").value(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
void returnsBadRequestForInvalidRuntimeRequest() throws Exception {
|
||||
UnifiedRuntimeEventAssemblyService eventAssemblyService = org.mockito.Mockito.mock(UnifiedRuntimeEventAssemblyService.class);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,185 @@
|
|||
package at.procon.eventhub.processing.eventprocessing.validation;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import at.procon.eventhub.processing.dto.UnifiedRuntimeDerivedProjectionResultDto;
|
||||
import at.procon.eventhub.processing.eventprocessing.RuntimeEventProcessingService;
|
||||
import at.procon.eventhub.processing.eventprocessing.dto.RuntimeEventProcessingPartitionResultDto;
|
||||
import at.procon.eventhub.processing.eventprocessing.dto.RuntimeEventProcessingResultDto;
|
||||
import at.procon.eventhub.processing.eventprocessing.partition.RuntimeEventPartitioningStrategy;
|
||||
import at.procon.eventhub.processing.eventprocessing.profile.TachographDriverEsperRuntimeEventProcessingProfile;
|
||||
import at.procon.eventhub.processing.model.UnifiedRuntimeProcessingRequest;
|
||||
import at.procon.eventhub.tachographfilesession.dto.TachographEsperDriverProcessingResultDto;
|
||||
import at.procon.eventhub.tachographfilesession.model.DriverExtractionSession;
|
||||
import at.procon.eventhub.tachographfilesession.model.ExtractionStats;
|
||||
import at.procon.eventhub.tachographfilesession.model.TachographFileSession;
|
||||
import at.procon.eventhub.tachographfilesession.service.TachographCompositeSessionRepository;
|
||||
import at.procon.eventhub.tachographfilesession.service.TachographFileSessionProcessingService;
|
||||
import at.procon.eventhub.tachographfilesession.service.TachographFileSessionRepository;
|
||||
import java.time.Instant;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class RuntimeTachographParityValidationServiceTest {
|
||||
|
||||
@Test
|
||||
void reportsEqualWhenRuntimeProfileMatchesFileSessionReferenceCounts() {
|
||||
TachographFileSessionRepository fileSessionRepository = org.mockito.Mockito.mock(TachographFileSessionRepository.class);
|
||||
TachographCompositeSessionRepository compositeSessionRepository = org.mockito.Mockito.mock(TachographCompositeSessionRepository.class);
|
||||
TachographFileSessionProcessingService fileSessionProcessingService = org.mockito.Mockito.mock(TachographFileSessionProcessingService.class);
|
||||
RuntimeEventProcessingService runtimeEventProcessingService = org.mockito.Mockito.mock(RuntimeEventProcessingService.class);
|
||||
RuntimeTachographParityValidationService service = new RuntimeTachographParityValidationService(
|
||||
fileSessionRepository,
|
||||
compositeSessionRepository,
|
||||
fileSessionProcessingService,
|
||||
runtimeEventProcessingService
|
||||
);
|
||||
|
||||
UUID sessionId = UUID.randomUUID();
|
||||
String driverKey = "12:123";
|
||||
TachographFileSession session = session(sessionId, driverKey);
|
||||
when(fileSessionRepository.find(sessionId)).thenReturn(Optional.of(session));
|
||||
when(fileSessionProcessingService.getEsperDriverProcessingResults(eq(sessionId), eq(driverKey), any()))
|
||||
.thenReturn(projection(sessionId, driverKey, 2, 1, 1));
|
||||
|
||||
UnifiedRuntimeProcessingRequest runtimeRequest = UnifiedRuntimeProcessingRequest.forTachographFileSession(
|
||||
sessionId,
|
||||
driverKey,
|
||||
OffsetDateTime.parse("2026-05-01T08:00:00Z"),
|
||||
OffsetDateTime.parse("2026-05-01T10:00:00Z"),
|
||||
true,
|
||||
0
|
||||
);
|
||||
UnifiedRuntimeDerivedProjectionResultDto runtimeDriverResult = new UnifiedRuntimeDerivedProjectionResultDto(
|
||||
runtimeRequest,
|
||||
4,
|
||||
1,
|
||||
0,
|
||||
4,
|
||||
List.of(),
|
||||
projection(sessionId, driverKey, 2, 1, 1),
|
||||
List.of()
|
||||
);
|
||||
when(runtimeEventProcessingService.process(any()))
|
||||
.thenReturn(new RuntimeEventProcessingResultDto(
|
||||
TachographDriverEsperRuntimeEventProcessingProfile.PROFILE_KEY,
|
||||
RuntimeEventPartitioningStrategy.DRIVER,
|
||||
runtimeRequest,
|
||||
4,
|
||||
1,
|
||||
1,
|
||||
List.of(),
|
||||
Map.of(driverKey, new RuntimeEventProcessingPartitionResultDto(
|
||||
"DRIVER",
|
||||
driverKey,
|
||||
"UnifiedRuntimeDerivedProjectionResultDto",
|
||||
runtimeDriverResult,
|
||||
Map.of()
|
||||
)),
|
||||
List.of(),
|
||||
List.of()
|
||||
));
|
||||
|
||||
RuntimeTachographParityValidationResultDto result = service.validate(new RuntimeTachographParityValidationApiRequest(
|
||||
sessionId,
|
||||
List.of(),
|
||||
null,
|
||||
driverKey,
|
||||
Set.of(),
|
||||
false,
|
||||
OffsetDateTime.parse("2026-05-01T08:00:00Z"),
|
||||
OffsetDateTime.parse("2026-05-01T10:00:00Z"),
|
||||
true,
|
||||
0,
|
||||
3,
|
||||
720,
|
||||
true
|
||||
));
|
||||
|
||||
assertThat(result.status()).isEqualTo("EQUAL");
|
||||
assertThat(result.driverResults()).containsKey(driverKey);
|
||||
assertThat(result.driverResults().get(driverKey).comparisons())
|
||||
.anySatisfy(comparison -> {
|
||||
assertThat(comparison.category()).isEqualTo("activityIntervals");
|
||||
assertThat(comparison.fileSessionCount()).isEqualTo(2);
|
||||
assertThat(comparison.runtimeCount()).isEqualTo(2);
|
||||
assertThat(comparison.equal()).isTrue();
|
||||
});
|
||||
}
|
||||
|
||||
private TachographFileSession session(UUID sessionId, String driverKey) {
|
||||
DriverExtractionSession driver = new DriverExtractionSession(
|
||||
driverKey,
|
||||
null,
|
||||
null,
|
||||
List.of(),
|
||||
List.of(),
|
||||
List.of(),
|
||||
List.of(),
|
||||
List.of(),
|
||||
List.of()
|
||||
);
|
||||
return new TachographFileSession(
|
||||
sessionId,
|
||||
null,
|
||||
Map.of(driverKey, driver),
|
||||
new ExtractionStats(1, 0, 0, 0, 0, 0),
|
||||
List.of(),
|
||||
Instant.now(),
|
||||
Instant.now().plusSeconds(3600)
|
||||
);
|
||||
}
|
||||
|
||||
private TachographEsperDriverProcessingResultDto projection(
|
||||
UUID sessionId,
|
||||
String driverKey,
|
||||
int activityCount,
|
||||
int drivingCount,
|
||||
int interruptionCount
|
||||
) {
|
||||
return new TachographEsperDriverProcessingResultDto(
|
||||
sessionId,
|
||||
driverKey,
|
||||
"DRIVER_CARD",
|
||||
OffsetDateTime.parse("2026-05-01T08:00:00Z"),
|
||||
OffsetDateTime.parse("2026-05-01T10:00:00Z"),
|
||||
OffsetDateTime.parse("2026-05-01T08:00:00Z"),
|
||||
OffsetDateTime.parse("2026-05-01T10:00:00Z"),
|
||||
activityCount,
|
||||
drivingCount,
|
||||
interruptionCount,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
List.of(),
|
||||
List.of(),
|
||||
List.of(),
|
||||
List.of(),
|
||||
List.of(),
|
||||
List.of(),
|
||||
List.of(),
|
||||
List.of(),
|
||||
List.of(),
|
||||
List.of(),
|
||||
List.of(),
|
||||
List.of(),
|
||||
List.of(),
|
||||
List.of()
|
||||
);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue