Align driver card identity normalization
This commit is contained in:
parent
33e9cb62c3
commit
4535f620fc
|
|
@ -1,5 +1,6 @@
|
||||||
package at.procon.eventhub.dto;
|
package at.procon.eventhub.dto;
|
||||||
|
|
||||||
|
import at.procon.eventhub.reference.DriverCardNumberNormalizer;
|
||||||
import at.procon.eventhub.reference.TachographNationRegistry;
|
import at.procon.eventhub.reference.TachographNationRegistry;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -43,6 +44,6 @@ public record DriverCardRefDto(
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String normalizeNullable(String value) {
|
private static String normalizeNullable(String value) {
|
||||||
return value == null || value.isBlank() ? null : value.trim();
|
return DriverCardNumberNormalizer.canonical(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ package at.procon.eventhub.persistence;
|
||||||
|
|
||||||
import at.procon.eventhub.dto.DriverCardRefDto;
|
import at.procon.eventhub.dto.DriverCardRefDto;
|
||||||
import at.procon.eventhub.dto.DriverRefDto;
|
import at.procon.eventhub.dto.DriverRefDto;
|
||||||
|
import at.procon.eventhub.reference.DriverCardNumberNormalizer;
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
|
|
@ -16,9 +17,6 @@ import org.springframework.transaction.annotation.Transactional;
|
||||||
@Repository
|
@Repository
|
||||||
public class DriverIdentityRepository {
|
public class DriverIdentityRepository {
|
||||||
|
|
||||||
private static final String YELLOWFOX_SYNTHETIC_REFERENCE_NATION = "YELLOWFOX";
|
|
||||||
private static final String UNKNOWN_CARD_NATION = "UNKNOWN";
|
|
||||||
|
|
||||||
private final JdbcTemplate jdbcTemplate;
|
private final JdbcTemplate jdbcTemplate;
|
||||||
private final ObjectMapper objectMapper;
|
private final ObjectMapper objectMapper;
|
||||||
|
|
||||||
|
|
@ -41,7 +39,7 @@ public class DriverIdentityRepository {
|
||||||
DriverCardRefDto driverCard = driverRef.driverCard();
|
DriverCardRefDto driverCard = driverRef.driverCard();
|
||||||
String cardNation = driverCard == null ? null : normalizeNullable(driverCard.nation());
|
String cardNation = driverCard == null ? null : normalizeNullable(driverCard.nation());
|
||||||
Integer cardNationNumericCode = driverCard == null ? null : driverCard.nationNumericCode();
|
Integer cardNationNumericCode = driverCard == null ? null : driverCard.nationNumericCode();
|
||||||
String cardNumber = driverCard == null ? null : normalizeDriverCardNumber(cardNation, driverCard.number());
|
String cardNumber = driverCard == null ? null : normalizeDriverCardNumber(driverCard.number());
|
||||||
|
|
||||||
UUID driverId = findBySourceDriverEntityId(normalizedTenantKey, eventSourceId, sourceDriverEntityId);
|
UUID driverId = findBySourceDriverEntityId(normalizedTenantKey, eventSourceId, sourceDriverEntityId);
|
||||||
UUID driverCardId = resolveOrCreateDriverCardId(cardNation, cardNationNumericCode, cardNumber, driverId);
|
UUID driverCardId = resolveOrCreateDriverCardId(cardNation, cardNationNumericCode, cardNumber, driverId);
|
||||||
|
|
@ -782,20 +780,8 @@ public class DriverIdentityRepository {
|
||||||
return legacyColumns != null && legacyColumns == 3;
|
return legacyColumns != null && legacyColumns == 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String normalizeDriverCardNumber(String cardNation, String cardNumber) {
|
private String normalizeDriverCardNumber(String cardNumber) {
|
||||||
String normalized = normalizeNullable(cardNumber);
|
return DriverCardNumberNormalizer.canonical(cardNumber);
|
||||||
if (normalized == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (isSyntheticYellowFoxCardNation(cardNation)) {
|
|
||||||
return normalized.length() <= 14 ? normalized : normalized.substring(0, 14);
|
|
||||||
}
|
|
||||||
return normalized;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isSyntheticYellowFoxCardNation(String cardNation) {
|
|
||||||
return YELLOWFOX_SYNTHETIC_REFERENCE_NATION.equalsIgnoreCase(cardNation)
|
|
||||||
|| UNKNOWN_CARD_NATION.equalsIgnoreCase(cardNation);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private UUID createDriverCard(
|
private UUID createDriverCard(
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package at.procon.eventhub.processing.model;
|
package at.procon.eventhub.processing.model;
|
||||||
|
|
||||||
|
import at.procon.eventhub.reference.DriverCardNumberNormalizer;
|
||||||
import java.time.OffsetDateTime;
|
import java.time.OffsetDateTime;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
@ -25,7 +26,7 @@ public record UnifiedDriverEventsRequest(
|
||||||
tenantKey = normalize(tenantKey);
|
tenantKey = normalize(tenantKey);
|
||||||
driverSourceEntityId = normalize(driverSourceEntityId);
|
driverSourceEntityId = normalize(driverSourceEntityId);
|
||||||
driverCardNation = normalizeUpper(driverCardNation);
|
driverCardNation = normalizeUpper(driverCardNation);
|
||||||
driverCardNumber = normalize(driverCardNumber);
|
driverCardNumber = normalizeDriverCardNumber(driverCardNumber);
|
||||||
vehicleSourceEntityId = normalize(vehicleSourceEntityId);
|
vehicleSourceEntityId = normalize(vehicleSourceEntityId);
|
||||||
vin = normalizeUpper(vin);
|
vin = normalizeUpper(vin);
|
||||||
registrationNation = normalizeUpper(registrationNation);
|
registrationNation = normalizeUpper(registrationNation);
|
||||||
|
|
@ -171,4 +172,8 @@ public record UnifiedDriverEventsRequest(
|
||||||
private static String normalizeUpper(String value) {
|
private static String normalizeUpper(String value) {
|
||||||
return value == null || value.isBlank() ? null : value.trim().toUpperCase();
|
return value == null || value.isBlank() ? null : value.trim().toUpperCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static String normalizeDriverCardNumber(String value) {
|
||||||
|
return DriverCardNumberNormalizer.canonical(value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package at.procon.eventhub.processing.model;
|
package at.procon.eventhub.processing.model;
|
||||||
|
|
||||||
|
import at.procon.eventhub.reference.DriverCardNumberNormalizer;
|
||||||
import java.time.OffsetDateTime;
|
import java.time.OffsetDateTime;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
@ -23,7 +24,7 @@ public record UnifiedRuntimeProcessingRequest(
|
||||||
tenantKey = normalize(tenantKey);
|
tenantKey = normalize(tenantKey);
|
||||||
driverSourceEntityId = normalize(driverSourceEntityId);
|
driverSourceEntityId = normalize(driverSourceEntityId);
|
||||||
driverCardNation = normalizeUpper(driverCardNation);
|
driverCardNation = normalizeUpper(driverCardNation);
|
||||||
driverCardNumber = normalize(driverCardNumber);
|
driverCardNumber = normalizeDriverCardNumber(driverCardNumber);
|
||||||
boolean includesFileSession = sourceFamilies != null && sourceFamilies.contains(UnifiedEventSourceFamily.TACHOGRAPH_FILE_SESSION);
|
boolean includesFileSession = sourceFamilies != null && sourceFamilies.contains(UnifiedEventSourceFamily.TACHOGRAPH_FILE_SESSION);
|
||||||
boolean includesExternalDb = sourceFamilies != null && sourceFamilies.stream()
|
boolean includesExternalDb = sourceFamilies != null && sourceFamilies.stream()
|
||||||
.anyMatch(family -> family == UnifiedEventSourceFamily.TACHOGRAPH_DB || family == UnifiedEventSourceFamily.YELLOWFOX_DB);
|
.anyMatch(family -> family == UnifiedEventSourceFamily.TACHOGRAPH_DB || family == UnifiedEventSourceFamily.YELLOWFOX_DB);
|
||||||
|
|
@ -196,4 +197,8 @@ public record UnifiedRuntimeProcessingRequest(
|
||||||
private static String normalizeUpper(String value) {
|
private static String normalizeUpper(String value) {
|
||||||
return value == null || value.isBlank() ? null : value.trim().toUpperCase();
|
return value == null || value.isBlank() ? null : value.trim().toUpperCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static String normalizeDriverCardNumber(String value) {
|
||||||
|
return DriverCardNumberNormalizer.canonical(value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -136,6 +136,7 @@ public class UnifiedEventTimelineReconstructor {
|
||||||
BigDecimal longitude = event.position() == null ? null : event.position().longitude();
|
BigDecimal longitude = event.position() == null ? null : event.position().longitude();
|
||||||
result.add(new ExtractedSupportEvent(
|
result.add(new ExtractedSupportEvent(
|
||||||
eventId,
|
eventId,
|
||||||
|
text(raw, "driverKey"),
|
||||||
event.occurredAt(),
|
event.occurredAt(),
|
||||||
event.eventDomain().name(),
|
event.eventDomain().name(),
|
||||||
text(raw, "supportEventType") == null ? event.eventType().name() : text(raw, "supportEventType"),
|
text(raw, "supportEventType") == null ? event.eventType().name() : text(raw, "supportEventType"),
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
package at.procon.eventhub.reference;
|
||||||
|
|
||||||
|
public final class DriverCardNumberNormalizer {
|
||||||
|
|
||||||
|
public static final int CANONICAL_LENGTH = 14;
|
||||||
|
|
||||||
|
private DriverCardNumberNormalizer() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String canonical(String rawCardNumber) {
|
||||||
|
String normalized = normalize(rawCardNumber);
|
||||||
|
if (normalized == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return normalized.length() <= CANONICAL_LENGTH
|
||||||
|
? normalized
|
||||||
|
: normalized.substring(0, CANONICAL_LENGTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String full(String rawCardNumber) {
|
||||||
|
return normalize(rawCardNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String normalize(String value) {
|
||||||
|
if (value == null || value.isBlank()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return value.trim().toUpperCase();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -6,6 +6,7 @@ public record ExtractedDriverCard(
|
||||||
String sourceDriverCardId,
|
String sourceDriverCardId,
|
||||||
String cardNation,
|
String cardNation,
|
||||||
String cardNumber,
|
String cardNumber,
|
||||||
|
String fullCardNumber,
|
||||||
String issuingAuthorityName,
|
String issuingAuthorityName,
|
||||||
OffsetDateTime issueDate,
|
OffsetDateTime issueDate,
|
||||||
OffsetDateTime validityBegin,
|
OffsetDateTime validityBegin,
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import java.time.OffsetDateTime;
|
||||||
|
|
||||||
public record ExtractedSupportEvent(
|
public record ExtractedSupportEvent(
|
||||||
String eventId,
|
String eventId,
|
||||||
|
String driverKey,
|
||||||
OffsetDateTime occurredAt,
|
OffsetDateTime occurredAt,
|
||||||
String eventDomain,
|
String eventDomain,
|
||||||
String eventType,
|
String eventType,
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,7 @@ public class DriverCardXmlExtractionService {
|
||||||
driverKeyFactory.createSourceDriverCardId(driverKey),
|
driverKeyFactory.createSourceDriverCardId(driverKey),
|
||||||
driverCard.cardNation(),
|
driverCard.cardNation(),
|
||||||
driverCard.cardNumber(),
|
driverCard.cardNumber(),
|
||||||
|
driverCard.fullCardNumber(),
|
||||||
driverCard.issuingAuthorityName(),
|
driverCard.issuingAuthorityName(),
|
||||||
driverCard.issueDate(),
|
driverCard.issueDate(),
|
||||||
driverCard.validityBegin(),
|
driverCard.validityBegin(),
|
||||||
|
|
@ -73,7 +74,7 @@ public class DriverCardXmlExtractionService {
|
||||||
extractVehicleUsageIntervals(document, registrationsByKey, vehiclesByKey, warnings);
|
extractVehicleUsageIntervals(document, registrationsByKey, vehiclesByKey, warnings);
|
||||||
List<ExtractedCardActivityInterval> activityIntervals =
|
List<ExtractedCardActivityInterval> activityIntervals =
|
||||||
assignVehicleCoverage(extractActivityIntervals(document, warnings), vehicleUsageIntervals);
|
assignVehicleCoverage(extractActivityIntervals(document, warnings), vehicleUsageIntervals);
|
||||||
List<ExtractedSupportEvent> supportEvents = extractSupportEvents(document, vehicleUsageIntervals, warnings);
|
List<ExtractedSupportEvent> supportEvents = extractSupportEvents(document, driverKey, vehicleUsageIntervals, warnings);
|
||||||
|
|
||||||
DriverExtractionSession driverSession = new DriverExtractionSession(
|
DriverExtractionSession driverSession = new DriverExtractionSession(
|
||||||
driverKey,
|
driverKey,
|
||||||
|
|
@ -114,12 +115,14 @@ public class DriverCardXmlExtractionService {
|
||||||
}
|
}
|
||||||
Element cardIdentification = child(identification, "cardIdentification");
|
Element cardIdentification = child(identification, "cardIdentification");
|
||||||
String cardNation = childText(cardIdentification, "cardIssuingMemberState");
|
String cardNation = childText(cardIdentification, "cardIssuingMemberState");
|
||||||
String cardNumber = joinCardNumber(identification);
|
String fullCardNumber = joinCardNumber(identification);
|
||||||
|
String cardNumber = driverKeyFactory.canonicalCardNumber(fullCardNumber);
|
||||||
String authority = childText(child(cardIdentification, "cardIssuingAuthorityName"), "name");
|
String authority = childText(child(cardIdentification, "cardIssuingAuthorityName"), "name");
|
||||||
return new ExtractedDriverCard(
|
return new ExtractedDriverCard(
|
||||||
null,
|
null,
|
||||||
cardNation,
|
cardNation,
|
||||||
cardNumber,
|
cardNumber,
|
||||||
|
fullCardNumber,
|
||||||
authority,
|
authority,
|
||||||
offsetDateTime(childText(cardIdentification, "cardIssueDate")),
|
offsetDateTime(childText(cardIdentification, "cardIssueDate")),
|
||||||
offsetDateTime(childText(cardIdentification, "cardValidityBegin")),
|
offsetDateTime(childText(cardIdentification, "cardValidityBegin")),
|
||||||
|
|
@ -307,17 +310,18 @@ public class DriverCardXmlExtractionService {
|
||||||
|
|
||||||
private List<ExtractedSupportEvent> extractSupportEvents(
|
private List<ExtractedSupportEvent> extractSupportEvents(
|
||||||
Document document,
|
Document document,
|
||||||
|
String driverKey,
|
||||||
List<ExtractedCardVehicleUsageInterval> vehicleUsageIntervals,
|
List<ExtractedCardVehicleUsageInterval> vehicleUsageIntervals,
|
||||||
List<ExtractionWarning> warnings
|
List<ExtractionWarning> warnings
|
||||||
) {
|
) {
|
||||||
VehicleUsageLookup vehicleUsageLookup = new VehicleUsageLookup(vehicleUsageIntervals);
|
VehicleUsageLookup vehicleUsageLookup = new VehicleUsageLookup(vehicleUsageIntervals);
|
||||||
List<ExtractedSupportEvent> supportEvents = new ArrayList<>();
|
List<ExtractedSupportEvent> supportEvents = new ArrayList<>();
|
||||||
Element root = document.getDocumentElement();
|
Element root = document.getDocumentElement();
|
||||||
extractCardPlaceSupportEvents(root, vehicleUsageLookup, supportEvents, warnings);
|
extractCardPlaceSupportEvents(root, driverKey, vehicleUsageLookup, supportEvents, warnings);
|
||||||
extractCardGnssSupportEvents(root, vehicleUsageLookup, supportEvents, warnings);
|
extractCardGnssSupportEvents(root, driverKey, vehicleUsageLookup, supportEvents, warnings);
|
||||||
extractCardSpecificConditionSupportEvents(root, vehicleUsageLookup, supportEvents, warnings);
|
extractCardSpecificConditionSupportEvents(root, driverKey, vehicleUsageLookup, supportEvents, warnings);
|
||||||
extractCardBorderCrossingSupportEvents(root, vehicleUsageLookup, supportEvents, warnings);
|
extractCardBorderCrossingSupportEvents(root, driverKey, vehicleUsageLookup, supportEvents, warnings);
|
||||||
extractCardLoadUnloadSupportEvents(root, vehicleUsageLookup, supportEvents, warnings);
|
extractCardLoadUnloadSupportEvents(root, driverKey, vehicleUsageLookup, supportEvents, warnings);
|
||||||
supportEvents.sort(Comparator.comparing(ExtractedSupportEvent::occurredAt)
|
supportEvents.sort(Comparator.comparing(ExtractedSupportEvent::occurredAt)
|
||||||
.thenComparing(ExtractedSupportEvent::eventDomain, Comparator.nullsLast(String::compareTo))
|
.thenComparing(ExtractedSupportEvent::eventDomain, Comparator.nullsLast(String::compareTo))
|
||||||
.thenComparing(ExtractedSupportEvent::eventId, Comparator.nullsLast(String::compareTo)));
|
.thenComparing(ExtractedSupportEvent::eventId, Comparator.nullsLast(String::compareTo)));
|
||||||
|
|
@ -326,6 +330,7 @@ public class DriverCardXmlExtractionService {
|
||||||
|
|
||||||
private void extractCardPlaceSupportEvents(
|
private void extractCardPlaceSupportEvents(
|
||||||
Element root,
|
Element root,
|
||||||
|
String driverKey,
|
||||||
VehicleUsageLookup vehicleUsageLookup,
|
VehicleUsageLookup vehicleUsageLookup,
|
||||||
List<ExtractedSupportEvent> supportEvents,
|
List<ExtractedSupportEvent> supportEvents,
|
||||||
List<ExtractionWarning> warnings
|
List<ExtractionWarning> warnings
|
||||||
|
|
@ -344,6 +349,10 @@ public class DriverCardXmlExtractionService {
|
||||||
}
|
}
|
||||||
|
|
||||||
ExtractedCardVehicleUsageInterval usage = vehicleUsageLookup.resolve(occurredAt);
|
ExtractedCardVehicleUsageInterval usage = vehicleUsageLookup.resolve(occurredAt);
|
||||||
|
if (!hasKnownRegistration(usage)) {
|
||||||
|
warnings.add(new ExtractionWarning("CARD_PLACE_UNKNOWN_VRN", "Driver-card place record has unknown vehicle registration and was ignored.", path));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
Element gnss = child(record, "entryGnssPlaceRecord");
|
Element gnss = child(record, "entryGnssPlaceRecord");
|
||||||
Element geoCoordinates = child(gnss, "geoCoordinates");
|
Element geoCoordinates = child(gnss, "geoCoordinates");
|
||||||
BigDecimal latitude = geoCoordinate(geoCoordinates, "latitude", true);
|
BigDecimal latitude = geoCoordinate(geoCoordinates, "latitude", true);
|
||||||
|
|
@ -352,6 +361,7 @@ public class DriverCardXmlExtractionService {
|
||||||
String entryType = childText(record, "entryTypeDailyWorkPeriod");
|
String entryType = childText(record, "entryTypeDailyWorkPeriod");
|
||||||
supportEvents.add(new ExtractedSupportEvent(
|
supportEvents.add(new ExtractedSupportEvent(
|
||||||
"CARDPLACE-" + (i + 1),
|
"CARDPLACE-" + (i + 1),
|
||||||
|
driverKey,
|
||||||
occurredAt,
|
occurredAt,
|
||||||
"PLACE",
|
"PLACE",
|
||||||
mapPlaceEntryType(entryType),
|
mapPlaceEntryType(entryType),
|
||||||
|
|
@ -379,6 +389,7 @@ public class DriverCardXmlExtractionService {
|
||||||
|
|
||||||
private void extractCardGnssSupportEvents(
|
private void extractCardGnssSupportEvents(
|
||||||
Element root,
|
Element root,
|
||||||
|
String driverKey,
|
||||||
VehicleUsageLookup vehicleUsageLookup,
|
VehicleUsageLookup vehicleUsageLookup,
|
||||||
List<ExtractedSupportEvent> supportEvents,
|
List<ExtractedSupportEvent> supportEvents,
|
||||||
List<ExtractionWarning> warnings
|
List<ExtractionWarning> warnings
|
||||||
|
|
@ -397,6 +408,11 @@ public class DriverCardXmlExtractionService {
|
||||||
}
|
}
|
||||||
|
|
||||||
ExtractedCardVehicleUsageInterval usage = vehicleUsageLookup.resolve(occurredAt);
|
ExtractedCardVehicleUsageInterval usage = vehicleUsageLookup.resolve(occurredAt);
|
||||||
|
if (!hasKnownRegistration(usage)) {
|
||||||
|
warnings.add(new ExtractionWarning("CARD_GNSS_MISSING_VRN", "Driver-card GNSS record is missing vehicle registration.", path));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
Element gnss = child(record, "gnssPlaceRecord");
|
Element gnss = child(record, "gnssPlaceRecord");
|
||||||
Element geoCoordinates = child(gnss, "geoCoordinates");
|
Element geoCoordinates = child(gnss, "geoCoordinates");
|
||||||
BigDecimal latitude = geoCoordinate(geoCoordinates, "latitude", true);
|
BigDecimal latitude = geoCoordinate(geoCoordinates, "latitude", true);
|
||||||
|
|
@ -404,6 +420,7 @@ public class DriverCardXmlExtractionService {
|
||||||
String authenticationStatus = normalizeToken(childText(gnss, "authenticationStatus"));
|
String authenticationStatus = normalizeToken(childText(gnss, "authenticationStatus"));
|
||||||
supportEvents.add(new ExtractedSupportEvent(
|
supportEvents.add(new ExtractedSupportEvent(
|
||||||
"CARDGNSS-" + (i + 1),
|
"CARDGNSS-" + (i + 1),
|
||||||
|
driverKey,
|
||||||
occurredAt,
|
occurredAt,
|
||||||
"POSITION",
|
"POSITION",
|
||||||
"POSITION_RECORDED",
|
"POSITION_RECORDED",
|
||||||
|
|
@ -431,6 +448,7 @@ public class DriverCardXmlExtractionService {
|
||||||
|
|
||||||
private void extractCardSpecificConditionSupportEvents(
|
private void extractCardSpecificConditionSupportEvents(
|
||||||
Element root,
|
Element root,
|
||||||
|
String driverKey,
|
||||||
VehicleUsageLookup vehicleUsageLookup,
|
VehicleUsageLookup vehicleUsageLookup,
|
||||||
List<ExtractedSupportEvent> supportEvents,
|
List<ExtractedSupportEvent> supportEvents,
|
||||||
List<ExtractionWarning> warnings
|
List<ExtractionWarning> warnings
|
||||||
|
|
@ -449,10 +467,15 @@ public class DriverCardXmlExtractionService {
|
||||||
}
|
}
|
||||||
|
|
||||||
ExtractedCardVehicleUsageInterval usage = vehicleUsageLookup.resolve(occurredAt);
|
ExtractedCardVehicleUsageInterval usage = vehicleUsageLookup.resolve(occurredAt);
|
||||||
|
if (!hasKnownRegistration(usage)) {
|
||||||
|
warnings.add(new ExtractionWarning("CARD_SPECIFIC_CONDITION_UNKNOWN_VRN", "Driver-card specific-condition record has unknown vehicle registration and was ignored.", path));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
String conditionCode = normalizeToken(childText(record, "specificConditionType"));
|
String conditionCode = normalizeToken(childText(record, "specificConditionType"));
|
||||||
String[] specificCondition = mapSpecificCondition(conditionCode);
|
String[] specificCondition = mapSpecificCondition(conditionCode);
|
||||||
supportEvents.add(new ExtractedSupportEvent(
|
supportEvents.add(new ExtractedSupportEvent(
|
||||||
"CARDSC-" + (i + 1),
|
"CARDSC-" + (i + 1),
|
||||||
|
driverKey,
|
||||||
occurredAt,
|
occurredAt,
|
||||||
"SPECIFIC_CONDITION",
|
"SPECIFIC_CONDITION",
|
||||||
specificCondition[0],
|
specificCondition[0],
|
||||||
|
|
@ -480,6 +503,7 @@ public class DriverCardXmlExtractionService {
|
||||||
|
|
||||||
private void extractCardBorderCrossingSupportEvents(
|
private void extractCardBorderCrossingSupportEvents(
|
||||||
Element root,
|
Element root,
|
||||||
|
String driverKey,
|
||||||
VehicleUsageLookup vehicleUsageLookup,
|
VehicleUsageLookup vehicleUsageLookup,
|
||||||
List<ExtractedSupportEvent> supportEvents,
|
List<ExtractedSupportEvent> supportEvents,
|
||||||
List<ExtractionWarning> warnings
|
List<ExtractionWarning> warnings
|
||||||
|
|
@ -499,12 +523,17 @@ public class DriverCardXmlExtractionService {
|
||||||
}
|
}
|
||||||
|
|
||||||
ExtractedCardVehicleUsageInterval usage = vehicleUsageLookup.resolve(occurredAt);
|
ExtractedCardVehicleUsageInterval usage = vehicleUsageLookup.resolve(occurredAt);
|
||||||
|
if (!hasKnownRegistration(usage)) {
|
||||||
|
warnings.add(new ExtractionWarning("CARD_BORDER_CROSSING_UNKNOWN_VRN", "Driver-card border-crossing record has unknown vehicle registration and was ignored.", path));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
Element geoCoordinates = child(gnss, "geoCoordinates");
|
Element geoCoordinates = child(gnss, "geoCoordinates");
|
||||||
BigDecimal latitude = geoCoordinate(geoCoordinates, "latitude", true);
|
BigDecimal latitude = geoCoordinate(geoCoordinates, "latitude", true);
|
||||||
BigDecimal longitude = geoCoordinate(geoCoordinates, "longitude", false);
|
BigDecimal longitude = geoCoordinate(geoCoordinates, "longitude", false);
|
||||||
String authenticationStatus = normalizeToken(childText(gnss, "authenticationStatus"));
|
String authenticationStatus = normalizeToken(childText(gnss, "authenticationStatus"));
|
||||||
supportEvents.add(new ExtractedSupportEvent(
|
supportEvents.add(new ExtractedSupportEvent(
|
||||||
"CARDBORDER-" + (i + 1),
|
"CARDBORDER-" + (i + 1),
|
||||||
|
driverKey,
|
||||||
occurredAt,
|
occurredAt,
|
||||||
"BORDER_CROSSING",
|
"BORDER_CROSSING",
|
||||||
"BORDER_OUTBOUND",
|
"BORDER_OUTBOUND",
|
||||||
|
|
@ -532,6 +561,7 @@ public class DriverCardXmlExtractionService {
|
||||||
|
|
||||||
private void extractCardLoadUnloadSupportEvents(
|
private void extractCardLoadUnloadSupportEvents(
|
||||||
Element root,
|
Element root,
|
||||||
|
String driverKey,
|
||||||
VehicleUsageLookup vehicleUsageLookup,
|
VehicleUsageLookup vehicleUsageLookup,
|
||||||
List<ExtractedSupportEvent> supportEvents,
|
List<ExtractedSupportEvent> supportEvents,
|
||||||
List<ExtractionWarning> warnings
|
List<ExtractionWarning> warnings
|
||||||
|
|
@ -550,6 +580,10 @@ public class DriverCardXmlExtractionService {
|
||||||
}
|
}
|
||||||
|
|
||||||
ExtractedCardVehicleUsageInterval usage = vehicleUsageLookup.resolve(occurredAt);
|
ExtractedCardVehicleUsageInterval usage = vehicleUsageLookup.resolve(occurredAt);
|
||||||
|
if (!hasKnownRegistration(usage)) {
|
||||||
|
warnings.add(new ExtractionWarning("CARD_LOAD_UNLOAD_UNKNOWN_VRN", "Driver-card load/unload record has unknown vehicle registration and was ignored.", path));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
Element gnss = child(record, "gnssPlaceAuthRecord");
|
Element gnss = child(record, "gnssPlaceAuthRecord");
|
||||||
Element geoCoordinates = child(gnss, "geoCoordinates");
|
Element geoCoordinates = child(gnss, "geoCoordinates");
|
||||||
BigDecimal latitude = geoCoordinate(geoCoordinates, "latitude", true);
|
BigDecimal latitude = geoCoordinate(geoCoordinates, "latitude", true);
|
||||||
|
|
@ -558,6 +592,7 @@ public class DriverCardXmlExtractionService {
|
||||||
String operation = mapOperation(childText(record, "operationType"));
|
String operation = mapOperation(childText(record, "operationType"));
|
||||||
supportEvents.add(new ExtractedSupportEvent(
|
supportEvents.add(new ExtractedSupportEvent(
|
||||||
"CARDLOAD-" + (i + 1),
|
"CARDLOAD-" + (i + 1),
|
||||||
|
driverKey,
|
||||||
occurredAt,
|
occurredAt,
|
||||||
"LOAD_UNLOAD",
|
"LOAD_UNLOAD",
|
||||||
operation,
|
operation,
|
||||||
|
|
@ -640,6 +675,17 @@ public class DriverCardXmlExtractionService {
|
||||||
return !usage.from().isAfter(timestamp) && timestamp.isBefore(usageEndExclusive(usage, null));
|
return !usage.from().isAfter(timestamp) && timestamp.isBefore(usageEndExclusive(usage, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean hasKnownRegistration(ExtractedCardVehicleUsageInterval usage) {
|
||||||
|
return usage != null && hasKnownRegistrationKey(usage.registrationKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasKnownRegistrationKey(String registrationKey) {
|
||||||
|
return registrationKey != null
|
||||||
|
&& !registrationKey.isBlank()
|
||||||
|
&& !registrationKey.startsWith("UNKNOWN:")
|
||||||
|
&& !registrationKey.endsWith(":UNKNOWN");
|
||||||
|
}
|
||||||
|
|
||||||
private OffsetDateTime usageEndExclusive(ExtractedCardVehicleUsageInterval usage, OffsetDateTime fallbackExclusiveEnd) {
|
private OffsetDateTime usageEndExclusive(ExtractedCardVehicleUsageInterval usage, OffsetDateTime fallbackExclusiveEnd) {
|
||||||
if (usage.to() == null) {
|
if (usage.to() == null) {
|
||||||
return fallbackExclusiveEnd == null ? OffsetDateTime.MAX : fallbackExclusiveEnd;
|
return fallbackExclusiveEnd == null ? OffsetDateTime.MAX : fallbackExclusiveEnd;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package at.procon.eventhub.tachographfilesession.service;
|
package at.procon.eventhub.tachographfilesession.service;
|
||||||
|
|
||||||
|
import at.procon.eventhub.reference.DriverCardNumberNormalizer;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
|
|
@ -7,10 +8,18 @@ public class DriverKeyFactory {
|
||||||
|
|
||||||
public String createDriverKey(String cardNation, String cardNumber) {
|
public String createDriverKey(String cardNation, String cardNumber) {
|
||||||
String normalizedNation = normalize(cardNation, "UNKNOWN");
|
String normalizedNation = normalize(cardNation, "UNKNOWN");
|
||||||
String normalizedCardNumber = normalize(cardNumber, "UNKNOWN");
|
String normalizedCardNumber = normalize(canonicalCardNumber(cardNumber), "UNKNOWN");
|
||||||
return normalizedNation + ":" + normalizedCardNumber;
|
return normalizedNation + ":" + normalizedCardNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String canonicalCardNumber(String cardNumber) {
|
||||||
|
return DriverCardNumberNormalizer.canonical(cardNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String fullCardNumber(String cardNumber) {
|
||||||
|
return DriverCardNumberNormalizer.full(cardNumber);
|
||||||
|
}
|
||||||
|
|
||||||
public String createSourceDriverId(String driverKey) {
|
public String createSourceDriverId(String driverKey) {
|
||||||
return "DRV:" + driverKey;
|
return "DRV:" + driverKey;
|
||||||
}
|
}
|
||||||
|
|
@ -23,6 +32,6 @@ public class DriverKeyFactory {
|
||||||
if (value == null || value.isBlank()) {
|
if (value == null || value.isBlank()) {
|
||||||
return fallback;
|
return fallback;
|
||||||
}
|
}
|
||||||
return value.trim();
|
return value.trim().toUpperCase();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -111,9 +111,7 @@ public class IntervalBackedDriverTimelineEventBuilder implements DriverTimelineE
|
||||||
eventSource,
|
eventSource,
|
||||||
sourcePackageRef
|
sourcePackageRef
|
||||||
);
|
);
|
||||||
List<EventHubEventDto> supportEvents = List.of();
|
List<EventHubEventDto> supportEvents = buildSupportEvents(
|
||||||
/*
|
|
||||||
buildSupportEvents(
|
|
||||||
session,
|
session,
|
||||||
timeline.supportEvents(),
|
timeline.supportEvents(),
|
||||||
driverRef,
|
driverRef,
|
||||||
|
|
@ -122,7 +120,6 @@ public class IntervalBackedDriverTimelineEventBuilder implements DriverTimelineE
|
||||||
eventSource,
|
eventSource,
|
||||||
sourcePackageRef
|
sourcePackageRef
|
||||||
);
|
);
|
||||||
*/
|
|
||||||
return new TachographTimelineEventBundle(activityEvents, vehicleUsageEvents, supportEvents);
|
return new TachographTimelineEventBundle(activityEvents, vehicleUsageEvents, supportEvents);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -309,6 +306,7 @@ public class IntervalBackedDriverTimelineEventBuilder implements DriverTimelineE
|
||||||
Map<String, Object> raw = new LinkedHashMap<>();
|
Map<String, Object> raw = new LinkedHashMap<>();
|
||||||
raw.put("sourceRowId", supportEvent.eventId());
|
raw.put("sourceRowId", supportEvent.eventId());
|
||||||
raw.put("supportEventId", supportEvent.eventId());
|
raw.put("supportEventId", supportEvent.eventId());
|
||||||
|
raw.put("driverKey", supportEvent.driverKey());
|
||||||
raw.put("supportEventType", supportEvent.eventType());
|
raw.put("supportEventType", supportEvent.eventType());
|
||||||
raw.put("slot", supportEvent.slot());
|
raw.put("slot", supportEvent.slot());
|
||||||
raw.put("registrationKey", supportEvent.registrationKey());
|
raw.put("registrationKey", supportEvent.registrationKey());
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,8 @@ public class VehicleUnitXmlExtractionService {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
String cardNation = text(record, "fullCardNumber/cardIssuingMemberState");
|
String cardNation = text(record, "fullCardNumber/cardIssuingMemberState");
|
||||||
String cardNumber = joinCardNumber(record, "fullCardNumber/cardNumber");
|
String fullCardNumber = joinCardNumber(record, "fullCardNumber/cardNumber");
|
||||||
|
String cardNumber = driverKeyFactory.canonicalCardNumber(fullCardNumber);
|
||||||
if (cardNumber == null) {
|
if (cardNumber == null) {
|
||||||
sessionWarnings.add(new ExtractionWarning(
|
sessionWarnings.add(new ExtractionWarning(
|
||||||
"MISSING_VU_DRIVER_CARD",
|
"MISSING_VU_DRIVER_CARD",
|
||||||
|
|
@ -86,6 +87,7 @@ public class VehicleUnitXmlExtractionService {
|
||||||
driverKeyFactory.createSourceDriverCardId(driverKey),
|
driverKeyFactory.createSourceDriverCardId(driverKey),
|
||||||
cardNation,
|
cardNation,
|
||||||
cardNumber,
|
cardNumber,
|
||||||
|
fullCardNumber,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
|
|
@ -366,6 +368,14 @@ public class VehicleUnitXmlExtractionService {
|
||||||
Map<String, DriverExtractionBuilder> driversByKey,
|
Map<String, DriverExtractionBuilder> driversByKey,
|
||||||
List<ExtractionWarning> warnings
|
List<ExtractionWarning> warnings
|
||||||
) {
|
) {
|
||||||
|
if (!hasKnownRegistration(vehicleContext.registration())) {
|
||||||
|
warnings.add(new ExtractionWarning(
|
||||||
|
"VU_SUPPORT_EVENTS_UNKNOWN_VRN",
|
||||||
|
"Vehicle-unit support events were ignored because vehicle registration is unknown.",
|
||||||
|
"/VehicleUnit/Activities"
|
||||||
|
));
|
||||||
|
return;
|
||||||
|
}
|
||||||
extractVuPlaceSupportEvents(document, vehicleContext, vuCardIwIntervals, driversByKey, warnings);
|
extractVuPlaceSupportEvents(document, vehicleContext, vuCardIwIntervals, driversByKey, warnings);
|
||||||
extractVuGnssSupportEvents(document, vehicleContext, vuCardIwIntervals, driversByKey, warnings);
|
extractVuGnssSupportEvents(document, vehicleContext, vuCardIwIntervals, driversByKey, warnings);
|
||||||
extractVuSpecificConditionSupportEvents(document, vehicleContext, vuCardIwIntervals, driversByKey, warnings);
|
extractVuSpecificConditionSupportEvents(document, vehicleContext, vuCardIwIntervals, driversByKey, warnings);
|
||||||
|
|
@ -415,6 +425,7 @@ public class VehicleUnitXmlExtractionService {
|
||||||
assignment,
|
assignment,
|
||||||
new ExtractedSupportEvent(
|
new ExtractedSupportEvent(
|
||||||
"VUPLACE-" + (i + 1) + "-" + assignment.driverKey(),
|
"VUPLACE-" + (i + 1) + "-" + assignment.driverKey(),
|
||||||
|
assignment.driverKey(),
|
||||||
occurredAt,
|
occurredAt,
|
||||||
"PLACE",
|
"PLACE",
|
||||||
mapPlaceEntryType(entryType),
|
mapPlaceEntryType(entryType),
|
||||||
|
|
@ -487,6 +498,7 @@ public class VehicleUnitXmlExtractionService {
|
||||||
assignment,
|
assignment,
|
||||||
new ExtractedSupportEvent(
|
new ExtractedSupportEvent(
|
||||||
"VUGNSS-" + (i + 1) + "-" + assignment.driverKey() + "-" + assignment.slot(),
|
"VUGNSS-" + (i + 1) + "-" + assignment.driverKey() + "-" + assignment.slot(),
|
||||||
|
assignment.driverKey(),
|
||||||
occurredAt,
|
occurredAt,
|
||||||
"POSITION",
|
"POSITION",
|
||||||
"POSITION_RECORDED",
|
"POSITION_RECORDED",
|
||||||
|
|
@ -553,6 +565,7 @@ public class VehicleUnitXmlExtractionService {
|
||||||
assignment,
|
assignment,
|
||||||
new ExtractedSupportEvent(
|
new ExtractedSupportEvent(
|
||||||
"VUSC-" + (i + 1) + "-" + assignment.driverKey() + "-" + assignment.slot(),
|
"VUSC-" + (i + 1) + "-" + assignment.driverKey() + "-" + assignment.slot(),
|
||||||
|
assignment.driverKey(),
|
||||||
occurredAt,
|
occurredAt,
|
||||||
"SPECIFIC_CONDITION",
|
"SPECIFIC_CONDITION",
|
||||||
specificCondition[0],
|
specificCondition[0],
|
||||||
|
|
@ -625,6 +638,7 @@ public class VehicleUnitXmlExtractionService {
|
||||||
assignment,
|
assignment,
|
||||||
new ExtractedSupportEvent(
|
new ExtractedSupportEvent(
|
||||||
"VUBORDER-" + (i + 1) + "-" + assignment.driverKey() + "-" + assignment.slot(),
|
"VUBORDER-" + (i + 1) + "-" + assignment.driverKey() + "-" + assignment.slot(),
|
||||||
|
assignment.driverKey(),
|
||||||
occurredAt,
|
occurredAt,
|
||||||
"BORDER_CROSSING",
|
"BORDER_CROSSING",
|
||||||
"BORDER_OUTBOUND",
|
"BORDER_OUTBOUND",
|
||||||
|
|
@ -698,6 +712,7 @@ public class VehicleUnitXmlExtractionService {
|
||||||
assignment,
|
assignment,
|
||||||
new ExtractedSupportEvent(
|
new ExtractedSupportEvent(
|
||||||
"VULOAD-" + (i + 1) + "-" + assignment.driverKey() + "-" + assignment.slot(),
|
"VULOAD-" + (i + 1) + "-" + assignment.driverKey() + "-" + assignment.slot(),
|
||||||
|
assignment.driverKey(),
|
||||||
occurredAt,
|
occurredAt,
|
||||||
"LOAD_UNLOAD",
|
"LOAD_UNLOAD",
|
||||||
operation,
|
operation,
|
||||||
|
|
@ -763,6 +778,7 @@ public class VehicleUnitXmlExtractionService {
|
||||||
assignment,
|
assignment,
|
||||||
new ExtractedSupportEvent(
|
new ExtractedSupportEvent(
|
||||||
"VUSPEED-" + (i + 1) + "-" + assignment.driverKey() + "-BEGIN",
|
"VUSPEED-" + (i + 1) + "-" + assignment.driverKey() + "-BEGIN",
|
||||||
|
assignment.driverKey(),
|
||||||
beginAt,
|
beginAt,
|
||||||
"SPEEDING",
|
"SPEEDING",
|
||||||
"SPEEDING",
|
"SPEEDING",
|
||||||
|
|
@ -793,6 +809,7 @@ public class VehicleUnitXmlExtractionService {
|
||||||
assignment,
|
assignment,
|
||||||
new ExtractedSupportEvent(
|
new ExtractedSupportEvent(
|
||||||
"VUSPEED-" + (i + 1) + "-" + assignment.driverKey() + "-END",
|
"VUSPEED-" + (i + 1) + "-" + assignment.driverKey() + "-END",
|
||||||
|
assignment.driverKey(),
|
||||||
endAt,
|
endAt,
|
||||||
"SPEEDING",
|
"SPEEDING",
|
||||||
"SPEEDING",
|
"SPEEDING",
|
||||||
|
|
@ -899,6 +916,17 @@ public class VehicleUnitXmlExtractionService {
|
||||||
builder.supportEvents.add(supportEvent);
|
builder.supportEvents.add(supportEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean hasKnownRegistration(ExtractedVehicleRegistration registration) {
|
||||||
|
return registration != null && hasKnownRegistrationKey(registration.registrationKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasKnownRegistrationKey(String registrationKey) {
|
||||||
|
return registrationKey != null
|
||||||
|
&& !registrationKey.isBlank()
|
||||||
|
&& !registrationKey.startsWith("UNKNOWN:")
|
||||||
|
&& !registrationKey.endsWith(":UNKNOWN");
|
||||||
|
}
|
||||||
|
|
||||||
private List<DriverAssignment> resolveDriverAssignments(
|
private List<DriverAssignment> resolveDriverAssignments(
|
||||||
OffsetDateTime occurredAt,
|
OffsetDateTime occurredAt,
|
||||||
String explicitDriverKey,
|
String explicitDriverKey,
|
||||||
|
|
@ -925,7 +953,7 @@ public class VehicleUnitXmlExtractionService {
|
||||||
|
|
||||||
private String driverKeyFromCardNode(Element node, String basePath) {
|
private String driverKeyFromCardNode(Element node, String basePath) {
|
||||||
String cardNation = text(node, basePath + "/cardIssuingMemberState");
|
String cardNation = text(node, basePath + "/cardIssuingMemberState");
|
||||||
String cardNumber = joinCardNumber(node, basePath + "/cardNumber");
|
String cardNumber = driverKeyFactory.canonicalCardNumber(joinCardNumber(node, basePath + "/cardNumber"));
|
||||||
return cardNumber == null ? null : driverKeyFactory.createDriverKey(cardNation, cardNumber);
|
return cardNumber == null ? null : driverKeyFactory.createDriverKey(cardNation, cardNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1109,6 +1137,7 @@ public class VehicleUnitXmlExtractionService {
|
||||||
String sourceDriverCardId,
|
String sourceDriverCardId,
|
||||||
String cardNation,
|
String cardNation,
|
||||||
String cardNumber,
|
String cardNumber,
|
||||||
|
String fullCardNumber,
|
||||||
String issuingAuthorityName,
|
String issuingAuthorityName,
|
||||||
OffsetDateTime issueDate,
|
OffsetDateTime issueDate,
|
||||||
OffsetDateTime validityBegin,
|
OffsetDateTime validityBegin,
|
||||||
|
|
@ -1119,6 +1148,7 @@ public class VehicleUnitXmlExtractionService {
|
||||||
sourceDriverCardId,
|
sourceDriverCardId,
|
||||||
cardNation,
|
cardNation,
|
||||||
cardNumber,
|
cardNumber,
|
||||||
|
fullCardNumber,
|
||||||
issuingAuthorityName,
|
issuingAuthorityName,
|
||||||
issueDate,
|
issueDate,
|
||||||
validityBegin,
|
validityBegin,
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import at.procon.eventhub.dto.DriverCardRefDto;
|
||||||
import at.procon.eventhub.dto.DriverRefDto;
|
import at.procon.eventhub.dto.DriverRefDto;
|
||||||
import at.procon.eventhub.dto.VehicleRefDto;
|
import at.procon.eventhub.dto.VehicleRefDto;
|
||||||
import at.procon.eventhub.dto.VehicleRegistrationRefDto;
|
import at.procon.eventhub.dto.VehicleRegistrationRefDto;
|
||||||
|
import at.procon.eventhub.reference.DriverCardNumberNormalizer;
|
||||||
import at.procon.eventhub.yellowfox.dto.YellowFoxD8BookingDto;
|
import at.procon.eventhub.yellowfox.dto.YellowFoxD8BookingDto;
|
||||||
import com.fasterxml.jackson.core.type.TypeReference;
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
|
@ -149,10 +150,6 @@ public class YellowFoxD8BookingRowMapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
private String normalizeBookingDriverCardNumber(String value) {
|
private String normalizeBookingDriverCardNumber(String value) {
|
||||||
if (value == null || value.isBlank()) {
|
return DriverCardNumberNormalizer.canonical(value);
|
||||||
return null;
|
|
||||||
}
|
|
||||||
String trimmed = value.trim();
|
|
||||||
return trimmed.length() <= 14 ? trimmed : trimmed.substring(0, 14);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ class UnifiedDriverEventsRequestTest {
|
||||||
" default ",
|
" default ",
|
||||||
" DRIVER:42 ",
|
" DRIVER:42 ",
|
||||||
"at",
|
"at",
|
||||||
" 123 ",
|
" 1234567890123457 ",
|
||||||
OffsetDateTime.parse("2026-05-01T00:00:00Z"),
|
OffsetDateTime.parse("2026-05-01T00:00:00Z"),
|
||||||
OffsetDateTime.parse("2026-05-02T00:00:00Z")
|
OffsetDateTime.parse("2026-05-02T00:00:00Z")
|
||||||
);
|
);
|
||||||
|
|
@ -41,7 +41,7 @@ class UnifiedDriverEventsRequestTest {
|
||||||
assertThat(request.tenantKey()).isEqualTo("default");
|
assertThat(request.tenantKey()).isEqualTo("default");
|
||||||
assertThat(request.driverSourceEntityId()).isEqualTo("DRIVER:42");
|
assertThat(request.driverSourceEntityId()).isEqualTo("DRIVER:42");
|
||||||
assertThat(request.driverCardNation()).isEqualTo("AT");
|
assertThat(request.driverCardNation()).isEqualTo("AT");
|
||||||
assertThat(request.driverCardNumber()).isEqualTo("123");
|
assertThat(request.driverCardNumber()).isEqualTo("12345678901234");
|
||||||
assertThat(request.hasDriverSelector()).isTrue();
|
assertThat(request.hasDriverSelector()).isTrue();
|
||||||
assertThat(request.hasVehicleSelector()).isFalse();
|
assertThat(request.hasVehicleSelector()).isFalse();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ class UnifiedRuntimeProcessingRequestTest {
|
||||||
Set.of(UnifiedEventSourceFamily.TACHOGRAPH_DB, UnifiedEventSourceFamily.YELLOWFOX_DB),
|
Set.of(UnifiedEventSourceFamily.TACHOGRAPH_DB, UnifiedEventSourceFamily.YELLOWFOX_DB),
|
||||||
"DRIVER:42",
|
"DRIVER:42",
|
||||||
"AT",
|
"AT",
|
||||||
"123",
|
"1234567890123457",
|
||||||
OffsetDateTime.parse("2026-05-01T00:00:00Z"),
|
OffsetDateTime.parse("2026-05-01T00:00:00Z"),
|
||||||
OffsetDateTime.parse("2026-05-02T00:00:00Z")
|
OffsetDateTime.parse("2026-05-02T00:00:00Z")
|
||||||
);
|
);
|
||||||
|
|
@ -29,7 +29,7 @@ class UnifiedRuntimeProcessingRequestTest {
|
||||||
);
|
);
|
||||||
assertThat(request.driverSourceEntityId()).isEqualTo("DRIVER:42");
|
assertThat(request.driverSourceEntityId()).isEqualTo("DRIVER:42");
|
||||||
assertThat(request.driverCardNation()).isEqualTo("AT");
|
assertThat(request.driverCardNation()).isEqualTo("AT");
|
||||||
assertThat(request.driverCardNumber()).isEqualTo("123");
|
assertThat(request.driverCardNumber()).isEqualTo("12345678901234");
|
||||||
assertThat(request.eventBackend()).isEqualTo(UnifiedRuntimeEventBackend.SOURCE_DB);
|
assertThat(request.eventBackend()).isEqualTo(UnifiedRuntimeEventBackend.SOURCE_DB);
|
||||||
assertThat(request.expandVehicleEvents()).isTrue();
|
assertThat(request.expandVehicleEvents()).isTrue();
|
||||||
assertThat(request.vehicleOccurredFrom()).isEqualTo(OffsetDateTime.parse("2026-05-01T00:00:00Z"));
|
assertThat(request.vehicleOccurredFrom()).isEqualTo(OffsetDateTime.parse("2026-05-01T00:00:00Z"));
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,7 @@ class TachographFileSessionRuntimeEventLoaderTest {
|
||||||
return new DriverExtractionSession(
|
return new DriverExtractionSession(
|
||||||
"12:123",
|
"12:123",
|
||||||
new ExtractedDriver("12:123", "DRV:12:123", "Doe", "Jane", null, null, null, null, null),
|
new ExtractedDriver("12:123", "DRV:12:123", "Doe", "Jane", null, null, null, null, null),
|
||||||
new ExtractedDriverCard("CARD:12:123", "12", "123", null, null, null, null),
|
new ExtractedDriverCard("CARD:12:123", "12", "123", "123", null, null, null, null),
|
||||||
List.of(new ExtractedVehicleRegistration("12:REG-1", "VR:12:REG-1", "12", "REG-1")),
|
List.of(new ExtractedVehicleRegistration("12:REG-1", "VR:12:REG-1", "12", "REG-1")),
|
||||||
List.of(new ExtractedVehicle("VIN-1", "VIN:VIN-1", "VIN-1")),
|
List.of(new ExtractedVehicle("VIN-1", "VIN:VIN-1", "VIN-1")),
|
||||||
List.of(new ExtractedCardVehicleUsageInterval(
|
List.of(new ExtractedCardVehicleUsageInterval(
|
||||||
|
|
@ -99,6 +99,7 @@ class TachographFileSessionRuntimeEventLoaderTest {
|
||||||
)),
|
)),
|
||||||
List.of(new ExtractedSupportEvent(
|
List.of(new ExtractedSupportEvent(
|
||||||
"SUP-1",
|
"SUP-1",
|
||||||
|
"12:123",
|
||||||
OffsetDateTime.parse("2026-05-01T08:45:00Z"),
|
OffsetDateTime.parse("2026-05-01T08:45:00Z"),
|
||||||
"POSITION",
|
"POSITION",
|
||||||
"POSITION_RECORDED",
|
"POSITION_RECORDED",
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,7 @@ class UnifiedDriverEventSourceServiceTest {
|
||||||
return new DriverExtractionSession(
|
return new DriverExtractionSession(
|
||||||
"12:123",
|
"12:123",
|
||||||
new ExtractedDriver("12:123", "DRV:12:123", "Doe", "Jane", null, null, null, null, null),
|
new ExtractedDriver("12:123", "DRV:12:123", "Doe", "Jane", null, null, null, null, null),
|
||||||
new ExtractedDriverCard("CARD:12:123", "12", "123", null, null, null, null),
|
new ExtractedDriverCard("CARD:12:123", "12", "123", "123", null, null, null, null),
|
||||||
List.of(new ExtractedVehicleRegistration("12:REG-1", "VR:12:REG-1", "12", "REG-1")),
|
List.of(new ExtractedVehicleRegistration("12:REG-1", "VR:12:REG-1", "12", "REG-1")),
|
||||||
List.of(new ExtractedVehicle("VIN-1", "VIN:VIN-1", "VIN-1")),
|
List.of(new ExtractedVehicle("VIN-1", "VIN:VIN-1", "VIN-1")),
|
||||||
List.of(new ExtractedCardVehicleUsageInterval(
|
List.of(new ExtractedCardVehicleUsageInterval(
|
||||||
|
|
@ -115,6 +115,7 @@ class UnifiedDriverEventSourceServiceTest {
|
||||||
)),
|
)),
|
||||||
List.of(new ExtractedSupportEvent(
|
List.of(new ExtractedSupportEvent(
|
||||||
"SUP-1",
|
"SUP-1",
|
||||||
|
"12:123",
|
||||||
OffsetDateTime.parse("2026-05-01T08:45:00Z"),
|
OffsetDateTime.parse("2026-05-01T08:45:00Z"),
|
||||||
"POSITION",
|
"POSITION",
|
||||||
"POSITION_RECORDED",
|
"POSITION_RECORDED",
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,7 @@ class UnifiedDriverTimelineServiceTest {
|
||||||
return new DriverExtractionSession(
|
return new DriverExtractionSession(
|
||||||
"12:123",
|
"12:123",
|
||||||
new ExtractedDriver("12:123", "DRV:12:123", "Doe", "Jane", null, null, null, null, null),
|
new ExtractedDriver("12:123", "DRV:12:123", "Doe", "Jane", null, null, null, null, null),
|
||||||
new ExtractedDriverCard("CARD:12:123", "12", "123", null, null, null, null),
|
new ExtractedDriverCard("CARD:12:123", "12", "123", "123", null, null, null, null),
|
||||||
List.of(new ExtractedVehicleRegistration("12:REG-1", "VR:12:REG-1", "12", "REG-1")),
|
List.of(new ExtractedVehicleRegistration("12:REG-1", "VR:12:REG-1", "12", "REG-1")),
|
||||||
List.of(new ExtractedVehicle("VIN-1", "VIN:VIN-1", "VIN-1")),
|
List.of(new ExtractedVehicle("VIN-1", "VIN:VIN-1", "VIN-1")),
|
||||||
List.of(new ExtractedCardVehicleUsageInterval(
|
List.of(new ExtractedCardVehicleUsageInterval(
|
||||||
|
|
@ -100,6 +100,7 @@ class UnifiedDriverTimelineServiceTest {
|
||||||
)),
|
)),
|
||||||
List.of(new ExtractedSupportEvent(
|
List.of(new ExtractedSupportEvent(
|
||||||
"SUP-1",
|
"SUP-1",
|
||||||
|
"12:123",
|
||||||
OffsetDateTime.parse("2026-05-01T08:45:00Z"),
|
OffsetDateTime.parse("2026-05-01T08:45:00Z"),
|
||||||
"POSITION",
|
"POSITION",
|
||||||
"POSITION_RECORDED",
|
"POSITION_RECORDED",
|
||||||
|
|
|
||||||
|
|
@ -93,7 +93,7 @@ class UnifiedVehicleEventSourceServiceTest {
|
||||||
return new DriverExtractionSession(
|
return new DriverExtractionSession(
|
||||||
"12:123",
|
"12:123",
|
||||||
new ExtractedDriver("12:123", "DRV:12:123", "Doe", "Jane", null, null, null, null, null),
|
new ExtractedDriver("12:123", "DRV:12:123", "Doe", "Jane", null, null, null, null, null),
|
||||||
new ExtractedDriverCard("CARD:12:123", "12", "123", null, null, null, null),
|
new ExtractedDriverCard("CARD:12:123", "12", "123", "123", null, null, null, null),
|
||||||
List.of(new ExtractedVehicleRegistration("12:REG-1", "VR:12:REG-1", "12", "REG-1")),
|
List.of(new ExtractedVehicleRegistration("12:REG-1", "VR:12:REG-1", "12", "REG-1")),
|
||||||
List.of(new ExtractedVehicle("VIN-1", "VIN:VIN-1", "VIN-1")),
|
List.of(new ExtractedVehicle("VIN-1", "VIN:VIN-1", "VIN-1")),
|
||||||
List.of(new ExtractedCardVehicleUsageInterval(
|
List.of(new ExtractedCardVehicleUsageInterval(
|
||||||
|
|
@ -120,6 +120,7 @@ class UnifiedVehicleEventSourceServiceTest {
|
||||||
)),
|
)),
|
||||||
List.of(new ExtractedSupportEvent(
|
List.of(new ExtractedSupportEvent(
|
||||||
"SUP-1",
|
"SUP-1",
|
||||||
|
"12:123",
|
||||||
OffsetDateTime.parse("2026-05-01T08:45:00Z"),
|
OffsetDateTime.parse("2026-05-01T08:45:00Z"),
|
||||||
"POSITION",
|
"POSITION",
|
||||||
"POSITION_RECORDED",
|
"POSITION_RECORDED",
|
||||||
|
|
|
||||||
|
|
@ -110,5 +110,73 @@ class DriverCardXmlExtractionServiceTest {
|
||||||
assertThat(driver.cardVehicleUsageIntervals().get(1).to()).isNull();
|
assertThat(driver.cardVehicleUsageIntervals().get(1).to()).isNull();
|
||||||
assertThat(driver.cardActivityIntervals()).hasSize(3);
|
assertThat(driver.cardActivityIntervals()).hasSize(3);
|
||||||
assertThat(driver.cardActivityIntervals().get(2).registrationKey()).isEqualTo("12:W-54321B");
|
assertThat(driver.cardActivityIntervals().get(2).registrationKey()).isEqualTo("12:W-54321B");
|
||||||
|
assertThat(driver.supportEvents()).hasSize(5);
|
||||||
|
assertThat(driver.supportEvents().stream()
|
||||||
|
.filter(event -> "12:W-54321B".equals(event.registrationKey()))
|
||||||
|
.map(event -> event.eventDomain() + ":" + event.eventType()))
|
||||||
|
.containsExactly("BORDER_CROSSING:BORDER_OUTBOUND", "LOAD_UNLOAD:UNLOAD");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void ignoresSupportEventsWhenVehicleRegistrationIsUnknown() {
|
||||||
|
String xml = DriverCardXmlSamples.validDriverCardXml()
|
||||||
|
.replace("<vehicleRegNumber>W-12345A</vehicleRegNumber>", "<vehicleRegNumber></vehicleRegNumber>")
|
||||||
|
.replace("<vehicleRegNumber>W-54321B</vehicleRegNumber>", "<vehicleRegNumber></vehicleRegNumber>");
|
||||||
|
|
||||||
|
TachographFileSession session = service.extract(
|
||||||
|
parser.parse(xml),
|
||||||
|
new TachographFileSessionMetadata(
|
||||||
|
"default",
|
||||||
|
"legalrequirements-drivercard",
|
||||||
|
"sample",
|
||||||
|
"sample.ddd",
|
||||||
|
"abc",
|
||||||
|
10,
|
||||||
|
"42",
|
||||||
|
"def",
|
||||||
|
true,
|
||||||
|
null
|
||||||
|
),
|
||||||
|
Instant.now(),
|
||||||
|
Instant.now().plus(4, ChronoUnit.HOURS)
|
||||||
|
);
|
||||||
|
|
||||||
|
DriverExtractionSession driver = session.driversByKey().values().iterator().next();
|
||||||
|
assertThat(driver.cardVehicleUsageIntervals()).hasSize(2);
|
||||||
|
assertThat(driver.cardVehicleUsageIntervals()).extracting("registrationKey")
|
||||||
|
.containsOnly("12:UNKNOWN");
|
||||||
|
assertThat(driver.supportEvents()).isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void usesCanonicalCardNumberForDriverIdentityAndKeepsFullCardNumberAsEvidence() {
|
||||||
|
String xml = DriverCardXmlSamples.validDriverCardXml()
|
||||||
|
.replace("<driverIdentification>123456789012</driverIdentification>", "<driverIdentification>12345678901234</driverIdentification>")
|
||||||
|
.replace("<cardReplacementIndex>0</cardReplacementIndex>", "<cardReplacementIndex>5</cardReplacementIndex>")
|
||||||
|
.replace("<cardRenewalIndex>0</cardRenewalIndex>", "<cardRenewalIndex>7</cardRenewalIndex>");
|
||||||
|
|
||||||
|
TachographFileSession session = service.extract(
|
||||||
|
parser.parse(xml),
|
||||||
|
new TachographFileSessionMetadata(
|
||||||
|
"default",
|
||||||
|
"legalrequirements-drivercard",
|
||||||
|
"sample",
|
||||||
|
"sample.ddd",
|
||||||
|
"abc",
|
||||||
|
10,
|
||||||
|
"42",
|
||||||
|
"def",
|
||||||
|
true,
|
||||||
|
null
|
||||||
|
),
|
||||||
|
Instant.now(),
|
||||||
|
Instant.now().plus(4, ChronoUnit.HOURS)
|
||||||
|
);
|
||||||
|
|
||||||
|
DriverExtractionSession driver = session.driversByKey().values().iterator().next();
|
||||||
|
assertThat(driver.driverKey()).isEqualTo("12:12345678901234");
|
||||||
|
assertThat(driver.driverCard().cardNumber()).isEqualTo("12345678901234");
|
||||||
|
assertThat(driver.driverCard().fullCardNumber()).isEqualTo("1234567890123457");
|
||||||
|
assertThat(driver.driverCard().sourceDriverCardId()).isEqualTo("CARD:12:12345678901234");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,7 @@ class DriverTimelineBuilderTest {
|
||||||
),
|
),
|
||||||
List.of(new ExtractedSupportEvent(
|
List.of(new ExtractedSupportEvent(
|
||||||
"SUP-1",
|
"SUP-1",
|
||||||
|
"12:123",
|
||||||
OffsetDateTime.parse("2026-05-01T08:30:00Z"),
|
OffsetDateTime.parse("2026-05-01T08:30:00Z"),
|
||||||
"PLACE",
|
"PLACE",
|
||||||
"BEGIN_DAILY_WORK_PERIOD",
|
"BEGIN_DAILY_WORK_PERIOD",
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ class EventBackedDriverTimelineBuilderTest {
|
||||||
DriverExtractionSession driver = new DriverExtractionSession(
|
DriverExtractionSession driver = new DriverExtractionSession(
|
||||||
"12:123",
|
"12:123",
|
||||||
new ExtractedDriver("12:123", "DRV:12:123", "Doe", "Jane", null, null, null, null, null),
|
new ExtractedDriver("12:123", "DRV:12:123", "Doe", "Jane", null, null, null, null, null),
|
||||||
new ExtractedDriverCard("CARD:12:123", "12", "123", null, null, null, null),
|
new ExtractedDriverCard("CARD:12:123", "12", "123", "123", null, null, null, null),
|
||||||
List.of(new ExtractedVehicleRegistration("12:REG-1", "VR:12:REG-1", "12", "REG-1")),
|
List.of(new ExtractedVehicleRegistration("12:REG-1", "VR:12:REG-1", "12", "REG-1")),
|
||||||
List.of(new ExtractedVehicle("VIN-1", "VIN:VIN-1", "VIN-1")),
|
List.of(new ExtractedVehicle("VIN-1", "VIN:VIN-1", "VIN-1")),
|
||||||
List.of(new ExtractedCardVehicleUsageInterval(
|
List.of(new ExtractedCardVehicleUsageInterval(
|
||||||
|
|
@ -70,6 +70,7 @@ class EventBackedDriverTimelineBuilderTest {
|
||||||
)),
|
)),
|
||||||
List.of(new ExtractedSupportEvent(
|
List.of(new ExtractedSupportEvent(
|
||||||
"SUP-1",
|
"SUP-1",
|
||||||
|
"12:123",
|
||||||
OffsetDateTime.parse("2026-05-01T08:45:00Z"),
|
OffsetDateTime.parse("2026-05-01T08:45:00Z"),
|
||||||
"POSITION",
|
"POSITION",
|
||||||
"POSITION_RECORDED",
|
"POSITION_RECORDED",
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ class IntervalBackedDriverTimelineEventBuilderTest {
|
||||||
DriverExtractionSession driver = new DriverExtractionSession(
|
DriverExtractionSession driver = new DriverExtractionSession(
|
||||||
"12:123",
|
"12:123",
|
||||||
new ExtractedDriver("12:123", "DRV:12:123", "Doe", "Jane", null, null, null, null, null),
|
new ExtractedDriver("12:123", "DRV:12:123", "Doe", "Jane", null, null, null, null, null),
|
||||||
new ExtractedDriverCard("CARD:12:123", "12", "123", null, null, null, null),
|
new ExtractedDriverCard("CARD:12:123", "12", "123", "123", null, null, null, null),
|
||||||
List.of(new ExtractedVehicleRegistration("12:REG-1", "VR:12:REG-1", "12", "REG-1")),
|
List.of(new ExtractedVehicleRegistration("12:REG-1", "VR:12:REG-1", "12", "REG-1")),
|
||||||
List.of(new ExtractedVehicle("VIN-1", "VIN:VIN-1", "VIN-1")),
|
List.of(new ExtractedVehicle("VIN-1", "VIN:VIN-1", "VIN-1")),
|
||||||
List.of(new ExtractedCardVehicleUsageInterval(
|
List.of(new ExtractedCardVehicleUsageInterval(
|
||||||
|
|
@ -92,7 +92,7 @@ class IntervalBackedDriverTimelineEventBuilderTest {
|
||||||
DriverExtractionSession driver = new DriverExtractionSession(
|
DriverExtractionSession driver = new DriverExtractionSession(
|
||||||
"12:123",
|
"12:123",
|
||||||
new ExtractedDriver("12:123", "DRV:12:123", "Doe", "Jane", null, null, null, null, null),
|
new ExtractedDriver("12:123", "DRV:12:123", "Doe", "Jane", null, null, null, null, null),
|
||||||
new ExtractedDriverCard("CARD:12:123", "12", "123", null, null, null, null),
|
new ExtractedDriverCard("CARD:12:123", "12", "123", "123", null, null, null, null),
|
||||||
List.of(new ExtractedVehicleRegistration("12:REG-1", "VR:12:REG-1", "12", "REG-1")),
|
List.of(new ExtractedVehicleRegistration("12:REG-1", "VR:12:REG-1", "12", "REG-1")),
|
||||||
List.of(new ExtractedVehicle("VIN-1", "VIN:VIN-1", "VIN-1")),
|
List.of(new ExtractedVehicle("VIN-1", "VIN:VIN-1", "VIN-1")),
|
||||||
List.of(new ExtractedCardVehicleUsageInterval(
|
List.of(new ExtractedCardVehicleUsageInterval(
|
||||||
|
|
@ -108,6 +108,7 @@ class IntervalBackedDriverTimelineEventBuilderTest {
|
||||||
List.of(),
|
List.of(),
|
||||||
List.of(new ExtractedSupportEvent(
|
List.of(new ExtractedSupportEvent(
|
||||||
"VUGNSS-1",
|
"VUGNSS-1",
|
||||||
|
"12:123",
|
||||||
OffsetDateTime.parse("2026-05-01T08:45:00Z"),
|
OffsetDateTime.parse("2026-05-01T08:45:00Z"),
|
||||||
"POSITION",
|
"POSITION",
|
||||||
"POSITION_RECORDED",
|
"POSITION_RECORDED",
|
||||||
|
|
|
||||||
|
|
@ -132,6 +132,66 @@ class VehicleUnitXmlExtractionServiceTest {
|
||||||
assertThat(secondDriver.cardVehicleUsageIntervals().get(0).to()).isNull();
|
assertThat(secondDriver.cardVehicleUsageIntervals().get(0).to()).isNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void ignoresSupportEventsWhenVehicleRegistrationIsUnknown() throws Exception {
|
||||||
|
String xml = VehicleUnitXmlSamples.vehicleUnitXml()
|
||||||
|
.replace("<vehicleRegNumber>W-1000V</vehicleRegNumber>", "<vehicleRegNumber></vehicleRegNumber>");
|
||||||
|
|
||||||
|
TachographFileSession session = service.extract(
|
||||||
|
new TachographXmlParser.ParsedTachographXml(document(xml), "VehicleUnit"),
|
||||||
|
new TachographFileSessionMetadata(
|
||||||
|
"default",
|
||||||
|
"legalrequirements-vehicleunit",
|
||||||
|
"sample-vu",
|
||||||
|
"sample-vu.ddd",
|
||||||
|
"abc",
|
||||||
|
10,
|
||||||
|
"42",
|
||||||
|
"def",
|
||||||
|
false,
|
||||||
|
null
|
||||||
|
),
|
||||||
|
Instant.now(),
|
||||||
|
Instant.now().plus(4, ChronoUnit.HOURS)
|
||||||
|
);
|
||||||
|
|
||||||
|
assertThat(session.driversByKey()).hasSize(2);
|
||||||
|
assertThat(session.driversByKey().values())
|
||||||
|
.allSatisfy(driver -> assertThat(driver.supportEvents()).isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void usesCanonicalCardNumberForVehicleUnitDriverIdentityAndKeepsFullCardNumberAsEvidence() throws Exception {
|
||||||
|
String xml = VehicleUnitXmlSamples.vehicleUnitXml()
|
||||||
|
.replaceFirst("<driverIdentification>123456789012</driverIdentification>", "<driverIdentification>12345678901234</driverIdentification>")
|
||||||
|
.replaceFirst("<cardReplacementIndex>0</cardReplacementIndex>", "<cardReplacementIndex>5</cardReplacementIndex>")
|
||||||
|
.replaceFirst("<cardRenewalIndex>0</cardRenewalIndex>", "<cardRenewalIndex>7</cardRenewalIndex>");
|
||||||
|
|
||||||
|
TachographFileSession session = service.extract(
|
||||||
|
new TachographXmlParser.ParsedTachographXml(document(xml), "VehicleUnit"),
|
||||||
|
new TachographFileSessionMetadata(
|
||||||
|
"default",
|
||||||
|
"legalrequirements-vehicleunit",
|
||||||
|
"sample-vu",
|
||||||
|
"sample-vu.ddd",
|
||||||
|
"abc",
|
||||||
|
10,
|
||||||
|
"42",
|
||||||
|
"def",
|
||||||
|
false,
|
||||||
|
null
|
||||||
|
),
|
||||||
|
Instant.now(),
|
||||||
|
Instant.now().plus(4, ChronoUnit.HOURS)
|
||||||
|
);
|
||||||
|
|
||||||
|
DriverExtractionSession firstDriver = session.driversByKey().get("12:12345678901234");
|
||||||
|
assertThat(firstDriver).isNotNull();
|
||||||
|
assertThat(firstDriver.driverCard().cardNumber()).isEqualTo("12345678901234");
|
||||||
|
assertThat(firstDriver.driverCard().fullCardNumber()).isEqualTo("1234567890123457");
|
||||||
|
assertThat(firstDriver.driverCard().sourceDriverCardId()).isEqualTo("CARD:12:12345678901234");
|
||||||
|
}
|
||||||
|
|
||||||
private Document document(String xml) throws Exception {
|
private Document document(String xml) throws Exception {
|
||||||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||||
factory.setNamespaceAware(false);
|
factory.setNamespaceAware(false);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue