-- migrate:up -- -- One-shot plate consolidation: -- 1. extract plate from each device's device_name (post " - ", strip _cam) -- 2. for each plate appearing on >1 device (tracker+camera pair), pick the -- lowest existing vehicle_id as canonical -- 3. remap state.position_history, state.live_positions, domain.devices -- to the canonical vehicle_id -- 4. delete orphaned vehicle rows -- 5. update canonical vehicles' plate to the extracted plate -- -- After this runs, domain.vehicles holds one row per physical plate. The -- PRD F1.6 dedup rule in serve.fn_live_view picks tracker-first when both -- a tracker and camera report for the same vehicle. -- -- Idempotent: re-running the migration only updates plates that have moved on. DO $migration$ BEGIN CREATE TEMP TABLE _plate_map ON COMMIT DROP AS SELECT d.imei, d.vehicle_id AS current_vehicle_id, regexp_replace( (regexp_match(lp.device_name, '^.* - (.+)$'))[1], '_(cam|CAM)$', '' ) AS new_plate FROM domain.devices d JOIN state.live_positions lp ON lp.imei = d.imei WHERE lp.device_name LIKE '% - %'; DELETE FROM _plate_map WHERE new_plate IS NULL OR new_plate = '' OR new_plate !~ '[A-Z]' OR new_plate !~ '[0-9]'; CREATE TEMP TABLE _canonical ON COMMIT DROP AS SELECT new_plate, min(current_vehicle_id) AS canonical_vehicle_id FROM _plate_map GROUP BY new_plate; -- Drop UNIQUE so the multi-row plate assignment doesn't transiently violate ALTER TABLE domain.vehicles DROP CONSTRAINT IF EXISTS vehicles_plate_key; UPDATE state.position_history ph SET vehicle_id = c.canonical_vehicle_id FROM _plate_map pm JOIN _canonical c ON c.new_plate = pm.new_plate WHERE ph.imei = pm.imei AND ph.vehicle_id != c.canonical_vehicle_id; UPDATE state.live_positions lp SET vehicle_id = c.canonical_vehicle_id FROM _plate_map pm JOIN _canonical c ON c.new_plate = pm.new_plate WHERE lp.imei = pm.imei AND lp.vehicle_id != c.canonical_vehicle_id; UPDATE domain.devices d SET vehicle_id = c.canonical_vehicle_id FROM _plate_map pm JOIN _canonical c ON c.new_plate = pm.new_plate WHERE d.imei = pm.imei AND d.vehicle_id != c.canonical_vehicle_id; DELETE FROM domain.vehicles v WHERE NOT EXISTS (SELECT 1 FROM domain.devices d WHERE d.vehicle_id = v.vehicle_id) AND NOT EXISTS (SELECT 1 FROM state.live_positions lp WHERE lp.vehicle_id = v.vehicle_id) AND NOT EXISTS (SELECT 1 FROM state.position_history ph WHERE ph.vehicle_id = v.vehicle_id); UPDATE domain.vehicles v SET plate = c.new_plate, updated_at = now() FROM _canonical c WHERE v.vehicle_id = c.canonical_vehicle_id; ALTER TABLE domain.vehicles ADD CONSTRAINT vehicles_plate_key UNIQUE (plate); END $migration$; -- migrate:down -- No-op: plate consolidation is a one-way operation.