Add numeric tachograph nation resolution
This commit is contained in:
parent
b35d428e80
commit
fc0d6db99a
|
|
@ -1,14 +1,24 @@
|
||||||
package at.procon.eventhub.dto;
|
package at.procon.eventhub.dto;
|
||||||
|
|
||||||
|
import at.procon.eventhub.reference.TachographNationRegistry;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tachograph driver-card identifier. The card number is scoped by issuing nation.
|
* Tachograph driver-card identifier. The card number is scoped by issuing nation.
|
||||||
*/
|
*/
|
||||||
public record DriverCardRefDto(
|
public record DriverCardRefDto(
|
||||||
String nation,
|
String nation,
|
||||||
|
Integer nationNumericCode,
|
||||||
String number
|
String number
|
||||||
) {
|
) {
|
||||||
|
public DriverCardRefDto(String nation, String number) {
|
||||||
|
this(nation, null, number);
|
||||||
|
}
|
||||||
|
|
||||||
public DriverCardRefDto {
|
public DriverCardRefDto {
|
||||||
nation = normalize(nation);
|
TachographNationRegistry.NationResolution nationResolution =
|
||||||
|
TachographNationRegistry.resolve(nation, nationNumericCode);
|
||||||
|
nation = normalize(nationResolution.legacyNation());
|
||||||
|
nationNumericCode = nationResolution.numericCode();
|
||||||
number = normalizeNullable(number);
|
number = normalizeNullable(number);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -17,11 +27,19 @@ public record DriverCardRefDto(
|
||||||
}
|
}
|
||||||
|
|
||||||
public String stableKey() {
|
public String stableKey() {
|
||||||
return (nation == null ? "" : nation) + ":" + (number == null ? "" : number);
|
String nationKey = nationNumericCode == null ? nation : String.valueOf(nationNumericCode);
|
||||||
|
return (nationKey == null ? "" : nationKey) + ":" + (number == null ? "" : number);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String normalize(String value) {
|
private static String normalize(String value) {
|
||||||
return value == null || value.isBlank() ? null : value.trim().toUpperCase();
|
if (value == null || value.isBlank()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
String trimmed = value.trim();
|
||||||
|
if (trimmed.matches("(?i)^unknown\\s+[0-9]+$")) {
|
||||||
|
return "Unknown " + trimmed.replaceAll("[^0-9]", "");
|
||||||
|
}
|
||||||
|
return trimmed.toUpperCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String normalizeNullable(String value) {
|
private static String normalizeNullable(String value) {
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,25 @@
|
||||||
package at.procon.eventhub.dto;
|
package at.procon.eventhub.dto;
|
||||||
|
|
||||||
|
import at.procon.eventhub.reference.TachographNationRegistry;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Vehicle registration number reference. VRN/plate is scoped by nation and can
|
* Vehicle registration number reference. VRN/plate is scoped by nation and can
|
||||||
* be resolved historically by occurredAt later.
|
* be resolved historically by occurredAt later.
|
||||||
*/
|
*/
|
||||||
public record VehicleRegistrationRefDto(
|
public record VehicleRegistrationRefDto(
|
||||||
String nation,
|
String nation,
|
||||||
|
Integer nationNumericCode,
|
||||||
String number
|
String number
|
||||||
) {
|
) {
|
||||||
|
public VehicleRegistrationRefDto(String nation, String number) {
|
||||||
|
this(nation, null, number);
|
||||||
|
}
|
||||||
|
|
||||||
public VehicleRegistrationRefDto {
|
public VehicleRegistrationRefDto {
|
||||||
nation = normalize(nation);
|
TachographNationRegistry.NationResolution nationResolution =
|
||||||
|
TachographNationRegistry.resolve(nation, nationNumericCode);
|
||||||
|
nation = normalize(nationResolution.legacyNation());
|
||||||
|
nationNumericCode = nationResolution.numericCode();
|
||||||
number = normalizeNullable(number);
|
number = normalizeNullable(number);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -18,11 +28,19 @@ public record VehicleRegistrationRefDto(
|
||||||
}
|
}
|
||||||
|
|
||||||
public String stableKey() {
|
public String stableKey() {
|
||||||
return (nation == null ? "" : nation) + ":" + (number == null ? "" : number);
|
String nationKey = nationNumericCode == null ? nation : String.valueOf(nationNumericCode);
|
||||||
|
return (nationKey == null ? "" : nationKey) + ":" + (number == null ? "" : number);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String normalize(String value) {
|
private static String normalize(String value) {
|
||||||
return value == null || value.isBlank() ? null : value.trim().toUpperCase();
|
if (value == null || value.isBlank()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
String trimmed = value.trim();
|
||||||
|
if (trimmed.matches("(?i)^unknown\\s+[0-9]+$")) {
|
||||||
|
return "Unknown " + trimmed.replaceAll("[^0-9]", "");
|
||||||
|
}
|
||||||
|
return trimmed.toUpperCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String normalizeNullable(String value) {
|
private static String normalizeNullable(String value) {
|
||||||
|
|
|
||||||
|
|
@ -40,10 +40,11 @@ public class DriverIdentityRepository {
|
||||||
String sourceDriverEntityId = normalizeNullable(driverRef.sourceEntityId());
|
String sourceDriverEntityId = normalizeNullable(driverRef.sourceEntityId());
|
||||||
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();
|
||||||
String cardNumber = driverCard == null ? null : normalizeDriverCardNumber(cardNation, driverCard.number());
|
String cardNumber = driverCard == null ? null : normalizeDriverCardNumber(cardNation, driverCard.number());
|
||||||
|
|
||||||
UUID driverId = findBySourceDriverEntityId(normalizedTenantKey, eventSourceId, sourceDriverEntityId);
|
UUID driverId = findBySourceDriverEntityId(normalizedTenantKey, eventSourceId, sourceDriverEntityId);
|
||||||
UUID driverCardId = resolveOrCreateDriverCardId(cardNation, cardNumber, driverId);
|
UUID driverCardId = resolveOrCreateDriverCardId(cardNation, cardNationNumericCode, cardNumber, driverId);
|
||||||
|
|
||||||
if (driverId == null && driverCardId != null) {
|
if (driverId == null && driverCardId != null) {
|
||||||
driverId = findDriverIdByCardId(driverCardId);
|
driverId = findDriverIdByCardId(driverCardId);
|
||||||
|
|
@ -621,21 +622,24 @@ public class DriverIdentityRepository {
|
||||||
|
|
||||||
private UUID resolveOrCreateDriverCardId(
|
private UUID resolveOrCreateDriverCardId(
|
||||||
String cardNation,
|
String cardNation,
|
||||||
|
Integer cardNationNumericCode,
|
||||||
String cardNumber,
|
String cardNumber,
|
||||||
UUID preferredDriverId
|
UUID preferredDriverId
|
||||||
) {
|
) {
|
||||||
if (cardNation == null || cardNumber == null) {
|
if ((cardNation == null && cardNationNumericCode == null) || cardNumber == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
UUID driverCardId = findDriverCardByCard(cardNation, cardNumber);
|
UUID driverCardId = findDriverCardByCard(cardNation, cardNationNumericCode, cardNumber);
|
||||||
if (driverCardId == null) {
|
if (driverCardId == null) {
|
||||||
Map<String, Object> payload = new LinkedHashMap<>();
|
Map<String, Object> payload = new LinkedHashMap<>();
|
||||||
put(payload, "source", "event");
|
put(payload, "source", "event");
|
||||||
put(payload, "card_nation", cardNation);
|
put(payload, "card_nation", cardNation);
|
||||||
|
put(payload, "card_nation_numeric_code", cardNationNumericCode);
|
||||||
put(payload, "card_number", cardNumber);
|
put(payload, "card_number", cardNumber);
|
||||||
return createDriverCard(
|
return createDriverCard(
|
||||||
preferredDriverId,
|
preferredDriverId,
|
||||||
cardNation,
|
cardNation,
|
||||||
|
cardNationNumericCode,
|
||||||
cardNumber,
|
cardNumber,
|
||||||
null,
|
null,
|
||||||
payload
|
payload
|
||||||
|
|
@ -683,10 +687,25 @@ public class DriverIdentityRepository {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private UUID findDriverCardByCard(String cardNation, String cardNumber) {
|
private UUID findDriverCardByCard(String cardNation, Integer cardNationNumericCode, String cardNumber) {
|
||||||
if (cardNation == null || cardNumber == null) {
|
if ((cardNation == null && cardNationNumericCode == null) || cardNumber == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
if (cardNationNumericCode != null) {
|
||||||
|
return jdbcTemplate.query(
|
||||||
|
"""
|
||||||
|
select card.id
|
||||||
|
from eventhub.driver_card card
|
||||||
|
where card.nation_numeric_code = ?
|
||||||
|
and card.card_number = ?
|
||||||
|
order by card.updated_at desc
|
||||||
|
limit 1
|
||||||
|
""",
|
||||||
|
rs -> rs.next() ? (UUID) rs.getObject("id") : null,
|
||||||
|
cardNationNumericCode,
|
||||||
|
cardNumber
|
||||||
|
);
|
||||||
|
}
|
||||||
return jdbcTemplate.query(
|
return jdbcTemplate.query(
|
||||||
"""
|
"""
|
||||||
select card.id
|
select card.id
|
||||||
|
|
@ -782,6 +801,7 @@ public class DriverIdentityRepository {
|
||||||
private UUID createDriverCard(
|
private UUID createDriverCard(
|
||||||
UUID driverId,
|
UUID driverId,
|
||||||
String cardNation,
|
String cardNation,
|
||||||
|
Integer cardNationNumericCode,
|
||||||
String cardNumber,
|
String cardNumber,
|
||||||
OffsetDateTime sourceUpdatedAt,
|
OffsetDateTime sourceUpdatedAt,
|
||||||
Map<String, Object> payload
|
Map<String, Object> payload
|
||||||
|
|
@ -790,12 +810,13 @@ public class DriverIdentityRepository {
|
||||||
jdbcTemplate.update(
|
jdbcTemplate.update(
|
||||||
"""
|
"""
|
||||||
insert into eventhub.driver_card(
|
insert into eventhub.driver_card(
|
||||||
id, driver_id, nation, card_number, source_updated_at, payload, updated_at
|
id, driver_id, nation, nation_numeric_code, card_number, source_updated_at, payload, updated_at
|
||||||
) values (?, ?, ?, ?, ?, ?::jsonb, now())
|
) values (?, ?, ?, ?, ?, ?, ?::jsonb, now())
|
||||||
""",
|
""",
|
||||||
driverCardId,
|
driverCardId,
|
||||||
driverId,
|
driverId,
|
||||||
cardNation,
|
cardNation,
|
||||||
|
cardNationNumericCode,
|
||||||
cardNumber,
|
cardNumber,
|
||||||
sourceUpdatedAt,
|
sourceUpdatedAt,
|
||||||
toJson(payload)
|
toJson(payload)
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ import at.procon.eventhub.dto.VehicleRefDto;
|
||||||
import at.procon.eventhub.dto.VehicleRegistrationRefDto;
|
import at.procon.eventhub.dto.VehicleRegistrationRefDto;
|
||||||
import at.procon.eventhub.processing.model.UnifiedDriverEventsRequest;
|
import at.procon.eventhub.processing.model.UnifiedDriverEventsRequest;
|
||||||
import at.procon.eventhub.processing.model.UnifiedVehicleEventsRequest;
|
import at.procon.eventhub.processing.model.UnifiedVehicleEventsRequest;
|
||||||
|
import at.procon.eventhub.reference.TachographNationRegistry;
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
|
@ -149,11 +150,13 @@ public class EventHubEventReadRepository {
|
||||||
detail.attributes,
|
detail.attributes,
|
||||||
driver.source_driver_entity_id,
|
driver.source_driver_entity_id,
|
||||||
driver_card.nation as driver_card_nation,
|
driver_card.nation as driver_card_nation,
|
||||||
|
driver_card.nation_numeric_code as driver_card_nation_numeric_code,
|
||||||
driver_card.card_number as driver_card_number,
|
driver_card.card_number as driver_card_number,
|
||||||
vehicle.source_vehicle_entity_id,
|
vehicle.source_vehicle_entity_id,
|
||||||
vehicle.vin,
|
vehicle.vin,
|
||||||
registration.source_registration_entity_id,
|
registration.source_registration_entity_id,
|
||||||
registration.nation as vehicle_registration_nation,
|
registration.nation as vehicle_registration_nation,
|
||||||
|
registration.nation_numeric_code as vehicle_registration_nation_numeric_code,
|
||||||
registration.registration_number as vehicle_registration_number,
|
registration.registration_number as vehicle_registration_number,
|
||||||
event.driver_id,
|
event.driver_id,
|
||||||
event.vehicle_id,
|
event.vehicle_id,
|
||||||
|
|
@ -209,8 +212,15 @@ public class EventHubEventReadRepository {
|
||||||
sql.append(" and driver_card.card_number = ?");
|
sql.append(" and driver_card.card_number = ?");
|
||||||
params.add(driverCardNumber);
|
params.add(driverCardNumber);
|
||||||
if (driverCardNation != null) {
|
if (driverCardNation != null) {
|
||||||
|
TachographNationRegistry.NationResolution driverCardNationResolution =
|
||||||
|
TachographNationRegistry.resolve(driverCardNation, null);
|
||||||
|
if (driverCardNationResolution.numericCode() != null) {
|
||||||
|
sql.append(" and driver_card.nation_numeric_code = ?");
|
||||||
|
params.add(driverCardNationResolution.numericCode());
|
||||||
|
} else {
|
||||||
sql.append(" and driver_card.nation = ?");
|
sql.append(" and driver_card.nation = ?");
|
||||||
params.add(driverCardNation);
|
params.add(driverCardNationResolution.legacyNation());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (vehicleSourceEntityId != null) {
|
if (vehicleSourceEntityId != null) {
|
||||||
|
|
@ -225,8 +235,15 @@ public class EventHubEventReadRepository {
|
||||||
sql.append(" and registration.registration_number = ?");
|
sql.append(" and registration.registration_number = ?");
|
||||||
params.add(registrationNumber);
|
params.add(registrationNumber);
|
||||||
if (registrationNation != null) {
|
if (registrationNation != null) {
|
||||||
|
TachographNationRegistry.NationResolution registrationNationResolution =
|
||||||
|
TachographNationRegistry.resolve(registrationNation, null);
|
||||||
|
if (registrationNationResolution.numericCode() != null) {
|
||||||
|
sql.append(" and registration.nation_numeric_code = ?");
|
||||||
|
params.add(registrationNationResolution.numericCode());
|
||||||
|
} else {
|
||||||
sql.append(" and registration.nation = ?");
|
sql.append(" and registration.nation = ?");
|
||||||
params.add(registrationNation);
|
params.add(registrationNationResolution.legacyNation());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -275,7 +292,11 @@ public class EventHubEventReadRepository {
|
||||||
String cardNumber = rs.getString("driver_card_number");
|
String cardNumber = rs.getString("driver_card_number");
|
||||||
DriverCardRefDto driverCard = cardNumber == null
|
DriverCardRefDto driverCard = cardNumber == null
|
||||||
? null
|
? null
|
||||||
: new DriverCardRefDto(rs.getString("driver_card_nation"), cardNumber);
|
: new DriverCardRefDto(
|
||||||
|
rs.getString("driver_card_nation"),
|
||||||
|
integerValue(rs, "driver_card_nation_numeric_code"),
|
||||||
|
cardNumber
|
||||||
|
);
|
||||||
DriverRefDto driverRef = new DriverRefDto(sourceEntityId, driverCard);
|
DriverRefDto driverRef = new DriverRefDto(sourceEntityId, driverCard);
|
||||||
return driverRef.hasAnyReference() ? driverRef : null;
|
return driverRef.hasAnyReference() ? driverRef : null;
|
||||||
}
|
}
|
||||||
|
|
@ -284,7 +305,11 @@ public class EventHubEventReadRepository {
|
||||||
VehicleRegistrationRefDto registration = null;
|
VehicleRegistrationRefDto registration = null;
|
||||||
String registrationNumber = rs.getString("vehicle_registration_number");
|
String registrationNumber = rs.getString("vehicle_registration_number");
|
||||||
if (registrationNumber != null) {
|
if (registrationNumber != null) {
|
||||||
registration = new VehicleRegistrationRefDto(rs.getString("vehicle_registration_nation"), registrationNumber);
|
registration = new VehicleRegistrationRefDto(
|
||||||
|
rs.getString("vehicle_registration_nation"),
|
||||||
|
integerValue(rs, "vehicle_registration_nation_numeric_code"),
|
||||||
|
registrationNumber
|
||||||
|
);
|
||||||
}
|
}
|
||||||
VehicleRefDto vehicleRef = new VehicleRefDto(
|
VehicleRefDto vehicleRef = new VehicleRefDto(
|
||||||
firstNonBlank(
|
firstNonBlank(
|
||||||
|
|
@ -406,6 +431,17 @@ public class EventHubEventReadRepository {
|
||||||
return Long.parseLong(value.toString());
|
return Long.parseLong(value.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Integer integerValue(ResultSet rs, String column) throws SQLException {
|
||||||
|
Object value = rs.getObject(column);
|
||||||
|
if (value == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (value instanceof Number number) {
|
||||||
|
return number.intValue();
|
||||||
|
}
|
||||||
|
return Integer.parseInt(value.toString());
|
||||||
|
}
|
||||||
|
|
||||||
private JsonNode json(String value) {
|
private JsonNode json(String value) {
|
||||||
try {
|
try {
|
||||||
return value == null || value.isBlank()
|
return value == null || value.isBlank()
|
||||||
|
|
|
||||||
|
|
@ -532,14 +532,18 @@ public class EventRepository {
|
||||||
String vin = normalizeNullable(vehicleRef.vin());
|
String vin = normalizeNullable(vehicleRef.vin());
|
||||||
String sourceRegistrationEntityId = normalizeNullable(vehicleRef.sourceRegistrationEntityId());
|
String sourceRegistrationEntityId = normalizeNullable(vehicleRef.sourceRegistrationEntityId());
|
||||||
VehicleRegistrationRefDto registration = vehicleRef.vehicleRegistration();
|
VehicleRegistrationRefDto registration = vehicleRef.vehicleRegistration();
|
||||||
String registrationNation = registration == null ? null : normalizeNullable(registration.nation());
|
String registrationNationKey = registration == null
|
||||||
|
? null
|
||||||
|
: registration.nationNumericCode() == null
|
||||||
|
? normalizeNullable(registration.nation())
|
||||||
|
: registration.nationNumericCode().toString();
|
||||||
String registrationNumber = registration == null ? null : normalizeNullable(registration.number());
|
String registrationNumber = registration == null ? null : normalizeNullable(registration.number());
|
||||||
|
|
||||||
return String.join("|",
|
return String.join("|",
|
||||||
sourceVehicleEntityId == null ? "" : sourceVehicleEntityId,
|
sourceVehicleEntityId == null ? "" : sourceVehicleEntityId,
|
||||||
vin == null ? "" : vin,
|
vin == null ? "" : vin,
|
||||||
sourceRegistrationEntityId == null ? "" : sourceRegistrationEntityId,
|
sourceRegistrationEntityId == null ? "" : sourceRegistrationEntityId,
|
||||||
registrationNation == null ? "" : registrationNation,
|
registrationNationKey == null ? "" : registrationNationKey,
|
||||||
registrationNumber == null ? "" : registrationNumber
|
registrationNumber == null ? "" : registrationNumber
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@ public class VehicleIdentityRepository {
|
||||||
String sourceRegistrationEntityId = normalizeNullable(vehicleRef.sourceRegistrationEntityId());
|
String sourceRegistrationEntityId = normalizeNullable(vehicleRef.sourceRegistrationEntityId());
|
||||||
VehicleRegistrationRefDto registration = vehicleRef.vehicleRegistration();
|
VehicleRegistrationRefDto registration = vehicleRef.vehicleRegistration();
|
||||||
String registrationNation = registration == null ? null : normalizeNullable(registration.nation());
|
String registrationNation = registration == null ? null : normalizeNullable(registration.nation());
|
||||||
|
Integer registrationNationNumericCode = registration == null ? null : registration.nationNumericCode();
|
||||||
String registrationNumber = registration == null ? null : normalizeNullable(registration.number());
|
String registrationNumber = registration == null ? null : normalizeNullable(registration.number());
|
||||||
String registrationNationForCreate = creationNation(registrationNation, registrationNumber);
|
String registrationNationForCreate = creationNation(registrationNation, registrationNumber);
|
||||||
|
|
||||||
|
|
@ -49,14 +50,21 @@ public class VehicleIdentityRepository {
|
||||||
eventSourceId,
|
eventSourceId,
|
||||||
sourceRegistrationEntityId,
|
sourceRegistrationEntityId,
|
||||||
registrationNation,
|
registrationNation,
|
||||||
|
registrationNationNumericCode,
|
||||||
registrationNumber
|
registrationNumber
|
||||||
);
|
);
|
||||||
if (registrationId == null && (sourceRegistrationEntityId != null || registrationNumber != null)) {
|
if (registrationId == null && (sourceRegistrationEntityId != null || registrationNumber != null)) {
|
||||||
registrationId = createRegistration(
|
registrationId = createRegistration(
|
||||||
registrationNationForCreate,
|
registrationNationForCreate,
|
||||||
|
registrationNationNumericCode,
|
||||||
registrationNumber,
|
registrationNumber,
|
||||||
null,
|
null,
|
||||||
Map.of("source", "event")
|
Map.of(
|
||||||
|
"source", "event",
|
||||||
|
"registration_nation", registrationNationForCreate,
|
||||||
|
"registration_nation_numeric_code", registrationNationNumericCode,
|
||||||
|
"registration_number", registrationNumber
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (registrationId != null && sourceRegistrationEntityId != null) {
|
if (registrationId != null && sourceRegistrationEntityId != null) {
|
||||||
|
|
@ -95,7 +103,7 @@ public class VehicleIdentityRepository {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
touchVehicle(vehicleId, vin);
|
touchVehicle(vehicleId, vin);
|
||||||
touchRegistration(registrationId, registrationNationForCreate, registrationNumber);
|
touchRegistration(registrationId, registrationNationForCreate, registrationNationNumericCode, registrationNumber);
|
||||||
|
|
||||||
return new ResolvedVehicleReferenceResolution(
|
return new ResolvedVehicleReferenceResolution(
|
||||||
new ResolvedVehicleReference(vehicleId, registrationId),
|
new ResolvedVehicleReference(vehicleId, registrationId),
|
||||||
|
|
@ -617,6 +625,7 @@ public class VehicleIdentityRepository {
|
||||||
int eventSourceId,
|
int eventSourceId,
|
||||||
String sourceRegistrationEntityId,
|
String sourceRegistrationEntityId,
|
||||||
String nation,
|
String nation,
|
||||||
|
Integer nationNumericCode,
|
||||||
String registrationNumber
|
String registrationNumber
|
||||||
) {
|
) {
|
||||||
if (isYellowFoxSyntheticRegistrationNation(nation) && registrationNumber != null) {
|
if (isYellowFoxSyntheticRegistrationNation(nation) && registrationNumber != null) {
|
||||||
|
|
@ -628,7 +637,7 @@ public class VehicleIdentityRepository {
|
||||||
}
|
}
|
||||||
UUID registrationId = findRegistrationBySourceRegistrationEntityId(tenantKey, eventSourceId, sourceRegistrationEntityId);
|
UUID registrationId = findRegistrationBySourceRegistrationEntityId(tenantKey, eventSourceId, sourceRegistrationEntityId);
|
||||||
if (registrationId == null) {
|
if (registrationId == null) {
|
||||||
registrationId = findRegistrationByPlate(nation, registrationNumber);
|
registrationId = findRegistrationByPlate(nation, nationNumericCode, registrationNumber);
|
||||||
}
|
}
|
||||||
return registrationId;
|
return registrationId;
|
||||||
}
|
}
|
||||||
|
|
@ -696,10 +705,25 @@ public class VehicleIdentityRepository {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private UUID findRegistrationByPlate(String nation, String registrationNumber) {
|
private UUID findRegistrationByPlate(String nation, Integer nationNumericCode, String registrationNumber) {
|
||||||
if (nation == null || registrationNumber == null) {
|
if ((nation == null && nationNumericCode == null) || registrationNumber == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
if (nationNumericCode != null) {
|
||||||
|
return jdbcTemplate.query(
|
||||||
|
"""
|
||||||
|
select r.id
|
||||||
|
from eventhub.vehicle_registration r
|
||||||
|
where r.nation_numeric_code = ?
|
||||||
|
and r.registration_number = ?
|
||||||
|
order by r.updated_at desc
|
||||||
|
limit 1
|
||||||
|
""",
|
||||||
|
rs -> rs.next() ? (UUID) rs.getObject("id") : null,
|
||||||
|
nationNumericCode,
|
||||||
|
registrationNumber
|
||||||
|
);
|
||||||
|
}
|
||||||
return jdbcTemplate.query(
|
return jdbcTemplate.query(
|
||||||
"""
|
"""
|
||||||
select r.id
|
select r.id
|
||||||
|
|
@ -787,6 +811,7 @@ public class VehicleIdentityRepository {
|
||||||
|
|
||||||
private UUID createRegistration(
|
private UUID createRegistration(
|
||||||
String nation,
|
String nation,
|
||||||
|
Integer nationNumericCode,
|
||||||
String registrationNumber,
|
String registrationNumber,
|
||||||
OffsetDateTime sourceUpdatedAt,
|
OffsetDateTime sourceUpdatedAt,
|
||||||
Map<String, Object> payload
|
Map<String, Object> payload
|
||||||
|
|
@ -798,11 +823,12 @@ public class VehicleIdentityRepository {
|
||||||
jdbcTemplate.update(
|
jdbcTemplate.update(
|
||||||
"""
|
"""
|
||||||
insert into eventhub.vehicle_registration(
|
insert into eventhub.vehicle_registration(
|
||||||
id, nation, registration_number, source_updated_at, payload, updated_at
|
id, nation, nation_numeric_code, registration_number, source_updated_at, payload, updated_at
|
||||||
) values (?, ?, ?, ?, ?::jsonb, now())
|
) values (?, ?, ?, ?, ?, ?::jsonb, now())
|
||||||
""",
|
""",
|
||||||
registrationId,
|
registrationId,
|
||||||
nation,
|
nation,
|
||||||
|
nationNumericCode,
|
||||||
registrationNumber,
|
registrationNumber,
|
||||||
sourceUpdatedAt,
|
sourceUpdatedAt,
|
||||||
toJson(payload)
|
toJson(payload)
|
||||||
|
|
@ -946,26 +972,30 @@ public class VehicleIdentityRepository {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void touchRegistration(UUID registrationId, String nation, String registrationNumber) {
|
private void touchRegistration(UUID registrationId, String nation, Integer nationNumericCode, String registrationNumber) {
|
||||||
if (registrationId == null || (nation == null && registrationNumber == null)) {
|
if (registrationId == null || (nation == null && nationNumericCode == null && registrationNumber == null)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
jdbcTemplate.update(
|
jdbcTemplate.update(
|
||||||
"""
|
"""
|
||||||
update eventhub.vehicle_registration
|
update eventhub.vehicle_registration
|
||||||
set nation = coalesce(cast(? as text), nation),
|
set nation = coalesce(cast(? as text), nation),
|
||||||
|
nation_numeric_code = coalesce(cast(? as integer), nation_numeric_code),
|
||||||
registration_number = coalesce(cast(? as text), registration_number),
|
registration_number = coalesce(cast(? as text), registration_number),
|
||||||
updated_at = now()
|
updated_at = now()
|
||||||
where id = ?
|
where id = ?
|
||||||
and (
|
and (
|
||||||
(nation is null and cast(? as text) is not null)
|
(nation is null and cast(? as text) is not null)
|
||||||
|
or (nation_numeric_code is null and cast(? as integer) is not null)
|
||||||
or (registration_number is null and cast(? as text) is not null)
|
or (registration_number is null and cast(? as text) is not null)
|
||||||
)
|
)
|
||||||
""",
|
""",
|
||||||
nation,
|
nation,
|
||||||
|
nationNumericCode,
|
||||||
registrationNumber,
|
registrationNumber,
|
||||||
registrationId,
|
registrationId,
|
||||||
nation,
|
nation,
|
||||||
|
nationNumericCode,
|
||||||
registrationNumber
|
registrationNumber
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ import at.procon.eventhub.processing.model.UnifiedDiscoveredVehicleRef;
|
||||||
import at.procon.eventhub.processing.model.UnifiedEventSourceFamily;
|
import at.procon.eventhub.processing.model.UnifiedEventSourceFamily;
|
||||||
import at.procon.eventhub.processing.model.UnifiedRuntimeEventBackend;
|
import at.procon.eventhub.processing.model.UnifiedRuntimeEventBackend;
|
||||||
import at.procon.eventhub.processing.model.UnifiedRuntimeProcessingRequest;
|
import at.procon.eventhub.processing.model.UnifiedRuntimeProcessingRequest;
|
||||||
|
import at.procon.eventhub.reference.TachographNationRegistry;
|
||||||
import at.procon.eventhub.tachograph.dto.TachographImportRequest;
|
import at.procon.eventhub.tachograph.dto.TachographImportRequest;
|
||||||
import at.procon.eventhub.tachograph.service.TachographExtractionDefinitionRegistry;
|
import at.procon.eventhub.tachograph.service.TachographExtractionDefinitionRegistry;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
@ -199,11 +200,11 @@ public class TachographDbRuntimeEventLoader implements RuntimeDriverEventLoader,
|
||||||
params.put("lastSourcePackageImportedAt", null);
|
params.put("lastSourcePackageImportedAt", null);
|
||||||
params.put("lastSourcePackageIdNumeric", null);
|
params.put("lastSourcePackageIdNumeric", null);
|
||||||
params.put("driverSourceEntityId", request.driverSourceEntityId());
|
params.put("driverSourceEntityId", request.driverSourceEntityId());
|
||||||
params.put("driverCardNation", request.driverCardNation());
|
params.put("driverCardNation", alphaNation(request.driverCardNation()));
|
||||||
params.put("driverCardNumber", request.driverCardNumber());
|
params.put("driverCardNumber", request.driverCardNumber());
|
||||||
params.put("vehicleSourceEntityId", vehicleRef == null ? null : vehicleRef.sourceVehicleEntityId());
|
params.put("vehicleSourceEntityId", vehicleRef == null ? null : vehicleRef.sourceVehicleEntityId());
|
||||||
params.put("vehicleVin", vehicleRef == null ? null : vehicleRef.vin());
|
params.put("vehicleVin", vehicleRef == null ? null : vehicleRef.vin());
|
||||||
params.put("vehicleRegistrationNation", vehicleRef == null ? null : vehicleRef.registrationNation());
|
params.put("vehicleRegistrationNation", vehicleRef == null ? null : alphaNation(vehicleRef.registrationNation()));
|
||||||
params.put("vehicleRegistrationNumber", vehicleRef == null ? null : vehicleRef.registrationNumber());
|
params.put("vehicleRegistrationNumber", vehicleRef == null ? null : vehicleRef.registrationNumber());
|
||||||
return params;
|
return params;
|
||||||
}
|
}
|
||||||
|
|
@ -251,4 +252,8 @@ public class TachographDbRuntimeEventLoader implements RuntimeDriverEventLoader,
|
||||||
throw new IllegalStateException("Failed to load tachograph runtime SQL " + sqlResource, ex);
|
throw new IllegalStateException("Failed to load tachograph runtime SQL " + sqlResource, ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String alphaNation(String rawNation) {
|
||||||
|
return TachographNationRegistry.alphaCode(rawNation, null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import at.procon.eventhub.dto.EventHubEventDto;
|
||||||
import at.procon.eventhub.dto.VehicleRefDto;
|
import at.procon.eventhub.dto.VehicleRefDto;
|
||||||
import at.procon.eventhub.processing.model.UnifiedEventSourceFamily;
|
import at.procon.eventhub.processing.model.UnifiedEventSourceFamily;
|
||||||
import at.procon.eventhub.processing.model.UnifiedVehicleEventsRequest;
|
import at.procon.eventhub.processing.model.UnifiedVehicleEventsRequest;
|
||||||
|
import at.procon.eventhub.reference.TachographNationRegistry;
|
||||||
import at.procon.eventhub.tachographfilesession.model.TachographFileSession;
|
import at.procon.eventhub.tachographfilesession.model.TachographFileSession;
|
||||||
import at.procon.eventhub.tachographfilesession.service.DriverTimelineEventBuilder;
|
import at.procon.eventhub.tachographfilesession.service.DriverTimelineEventBuilder;
|
||||||
import at.procon.eventhub.tachographfilesession.service.TachographFileSessionNotFoundException;
|
import at.procon.eventhub.tachographfilesession.service.TachographFileSessionNotFoundException;
|
||||||
|
|
@ -57,8 +58,7 @@ public class TachographFileSessionUnifiedVehicleEventSource implements UnifiedVe
|
||||||
return request.registrationNumber() != null
|
return request.registrationNumber() != null
|
||||||
&& vehicleRef.vehicleRegistration() != null
|
&& vehicleRef.vehicleRegistration() != null
|
||||||
&& request.registrationNumber().equals(vehicleRef.vehicleRegistration().number())
|
&& request.registrationNumber().equals(vehicleRef.vehicleRegistration().number())
|
||||||
&& (request.registrationNation() == null
|
&& matchesNation(request.registrationNation(), vehicleRef.vehicleRegistration().nation(), vehicleRef.vehicleRegistration().nationNumericCode());
|
||||||
|| request.registrationNation().equals(vehicleRef.vehicleRegistration().nation()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean withinWindow(
|
private boolean withinWindow(
|
||||||
|
|
@ -74,4 +74,18 @@ public class TachographFileSessionUnifiedVehicleEventSource implements UnifiedVe
|
||||||
}
|
}
|
||||||
return occurredTo == null || !occurredAt.isAfter(occurredTo);
|
return occurredTo == null || !occurredAt.isAfter(occurredTo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean matchesNation(String requestedNation, String actualNation, Integer actualNationNumericCode) {
|
||||||
|
if (requestedNation == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
TachographNationRegistry.NationResolution requested = TachographNationRegistry.resolve(requestedNation, null);
|
||||||
|
TachographNationRegistry.NationResolution actual = TachographNationRegistry.resolve(actualNation, actualNationNumericCode);
|
||||||
|
if (requested.numericCode() != null || actual.numericCode() != null) {
|
||||||
|
return requested.numericCode() != null
|
||||||
|
&& actual.numericCode() != null
|
||||||
|
&& requested.numericCode().equals(actual.numericCode());
|
||||||
|
}
|
||||||
|
return requested.legacyNation() != null && requested.legacyNation().equals(actual.legacyNation());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -97,7 +97,11 @@ public class UnifiedRuntimeEventAssemblyService {
|
||||||
UnifiedDiscoveredVehicleRef candidate = new UnifiedDiscoveredVehicleRef(
|
UnifiedDiscoveredVehicleRef candidate = new UnifiedDiscoveredVehicleRef(
|
||||||
vehicleRef.sourceVehicleEntityId(),
|
vehicleRef.sourceVehicleEntityId(),
|
||||||
vehicleRef.vin(),
|
vehicleRef.vin(),
|
||||||
vehicleRef.vehicleRegistration() == null ? null : vehicleRef.vehicleRegistration().nation(),
|
vehicleRef.vehicleRegistration() == null
|
||||||
|
? null
|
||||||
|
: vehicleRef.vehicleRegistration().nationNumericCode() == null
|
||||||
|
? vehicleRef.vehicleRegistration().nation()
|
||||||
|
: vehicleRef.vehicleRegistration().nationNumericCode().toString(),
|
||||||
vehicleRef.vehicleRegistration() == null ? null : vehicleRef.vehicleRegistration().number()
|
vehicleRef.vehicleRegistration() == null ? null : vehicleRef.vehicleRegistration().number()
|
||||||
);
|
);
|
||||||
if (!candidate.hasAnyReference()) {
|
if (!candidate.hasAnyReference()) {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,178 @@
|
||||||
|
package at.procon.eventhub.reference;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
public final class TachographNationRegistry {
|
||||||
|
|
||||||
|
private static final Pattern UNKNOWN_NUMERIC_PATTERN = Pattern.compile("(?i)^unknown\\s+([0-9]+)$");
|
||||||
|
private static final String RESOURCE_PATH = "/reference/nation.csv";
|
||||||
|
private static final Map<Integer, NationRecord> BY_NUMERIC_CODE;
|
||||||
|
private static final Map<String, NationRecord> BY_ALPHA_CODE;
|
||||||
|
|
||||||
|
static {
|
||||||
|
Map<Integer, NationRecord> byNumeric = new LinkedHashMap<>();
|
||||||
|
Map<String, NationRecord> byAlpha = new LinkedHashMap<>();
|
||||||
|
try {
|
||||||
|
var inputStream = TachographNationRegistry.class.getResourceAsStream(RESOURCE_PATH);
|
||||||
|
if (inputStream == null) {
|
||||||
|
throw new IllegalStateException("Missing tachograph nation reference data " + RESOURCE_PATH);
|
||||||
|
}
|
||||||
|
try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8))) {
|
||||||
|
reader.readLine();
|
||||||
|
String line;
|
||||||
|
while ((line = reader.readLine()) != null) {
|
||||||
|
if (line.isBlank()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String[] parts = line.split(";", -1);
|
||||||
|
if (parts.length < 5) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Integer numericCode = parseInteger(parts[3]);
|
||||||
|
if (numericCode == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String name = normalizeNullable(parts[1]);
|
||||||
|
String alphaCode = normalizeAlpha(parts[2]);
|
||||||
|
String defaultLanguageCode = normalizeNullable(parts[4]);
|
||||||
|
NationRecord record = new NationRecord(numericCode, alphaCode, name, defaultLanguageCode, true);
|
||||||
|
byNumeric.put(numericCode, record);
|
||||||
|
if (alphaCode != null) {
|
||||||
|
byAlpha.put(alphaCode, record);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (IOException ex) {
|
||||||
|
throw new IllegalStateException("Failed to load tachograph nation reference data.", ex);
|
||||||
|
}
|
||||||
|
BY_NUMERIC_CODE = Collections.unmodifiableMap(byNumeric);
|
||||||
|
BY_ALPHA_CODE = Collections.unmodifiableMap(byAlpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
private TachographNationRegistry() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static NationResolution resolve(String legacyNation, Integer nationNumericCode) {
|
||||||
|
String normalizedLegacyNation = normalizeNullable(legacyNation);
|
||||||
|
if (nationNumericCode != null) {
|
||||||
|
NationRecord record = BY_NUMERIC_CODE.get(nationNumericCode);
|
||||||
|
if (record != null) {
|
||||||
|
return new NationResolution(
|
||||||
|
record.alphaCode(),
|
||||||
|
record.numericCode(),
|
||||||
|
record.name(),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return new NationResolution(
|
||||||
|
normalizedLegacyNation != null ? normalizedLegacyNation : unknownLabel(nationNumericCode),
|
||||||
|
nationNumericCode,
|
||||||
|
unknownLabel(nationNumericCode),
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (normalizedLegacyNation == null) {
|
||||||
|
return NationResolution.empty();
|
||||||
|
}
|
||||||
|
Integer parsedNumericCode = parseInteger(normalizedLegacyNation);
|
||||||
|
if (parsedNumericCode != null) {
|
||||||
|
return resolve(null, parsedNumericCode);
|
||||||
|
}
|
||||||
|
Matcher unknownMatcher = UNKNOWN_NUMERIC_PATTERN.matcher(normalizedLegacyNation);
|
||||||
|
if (unknownMatcher.matches()) {
|
||||||
|
Integer unknownNumericCode = parseInteger(unknownMatcher.group(1));
|
||||||
|
if (unknownNumericCode != null) {
|
||||||
|
return resolve(normalizedLegacyNation, unknownNumericCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NationRecord record = BY_ALPHA_CODE.get(normalizedLegacyNation.toUpperCase(Locale.ROOT));
|
||||||
|
if (record != null) {
|
||||||
|
return new NationResolution(
|
||||||
|
record.alphaCode(),
|
||||||
|
record.numericCode(),
|
||||||
|
record.name(),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return new NationResolution(normalizedLegacyNation, null, null, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Integer numericCode(String legacyNation, Integer nationNumericCode) {
|
||||||
|
return resolve(legacyNation, nationNumericCode).numericCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String alphaCode(String legacyNation, Integer nationNumericCode) {
|
||||||
|
return resolve(legacyNation, nationNumericCode).legacyNation();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static NationRecord recordByNumericCode(Integer numericCode) {
|
||||||
|
if (numericCode == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
NationRecord record = BY_NUMERIC_CODE.get(numericCode);
|
||||||
|
return record != null
|
||||||
|
? record
|
||||||
|
: new NationRecord(numericCode, null, unknownLabel(numericCode), null, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String normalizeNullable(String value) {
|
||||||
|
if (value == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
String trimmed = value.trim();
|
||||||
|
if (trimmed.equalsIgnoreCase("NULL")) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return trimmed.isEmpty() ? null : trimmed;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String normalizeAlpha(String value) {
|
||||||
|
String normalized = normalizeNullable(value);
|
||||||
|
return normalized == null ? null : normalized.toUpperCase(Locale.ROOT);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Integer parseInteger(String value) {
|
||||||
|
String normalized = normalizeNullable(value);
|
||||||
|
if (normalized == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return Integer.parseInt(normalized);
|
||||||
|
} catch (NumberFormatException ignored) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String unknownLabel(Integer numericCode) {
|
||||||
|
return numericCode == null ? null : "Unknown " + numericCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public record NationRecord(
|
||||||
|
Integer numericCode,
|
||||||
|
String alphaCode,
|
||||||
|
String name,
|
||||||
|
String defaultLanguageCode,
|
||||||
|
boolean known
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public record NationResolution(
|
||||||
|
String legacyNation,
|
||||||
|
Integer numericCode,
|
||||||
|
String displayName,
|
||||||
|
boolean known
|
||||||
|
) {
|
||||||
|
public static NationResolution empty() {
|
||||||
|
return new NationResolution(null, null, null, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -5,6 +5,7 @@ import at.procon.eventhub.dto.CardStatus;
|
||||||
import at.procon.eventhub.dto.DriverCardRefDto;
|
import at.procon.eventhub.dto.DriverCardRefDto;
|
||||||
import at.procon.eventhub.dto.DrivingStatus;
|
import at.procon.eventhub.dto.DrivingStatus;
|
||||||
import at.procon.eventhub.dto.EventDetailsDto;
|
import at.procon.eventhub.dto.EventDetailsDto;
|
||||||
|
import at.procon.eventhub.reference.TachographNationRegistry;
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
|
@ -39,6 +40,7 @@ public class EventDetailsFactory {
|
||||||
put(attributes, "cardStatus", cardStatus);
|
put(attributes, "cardStatus", cardStatus);
|
||||||
if (driverCard != null && driverCard.hasValue()) {
|
if (driverCard != null && driverCard.hasValue()) {
|
||||||
put(attributes, "cardNation", driverCard.nation());
|
put(attributes, "cardNation", driverCard.nation());
|
||||||
|
put(attributes, "cardNationNumericCode", driverCard.nationNumericCode());
|
||||||
put(attributes, "cardNumber", driverCard.number());
|
put(attributes, "cardNumber", driverCard.number());
|
||||||
}
|
}
|
||||||
return new EventDetailsDto("DRIVER_CARD", objectMapper.valueToTree(attributes));
|
return new EventDetailsDto("DRIVER_CARD", objectMapper.valueToTree(attributes));
|
||||||
|
|
@ -52,15 +54,21 @@ public class EventDetailsFactory {
|
||||||
|
|
||||||
public EventDetailsDto place(String country, String region) {
|
public EventDetailsDto place(String country, String region) {
|
||||||
Map<String, Object> attributes = new LinkedHashMap<>();
|
Map<String, Object> attributes = new LinkedHashMap<>();
|
||||||
put(attributes, "country", country);
|
TachographNationRegistry.NationResolution nationResolution = TachographNationRegistry.resolve(country, null);
|
||||||
|
put(attributes, "country", nationResolution.legacyNation());
|
||||||
|
put(attributes, "countryNumericCode", nationResolution.numericCode());
|
||||||
put(attributes, "region", region);
|
put(attributes, "region", region);
|
||||||
return new EventDetailsDto("PLACE", objectMapper.valueToTree(attributes));
|
return new EventDetailsDto("PLACE", objectMapper.valueToTree(attributes));
|
||||||
}
|
}
|
||||||
|
|
||||||
public EventDetailsDto borderCrossing(String countryFrom, String countryTo) {
|
public EventDetailsDto borderCrossing(String countryFrom, String countryTo) {
|
||||||
Map<String, Object> attributes = new LinkedHashMap<>();
|
Map<String, Object> attributes = new LinkedHashMap<>();
|
||||||
put(attributes, "countryFrom", countryFrom);
|
TachographNationRegistry.NationResolution fromResolution = TachographNationRegistry.resolve(countryFrom, null);
|
||||||
put(attributes, "countryTo", countryTo);
|
TachographNationRegistry.NationResolution toResolution = TachographNationRegistry.resolve(countryTo, null);
|
||||||
|
put(attributes, "countryFrom", fromResolution.legacyNation());
|
||||||
|
put(attributes, "countryFromNumericCode", fromResolution.numericCode());
|
||||||
|
put(attributes, "countryTo", toResolution.legacyNation());
|
||||||
|
put(attributes, "countryToNumericCode", toResolution.numericCode());
|
||||||
return new EventDetailsDto("BORDER_CROSSING", objectMapper.valueToTree(attributes));
|
return new EventDetailsDto("BORDER_CROSSING", objectMapper.valueToTree(attributes));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -145,6 +145,84 @@ create table if not exists eventhub.source_master_relation (
|
||||||
constraint chk_source_master_relation_valid_time_order check (valid_from is null or valid_to is null or valid_from <= valid_to)
|
constraint chk_source_master_relation_valid_time_order check (valid_from is null or valid_to is null or valid_from <= valid_to)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
create table if not exists eventhub.nation (
|
||||||
|
numeric_code integer primary key,
|
||||||
|
alpha_code text,
|
||||||
|
name text not null,
|
||||||
|
default_language_code text,
|
||||||
|
is_known boolean not null default true,
|
||||||
|
created_at timestamptz not null default now(),
|
||||||
|
updated_at timestamptz not null default now()
|
||||||
|
);
|
||||||
|
|
||||||
|
insert into eventhub.nation(numeric_code, alpha_code, name, default_language_code, is_known)
|
||||||
|
values
|
||||||
|
(0, '0', 'Unknown 0', null, true),
|
||||||
|
(1, 'A', 'Austria', 'de-AT', true),
|
||||||
|
(2, 'AL', 'Albania', 'sq-AL', true),
|
||||||
|
(3, 'AND', 'Andorra', 'ca', true),
|
||||||
|
(4, 'ARM', 'Armenia', 'hy-AM', true),
|
||||||
|
(5, 'AZ', 'Azerbaijan', 'az', true),
|
||||||
|
(6, 'B', 'Belgium', null, true),
|
||||||
|
(7, 'BG', 'Bulgaria', 'bg-BG', true),
|
||||||
|
(8, 'BIH', 'Bosnia Herzegovina', null, true),
|
||||||
|
(9, 'BY', 'Belarus', 'be-BY', true),
|
||||||
|
(10, 'CH', 'Switzerland', 'de-CH', true),
|
||||||
|
(11, 'CY', 'Cyprus', null, true),
|
||||||
|
(12, 'CZ', 'Czech Republic', 'cs-CZ', true),
|
||||||
|
(13, 'D', 'Germany', 'de-DE', true),
|
||||||
|
(14, 'DK', 'Denmark', 'da-DK', true),
|
||||||
|
(15, 'E', 'Spain', 'es-ES', true),
|
||||||
|
(16, 'EST', 'Estonia', 'et-EE', true),
|
||||||
|
(17, 'F', 'France', 'fr-FR', true),
|
||||||
|
(18, 'FIN', 'Finland', 'fi-FI', true),
|
||||||
|
(19, 'FL', 'Liechtenstein', 'de-LI', true),
|
||||||
|
(20, 'FR', 'Faroe Islands', 'fo-FO', true),
|
||||||
|
(21, 'UK', 'United Kingdom', 'en-GB', true),
|
||||||
|
(22, 'GE', 'Georgia', 'ka-GE', true),
|
||||||
|
(23, 'GR', 'Greece', 'el-GR', true),
|
||||||
|
(24, 'H', 'Hungary', 'hu-HU', true),
|
||||||
|
(25, 'HR', 'Croatia', 'hr-HR', true),
|
||||||
|
(26, 'I', 'Italy', 'it-IT', true),
|
||||||
|
(27, 'IRL', 'Ireland', 'en-IE', true),
|
||||||
|
(28, 'IS', 'Iceland', 'is-IS', true),
|
||||||
|
(29, 'KZ', 'Kazakhstan', 'kk-KZ', true),
|
||||||
|
(30, 'L', 'Luxembourg', 'de-LU', true),
|
||||||
|
(31, 'LT', 'Lithuania', 'lt-LT', true),
|
||||||
|
(32, 'LV', 'Latvia', 'lv-LV', true),
|
||||||
|
(33, 'M', 'Malta', null, true),
|
||||||
|
(34, 'MC', 'Monaco', 'fr-MC', true),
|
||||||
|
(35, 'MD', 'Moldova', 'ro', true),
|
||||||
|
(36, 'MK', 'North Macedonia', 'mk-MK', true),
|
||||||
|
(37, 'N', 'Norway', 'no', true),
|
||||||
|
(38, 'NL', 'Netherlands', 'nl-NL', true),
|
||||||
|
(39, 'P', 'Portugal', 'pt-PT', true),
|
||||||
|
(40, 'PL', 'Poland', 'pl-PL', true),
|
||||||
|
(41, 'RO', 'Romania', 'ro-RO', true),
|
||||||
|
(42, 'RSM', 'San Marino', 'it-IT', true),
|
||||||
|
(43, 'RUS', 'Russia', 'ru-RU', true),
|
||||||
|
(44, 'S', 'Sweden', 'sv-SE', true),
|
||||||
|
(45, 'SK', 'Slovakia', 'sk-SK', true),
|
||||||
|
(46, 'SLO', 'Slovenia', 'sl-SI', true),
|
||||||
|
(47, 'TM', 'Turkmenistan', null, true),
|
||||||
|
(48, 'TR', 'Turkey', 'tr-TR', true),
|
||||||
|
(49, 'UA', 'Ukraine', 'uk-UA', true),
|
||||||
|
(50, 'V', 'Vatican City', 'it-IT', true),
|
||||||
|
(51, 'YU', 'Yugoslavia', null, true),
|
||||||
|
(52, 'MNE', 'Montenegro', null, true),
|
||||||
|
(53, 'SRB', 'Serbia', null, true),
|
||||||
|
(54, 'UZ', 'Uzbekistan', null, true),
|
||||||
|
(55, 'TJ', 'Tajikistan', null, true),
|
||||||
|
(253, 'EC', 'European Community', null, true),
|
||||||
|
(254, 'EUR', 'Rest of Europe', null, true),
|
||||||
|
(255, 'WLD', 'Rest of the world', null, true)
|
||||||
|
on conflict (numeric_code) do update set
|
||||||
|
alpha_code = excluded.alpha_code,
|
||||||
|
name = excluded.name,
|
||||||
|
default_language_code = excluded.default_language_code,
|
||||||
|
is_known = excluded.is_known,
|
||||||
|
updated_at = now();
|
||||||
|
|
||||||
create table if not exists eventhub.driver (
|
create table if not exists eventhub.driver (
|
||||||
id uuid primary key,
|
id uuid primary key,
|
||||||
first_names text,
|
first_names text,
|
||||||
|
|
@ -160,6 +238,7 @@ create table if not exists eventhub.driver_card (
|
||||||
id uuid primary key,
|
id uuid primary key,
|
||||||
driver_id uuid references eventhub.driver(id),
|
driver_id uuid references eventhub.driver(id),
|
||||||
nation text not null,
|
nation text not null,
|
||||||
|
nation_numeric_code integer references eventhub.nation(numeric_code),
|
||||||
card_number text not null,
|
card_number text not null,
|
||||||
source_updated_at timestamptz,
|
source_updated_at timestamptz,
|
||||||
payload jsonb not null default '{}'::jsonb,
|
payload jsonb not null default '{}'::jsonb,
|
||||||
|
|
@ -203,6 +282,7 @@ create table if not exists eventhub.vehicle (
|
||||||
create table if not exists eventhub.vehicle_registration (
|
create table if not exists eventhub.vehicle_registration (
|
||||||
id uuid primary key,
|
id uuid primary key,
|
||||||
nation text not null,
|
nation text not null,
|
||||||
|
nation_numeric_code integer references eventhub.nation(numeric_code),
|
||||||
registration_number text not null,
|
registration_number text not null,
|
||||||
source_updated_at timestamptz,
|
source_updated_at timestamptz,
|
||||||
payload jsonb not null default '{}'::jsonb,
|
payload jsonb not null default '{}'::jsonb,
|
||||||
|
|
@ -353,6 +433,10 @@ create index if not exists idx_vehicle_vin
|
||||||
create index if not exists idx_vehicle_registration_plate
|
create index if not exists idx_vehicle_registration_plate
|
||||||
on eventhub.vehicle_registration(nation, registration_number);
|
on eventhub.vehicle_registration(nation, registration_number);
|
||||||
|
|
||||||
|
create index if not exists idx_vehicle_registration_numeric_key
|
||||||
|
on eventhub.vehicle_registration(nation_numeric_code, registration_number)
|
||||||
|
where nation_numeric_code is not null;
|
||||||
|
|
||||||
create index if not exists idx_vehicle_registration_assignment_registration_time
|
create index if not exists idx_vehicle_registration_assignment_registration_time
|
||||||
on eventhub.vehicle_registration_assignment(vehicle_registration_id, valid_from desc, valid_to);
|
on eventhub.vehicle_registration_assignment(vehicle_registration_id, valid_from desc, valid_to);
|
||||||
|
|
||||||
|
|
@ -382,6 +466,10 @@ create index if not exists idx_event_domain_type_time
|
||||||
create index if not exists idx_driver_card_key
|
create index if not exists idx_driver_card_key
|
||||||
on eventhub.driver_card(nation, card_number);
|
on eventhub.driver_card(nation, card_number);
|
||||||
|
|
||||||
|
create index if not exists idx_driver_card_numeric_key
|
||||||
|
on eventhub.driver_card(nation_numeric_code, card_number)
|
||||||
|
where nation_numeric_code is not null;
|
||||||
|
|
||||||
create index if not exists idx_driver_card_driver
|
create index if not exists idx_driver_card_driver
|
||||||
on eventhub.driver_card(driver_id)
|
on eventhub.driver_card(driver_id)
|
||||||
where driver_id is not null;
|
where driver_id is not null;
|
||||||
|
|
@ -396,6 +484,10 @@ create unique index if not exists ux_vehicle_vin
|
||||||
create unique index if not exists ux_vehicle_registration_plate
|
create unique index if not exists ux_vehicle_registration_plate
|
||||||
on eventhub.vehicle_registration(nation, registration_number);
|
on eventhub.vehicle_registration(nation, registration_number);
|
||||||
|
|
||||||
|
create unique index if not exists ux_eventhub_nation_alpha_code
|
||||||
|
on eventhub.nation(alpha_code)
|
||||||
|
where alpha_code is not null;
|
||||||
|
|
||||||
create index if not exists idx_source_driver_identity_driver
|
create index if not exists idx_source_driver_identity_driver
|
||||||
on eventhub.source_driver_identity(driver_id);
|
on eventhub.source_driver_identity(driver_id);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,147 @@
|
||||||
|
create table if not exists eventhub.nation (
|
||||||
|
numeric_code integer primary key,
|
||||||
|
alpha_code text,
|
||||||
|
name text not null,
|
||||||
|
default_language_code text,
|
||||||
|
is_known boolean not null default true,
|
||||||
|
created_at timestamptz not null default now(),
|
||||||
|
updated_at timestamptz not null default now()
|
||||||
|
);
|
||||||
|
|
||||||
|
create unique index if not exists ux_eventhub_nation_alpha_code
|
||||||
|
on eventhub.nation(alpha_code)
|
||||||
|
where alpha_code is not null;
|
||||||
|
|
||||||
|
insert into eventhub.nation(numeric_code, alpha_code, name, default_language_code, is_known)
|
||||||
|
values
|
||||||
|
(0, '0', 'Unknown 0', null, true),
|
||||||
|
(1, 'A', 'Austria', 'de-AT', true),
|
||||||
|
(2, 'AL', 'Albania', 'sq-AL', true),
|
||||||
|
(3, 'AND', 'Andorra', 'ca', true),
|
||||||
|
(4, 'ARM', 'Armenia', 'hy-AM', true),
|
||||||
|
(5, 'AZ', 'Azerbaijan', 'az', true),
|
||||||
|
(6, 'B', 'Belgium', null, true),
|
||||||
|
(7, 'BG', 'Bulgaria', 'bg-BG', true),
|
||||||
|
(8, 'BIH', 'Bosnia Herzegovina', null, true),
|
||||||
|
(9, 'BY', 'Belarus', 'be-BY', true),
|
||||||
|
(10, 'CH', 'Switzerland', 'de-CH', true),
|
||||||
|
(11, 'CY', 'Cyprus', null, true),
|
||||||
|
(12, 'CZ', 'Czech Republic', 'cs-CZ', true),
|
||||||
|
(13, 'D', 'Germany', 'de-DE', true),
|
||||||
|
(14, 'DK', 'Denmark', 'da-DK', true),
|
||||||
|
(15, 'E', 'Spain', 'es-ES', true),
|
||||||
|
(16, 'EST', 'Estonia', 'et-EE', true),
|
||||||
|
(17, 'F', 'France', 'fr-FR', true),
|
||||||
|
(18, 'FIN', 'Finland', 'fi-FI', true),
|
||||||
|
(19, 'FL', 'Liechtenstein', 'de-LI', true),
|
||||||
|
(20, 'FR', 'Faroe Islands', 'fo-FO', true),
|
||||||
|
(21, 'UK', 'United Kingdom', 'en-GB', true),
|
||||||
|
(22, 'GE', 'Georgia', 'ka-GE', true),
|
||||||
|
(23, 'GR', 'Greece', 'el-GR', true),
|
||||||
|
(24, 'H', 'Hungary', 'hu-HU', true),
|
||||||
|
(25, 'HR', 'Croatia', 'hr-HR', true),
|
||||||
|
(26, 'I', 'Italy', 'it-IT', true),
|
||||||
|
(27, 'IRL', 'Ireland', 'en-IE', true),
|
||||||
|
(28, 'IS', 'Iceland', 'is-IS', true),
|
||||||
|
(29, 'KZ', 'Kazakhstan', 'kk-KZ', true),
|
||||||
|
(30, 'L', 'Luxembourg', 'de-LU', true),
|
||||||
|
(31, 'LT', 'Lithuania', 'lt-LT', true),
|
||||||
|
(32, 'LV', 'Latvia', 'lv-LV', true),
|
||||||
|
(33, 'M', 'Malta', null, true),
|
||||||
|
(34, 'MC', 'Monaco', 'fr-MC', true),
|
||||||
|
(35, 'MD', 'Moldova', 'ro', true),
|
||||||
|
(36, 'MK', 'North Macedonia', 'mk-MK', true),
|
||||||
|
(37, 'N', 'Norway', 'no', true),
|
||||||
|
(38, 'NL', 'Netherlands', 'nl-NL', true),
|
||||||
|
(39, 'P', 'Portugal', 'pt-PT', true),
|
||||||
|
(40, 'PL', 'Poland', 'pl-PL', true),
|
||||||
|
(41, 'RO', 'Romania', 'ro-RO', true),
|
||||||
|
(42, 'RSM', 'San Marino', 'it-IT', true),
|
||||||
|
(43, 'RUS', 'Russia', 'ru-RU', true),
|
||||||
|
(44, 'S', 'Sweden', 'sv-SE', true),
|
||||||
|
(45, 'SK', 'Slovakia', 'sk-SK', true),
|
||||||
|
(46, 'SLO', 'Slovenia', 'sl-SI', true),
|
||||||
|
(47, 'TM', 'Turkmenistan', null, true),
|
||||||
|
(48, 'TR', 'Turkey', 'tr-TR', true),
|
||||||
|
(49, 'UA', 'Ukraine', 'uk-UA', true),
|
||||||
|
(50, 'V', 'Vatican City', 'it-IT', true),
|
||||||
|
(51, 'YU', 'Yugoslavia', null, true),
|
||||||
|
(52, 'MNE', 'Montenegro', null, true),
|
||||||
|
(53, 'SRB', 'Serbia', null, true),
|
||||||
|
(54, 'UZ', 'Uzbekistan', null, true),
|
||||||
|
(55, 'TJ', 'Tajikistan', null, true),
|
||||||
|
(253, 'EC', 'European Community', null, true),
|
||||||
|
(254, 'EUR', 'Rest of Europe', null, true),
|
||||||
|
(255, 'WLD', 'Rest of the world', null, true)
|
||||||
|
on conflict (numeric_code) do update set
|
||||||
|
alpha_code = excluded.alpha_code,
|
||||||
|
name = excluded.name,
|
||||||
|
default_language_code = excluded.default_language_code,
|
||||||
|
is_known = excluded.is_known,
|
||||||
|
updated_at = now();
|
||||||
|
|
||||||
|
alter table eventhub.driver_card
|
||||||
|
add column if not exists nation_numeric_code integer references eventhub.nation(numeric_code);
|
||||||
|
|
||||||
|
alter table eventhub.vehicle_registration
|
||||||
|
add column if not exists nation_numeric_code integer references eventhub.nation(numeric_code);
|
||||||
|
|
||||||
|
create index if not exists idx_driver_card_numeric_key
|
||||||
|
on eventhub.driver_card(nation_numeric_code, card_number)
|
||||||
|
where nation_numeric_code is not null;
|
||||||
|
|
||||||
|
create index if not exists idx_vehicle_registration_numeric_key
|
||||||
|
on eventhub.vehicle_registration(nation_numeric_code, registration_number)
|
||||||
|
where nation_numeric_code is not null;
|
||||||
|
|
||||||
|
update eventhub.driver_card card
|
||||||
|
set nation_numeric_code = nation_ref.numeric_code
|
||||||
|
from eventhub.nation nation_ref
|
||||||
|
where card.nation_numeric_code is null
|
||||||
|
and upper(card.nation) = upper(nation_ref.alpha_code);
|
||||||
|
|
||||||
|
update eventhub.driver_card card
|
||||||
|
set nation_numeric_code = cast(card.nation as integer)
|
||||||
|
where card.nation_numeric_code is null
|
||||||
|
and trim(card.nation) ~ '^[0-9]+$';
|
||||||
|
|
||||||
|
update eventhub.driver_card card
|
||||||
|
set nation_numeric_code = cast(substring(card.nation from '^[Uu]nknown[[:space:]]+([0-9]+)$') as integer)
|
||||||
|
where card.nation_numeric_code is null
|
||||||
|
and substring(card.nation from '^[Uu]nknown[[:space:]]+([0-9]+)$') is not null;
|
||||||
|
|
||||||
|
update eventhub.driver_card card
|
||||||
|
set nation = coalesce(nation_ref.alpha_code, 'Unknown ' || card.nation_numeric_code::text)
|
||||||
|
from eventhub.nation nation_ref
|
||||||
|
where card.nation_numeric_code is not null
|
||||||
|
and nation_ref.numeric_code = card.nation_numeric_code
|
||||||
|
and (
|
||||||
|
trim(card.nation) ~ '^[0-9]+$'
|
||||||
|
or substring(card.nation from '^[Uu]nknown[[:space:]]+([0-9]+)$') is not null
|
||||||
|
);
|
||||||
|
|
||||||
|
update eventhub.vehicle_registration registration
|
||||||
|
set nation_numeric_code = nation_ref.numeric_code
|
||||||
|
from eventhub.nation nation_ref
|
||||||
|
where registration.nation_numeric_code is null
|
||||||
|
and upper(registration.nation) = upper(nation_ref.alpha_code);
|
||||||
|
|
||||||
|
update eventhub.vehicle_registration registration
|
||||||
|
set nation_numeric_code = cast(registration.nation as integer)
|
||||||
|
where registration.nation_numeric_code is null
|
||||||
|
and trim(registration.nation) ~ '^[0-9]+$';
|
||||||
|
|
||||||
|
update eventhub.vehicle_registration registration
|
||||||
|
set nation_numeric_code = cast(substring(registration.nation from '^[Uu]nknown[[:space:]]+([0-9]+)$') as integer)
|
||||||
|
where registration.nation_numeric_code is null
|
||||||
|
and substring(registration.nation from '^[Uu]nknown[[:space:]]+([0-9]+)$') is not null;
|
||||||
|
|
||||||
|
update eventhub.vehicle_registration registration
|
||||||
|
set nation = coalesce(nation_ref.alpha_code, 'Unknown ' || registration.nation_numeric_code::text)
|
||||||
|
from eventhub.nation nation_ref
|
||||||
|
where registration.nation_numeric_code is not null
|
||||||
|
and nation_ref.numeric_code = registration.nation_numeric_code
|
||||||
|
and (
|
||||||
|
trim(registration.nation) ~ '^[0-9]+$'
|
||||||
|
or substring(registration.nation from '^[Uu]nknown[[:space:]]+([0-9]+)$') is not null
|
||||||
|
);
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
ID;Name;AlphaCode;NumericCode;DefaultLanguageCode;ID_Certificate;ID_FileLog
|
||||||
|
0;Unknown 0;0;0;NULL;NULL;NULL
|
||||||
|
1;Austria;A;1;de-AT;NULL;NULL
|
||||||
|
2;Albania;AL;2;sq-AL;NULL;NULL
|
||||||
|
3;Andorra;AND;3;ca;NULL;NULL
|
||||||
|
4;Armenia;ARM;4;hy-AM;NULL;NULL
|
||||||
|
5;Azerbaijan;AZ;5;az;NULL;NULL
|
||||||
|
6;Belgium;B;6;NULL;NULL;NULL
|
||||||
|
7;Bulgaria;BG;7;bg-BG;NULL;NULL
|
||||||
|
8;Bosnia Herzegovina;BIH;8;NULL;NULL;NULL
|
||||||
|
9;Belarus;BY;9;be-BY;NULL;NULL
|
||||||
|
10;Switzerland;CH;10;de-CH;NULL;NULL
|
||||||
|
11;Cyprus;CY;11;NULL;NULL;NULL
|
||||||
|
12;Czech Republic;CZ;12;cs-CZ;NULL;NULL
|
||||||
|
13;Germany;D;13;de-DE;NULL;NULL
|
||||||
|
14;Denmark;DK;14;da-DK;NULL;NULL
|
||||||
|
15;Spain;E;15;es-ES;NULL;NULL
|
||||||
|
16;Estonia;EST;16;et-EE;NULL;NULL
|
||||||
|
17;France;F;17;fr-FR;NULL;NULL
|
||||||
|
18;Finland;FIN;18;fi-FI;NULL;NULL
|
||||||
|
19;Liechtenstein;FL;19;de-LI;NULL;NULL
|
||||||
|
20;Faroe Islands;FR;20;fo-FO;NULL;NULL
|
||||||
|
21;United Kingdom;UK;21;en-GB;NULL;NULL
|
||||||
|
22;Georgia;GE;22;ka-GE;NULL;NULL
|
||||||
|
23;Greece;GR;23;el-GR;NULL;NULL
|
||||||
|
24;Hungary;H;24;hu-HU;NULL;NULL
|
||||||
|
25;Croatia;HR;25;hr-HR;NULL;NULL
|
||||||
|
26;Italy;I;26;it-IT;NULL;NULL
|
||||||
|
27;Ireland;IRL;27;en-IE;NULL;NULL
|
||||||
|
28;Iceland;IS;28;is-IS;NULL;NULL
|
||||||
|
29;Kazakhstan;KZ;29;kk-KZ;NULL;NULL
|
||||||
|
30;Luxembourg;L;30;de-LU;NULL;NULL
|
||||||
|
31;Lithuania;LT;31;lt-LT;NULL;NULL
|
||||||
|
32;Latvia;LV;32;lv-LV;NULL;NULL
|
||||||
|
33;Malta;M;33;NULL;NULL;NULL
|
||||||
|
34;Monaco;MC;34;fr-MC;NULL;NULL
|
||||||
|
35;Moldova;MD;35;ro;NULL;NULL
|
||||||
|
36;North Macedonia;MK;36;mk-MK;NULL;NULL
|
||||||
|
37;Norway;N;37;no;NULL;NULL
|
||||||
|
38;Netherlands;NL;38;nl-NL;NULL;NULL
|
||||||
|
39;Portugal;P;39;pt-PT;NULL;NULL
|
||||||
|
40;Poland;PL;40;pl-PL;NULL;NULL
|
||||||
|
41;Romania;RO;41;ro-RO;NULL;NULL
|
||||||
|
42;San Marino;RSM;42;it-IT;NULL;NULL
|
||||||
|
43;Russia;RUS;43;ru-RU;NULL;NULL
|
||||||
|
44;Sweden;S;44;sv-SE;NULL;NULL
|
||||||
|
45;Slovakia;SK;45;sk-SK;NULL;NULL
|
||||||
|
46;Slovenia;SLO;46;sl-SI;NULL;NULL
|
||||||
|
47;Turkmenistan;TM;47;NULL;NULL;NULL
|
||||||
|
48;Turkey;TR;48;tr-TR;NULL;NULL
|
||||||
|
49;Ukraine;UA;49;uk-UA;NULL;NULL
|
||||||
|
50;Vatican City;V;50;it-IT;NULL;NULL
|
||||||
|
51;Yugoslavia;YU;51;NULL;NULL;NULL
|
||||||
|
52;Montenegro;MNE;52;NULL;NULL;763087
|
||||||
|
53;Serbia;SRB;53;NULL;NULL;272576
|
||||||
|
54;Uzbekistan;UZ;54;NULL;NULL;308001
|
||||||
|
55;Tajikistan;TJ;55;NULL;NULL;NULL
|
||||||
|
253;European Community;EC;253;NULL;NULL;NULL
|
||||||
|
254;Rest of Europe;EUR;254;NULL;NULL;NULL
|
||||||
|
255;Rest of the world;WLD;255;NULL;NULL;NULL
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
package at.procon.eventhub.reference;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
import at.procon.eventhub.dto.DriverCardRefDto;
|
||||||
|
import at.procon.eventhub.dto.VehicleRegistrationRefDto;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
class TachographNationRegistryTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void resolvesKnownNumericNationCodeToAlphaAndNumeric() {
|
||||||
|
DriverCardRefDto driverCard = new DriverCardRefDto("13", "CARD-1");
|
||||||
|
VehicleRegistrationRefDto registration = new VehicleRegistrationRefDto("13", "W-1");
|
||||||
|
|
||||||
|
assertThat(driverCard.nation()).isEqualTo("D");
|
||||||
|
assertThat(driverCard.nationNumericCode()).isEqualTo(13);
|
||||||
|
assertThat(driverCard.stableKey()).isEqualTo("13:CARD-1");
|
||||||
|
|
||||||
|
assertThat(registration.nation()).isEqualTo("D");
|
||||||
|
assertThat(registration.nationNumericCode()).isEqualTo(13);
|
||||||
|
assertThat(registration.stableKey()).isEqualTo("13:W-1");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void resolvesKnownAlphaNationCodeToNumeric() {
|
||||||
|
DriverCardRefDto driverCard = new DriverCardRefDto("A", "CARD-1");
|
||||||
|
|
||||||
|
assertThat(driverCard.nation()).isEqualTo("A");
|
||||||
|
assertThat(driverCard.nationNumericCode()).isEqualTo(1);
|
||||||
|
assertThat(driverCard.stableKey()).isEqualTo("1:CARD-1");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void preservesUnknownNumericNationCodeAsSyntheticLabel() {
|
||||||
|
DriverCardRefDto driverCard = new DriverCardRefDto("209", "CARD-1");
|
||||||
|
|
||||||
|
assertThat(driverCard.nation()).isEqualTo("Unknown 209");
|
||||||
|
assertThat(driverCard.nationNumericCode()).isEqualTo(209);
|
||||||
|
assertThat(driverCard.stableKey()).isEqualTo("209:CARD-1");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void keepsSyntheticTelematicsNationOutsideTachographMapping() {
|
||||||
|
VehicleRegistrationRefDto registration = new VehicleRegistrationRefDto("YELLOWFOX", "W-1");
|
||||||
|
|
||||||
|
assertThat(registration.nation()).isEqualTo("YELLOWFOX");
|
||||||
|
assertThat(registration.nationNumericCode()).isNull();
|
||||||
|
assertThat(registration.stableKey()).isEqualTo("YELLOWFOX:W-1");
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue