fix: trip builder handles NULL-GPS speed-only rows (BUG-16 follow-up)

Trips starting/ending on speed-only rows violated the trips.*GPSX NOT NULL
constraint. Use the first/last GPS-bearing row for start/end coordinates, and
skip a trip that never got any GPS fix (no location to record).
This commit is contained in:
Mathieu Moran
2026-08-13 15:52:07 -04:00
parent e5ac14e38b
commit f5f20c315b
2 changed files with 36 additions and 9 deletions
+20 -5
View File
@@ -115,7 +115,7 @@ class TripBuilderTest(unittest.TestCase):
self.assertEqual(trips[0]["start_tracking_id"], 1)
self.assertEqual(trips[0]["end_tracking_id"], 5)
def test_speed_only_rows_without_gps_build_trip(self):
def test_speed_only_rows_without_any_gps_are_skipped(self):
started = datetime(2026, 1, 1, 8)
rows = [
(index + 1, started + timedelta(seconds=index * 5), None, None, 30)
@@ -124,12 +124,27 @@ class TripBuilderTest(unittest.TestCase):
trips = app_trip.build_trip_summaries(rows)
# No GPS fix at all -> no location to record -> no trip (the speed-only
# rows remain in the DB but can't form a geolocated trip).
self.assertEqual(len(trips), 0)
def test_speed_only_start_uses_first_gps_fix_for_start_coords(self):
started = datetime(2026, 1, 1, 8)
rows = [
(1, started, None, None, 30),
(2, started + timedelta(seconds=5), None, None, 30),
(3, started + timedelta(seconds=10), 45.5000, -73.5000, 30),
(4, started + timedelta(seconds=15), 45.5001, -73.5000, 30),
(5, started + timedelta(seconds=20), 45.5002, -73.5000, 30),
]
trips = app_trip.build_trip_summaries(rows)
self.assertEqual(len(trips), 1)
self.assertEqual(trips[0]["start_tracking_id"], 1)
self.assertEqual(trips[0]["end_tracking_id"], 4)
self.assertEqual(trips[0]["distance_km"], 0)
self.assertEqual(trips[0]["max_speed_kmh"], 30)
self.assertEqual(trips[0]["point_count"], 4)
self.assertEqual(trips[0]["end_tracking_id"], 5)
self.assertEqual(trips[0]["start_gpsx"], 45.5)
self.assertEqual(trips[0]["start_gpsy"], -73.5)
def test_clock_rollback_does_not_merge_motion_episodes(self):
first = self.rows_for_route(