refactor: store jt808 mileage as metric diff

This commit is contained in:
lingniu
2026-07-01 02:32:46 +08:00
parent a5f5cc94ee
commit b94780b48c
12 changed files with 73 additions and 40 deletions

View File

@@ -1,6 +1,16 @@
package com.lingniu.ingest.vehiclestat;
public enum DailyMileageStrategy {
CURRENT_LAST_MINUS_PREVIOUS_LAST,
DAY_MAX_MINUS_DAY_MIN
JT808_TOTAL_MILEAGE_DIFF;
public static DailyMileageStrategy fromStorage(String value) {
if (value == null || value.isBlank()) {
return JT808_TOTAL_MILEAGE_DIFF;
}
String normalized = value.trim();
if ("CURRENT_LAST_MINUS_PREVIOUS_LAST".equals(normalized)) {
return JT808_TOTAL_MILEAGE_DIFF;
}
return DailyMileageStrategy.valueOf(normalized);
}
}

View File

@@ -57,7 +57,7 @@ public final class JdbcVehicleStatMetricRepository implements VehicleStatReposit
rs.getBigDecimal("metric_value") == null
? OptionalDouble.empty()
: OptionalDouble.of(rs.getBigDecimal("metric_value").doubleValue()),
DailyMileageStrategy.valueOf(rs.getString("calculation_method"))),
DailyMileageStrategy.fromStorage(rs.getString("calculation_method"))),
normalizedVin, Date.valueOf(statDate), DAILY_MILEAGE_KEY);
return rows.stream().findFirst();
}

View File

@@ -19,7 +19,7 @@ public record VehicleDailyStatResult(String vin,
dailyMileageKm = OptionalDouble.empty();
}
if (dailyMileageStrategy == null) {
dailyMileageStrategy = DailyMileageStrategy.CURRENT_LAST_MINUS_PREVIOUS_LAST;
dailyMileageStrategy = DailyMileageStrategy.JT808_TOTAL_MILEAGE_DIFF;
}
}
}

View File

@@ -90,7 +90,7 @@ public final class Jt808DailyMileageState {
statVehicleId(),
statDate,
dailyMileage,
DailyMileageStrategy.CURRENT_LAST_MINUS_PREVIOUS_LAST));
DailyMileageStrategy.JT808_TOTAL_MILEAGE_DIFF));
}
private void updateOdometer(Jt808LocationPoint point) {

View File

@@ -23,12 +23,12 @@ class JdbcVehicleStatMetricRepositoryTest {
"VIN001",
LocalDate.of(2026, 6, 30),
OptionalDouble.of(12.345),
DailyMileageStrategy.CURRENT_LAST_MINUS_PREVIOUS_LAST));
DailyMileageStrategy.JT808_TOTAL_MILEAGE_DIFF));
repository.saveDailyStat(new VehicleDailyStatResult(
"VIN001",
LocalDate.of(2026, 6, 30),
OptionalDouble.of(15.5),
DailyMileageStrategy.CURRENT_LAST_MINUS_PREVIOUS_LAST));
DailyMileageStrategy.JT808_TOTAL_MILEAGE_DIFF));
assertThat(repository.findDailyStat("VIN001", LocalDate.of(2026, 6, 30)))
.isPresent()
@@ -40,5 +40,33 @@ class JdbcVehicleStatMetricRepositoryTest {
assertThat(jdbcTemplate.queryForObject(
"SELECT metric_key FROM vehicle_stat_metric WHERE vin = 'VIN001'",
String.class)).isEqualTo("daily_mileage_km");
assertThat(jdbcTemplate.queryForObject(
"SELECT calculation_method FROM vehicle_stat_metric WHERE vin = 'VIN001'",
String.class)).isEqualTo("JT808_TOTAL_MILEAGE_DIFF");
assertThat(jdbcTemplate.queryForObject("""
SELECT COUNT(*)
FROM information_schema.tables
WHERE table_name = 'vehicle_daily_stat'
""", Integer.class)).isZero();
}
@Test
void readsLegacyCalculationMethodAsTotalMileageDifference() {
JdbcTemplate jdbcTemplate = new JdbcTemplate(new DriverManagerDataSource(
"jdbc:h2:mem:vehicle_stat_metric_legacy;MODE=MySQL;DATABASE_TO_LOWER=TRUE;DB_CLOSE_DELAY=-1",
"sa",
""));
JdbcVehicleStatMetricRepository repository = new JdbcVehicleStatMetricRepository(jdbcTemplate);
jdbcTemplate.update("""
INSERT INTO vehicle_stat_metric
(vin, stat_date, metric_key, metric_value, metric_unit, calculation_method)
VALUES ('VIN001', DATE '2026-06-30', 'daily_mileage_km', 8.5, 'km', 'CURRENT_LAST_MINUS_PREVIOUS_LAST')
""");
assertThat(repository.findDailyStat("VIN001", LocalDate.of(2026, 6, 30)))
.isPresent()
.get()
.extracting(VehicleDailyStatResult::dailyMileageStrategy)
.isEqualTo(DailyMileageStrategy.JT808_TOTAL_MILEAGE_DIFF);
}
}

View File

@@ -21,14 +21,15 @@ class VehicleStatControllerTest {
"VIN001",
LocalDate.parse("2026-06-22"),
OptionalDouble.of(35.5),
DailyMileageStrategy.CURRENT_LAST_MINUS_PREVIOUS_LAST));
DailyMileageStrategy.JT808_TOTAL_MILEAGE_DIFF));
MockMvc mvc = standaloneSetup(new VehicleStatController(repository)).build();
mvc.perform(get("/api/vehicle-stat/VIN001/daily").param("date", "2026-06-22"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.vin").value("VIN001"))
.andExpect(jsonPath("$.statDate").value("2026-06-22"))
.andExpect(jsonPath("$.dailyMileageKm").value(35.5));
.andExpect(jsonPath("$.dailyMileageKm").value(35.5))
.andExpect(jsonPath("$.dailyMileageStrategy").value("JT808_TOTAL_MILEAGE_DIFF"));
}
private static final class InMemoryVehicleStatRepository implements VehicleStatRepository {

View File

@@ -36,7 +36,7 @@ class Jt808MileageStreamProcessorTest {
assertThat(latest.vin()).isEqualTo("VIN001");
assertThat(latest.statDate()).isEqualTo(LocalDate.of(2026, 6, 30));
assertThat(latest.dailyMileageKm()).hasValue(1.0);
assertThat(latest.dailyMileageStrategy()).isEqualTo(DailyMileageStrategy.CURRENT_LAST_MINUS_PREVIOUS_LAST);
assertThat(latest.dailyMileageStrategy()).isEqualTo(DailyMileageStrategy.JT808_TOTAL_MILEAGE_DIFF);
}
@Test