diff --git a/scripts/restore_gps.py b/scripts/restore_gps.py new file mode 100644 index 0000000..72f79d2 --- /dev/null +++ b/scripts/restore_gps.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python3 +"""Restore GPS data from pre-MSFS backup by matching serial numbers.""" + +import sqlite3 +import sys + +DB_PATH = "/home/oplabs/projects/canteen-asset-tracker/assets.db" +OLD_DB_PATH = "/home/oplabs/projects/canteen-asset-tracker/assets.db.20260528_214316.pre-msfs-import" + +def main(): + # Open old DB (read-only) + old = sqlite3.connect(f"file:{OLD_DB_PATH}?mode=ro", uri=True) + old.row_factory = sqlite3.Row + + # Build mapping: serial_number -> (lat, lon) from old DB + old_gps = {} + for r in old.execute( + "SELECT serial_number, latitude, longitude FROM assets " + "WHERE serial_number IS NOT NULL AND serial_number != '' " + "AND latitude IS NOT NULL AND latitude != 0 AND longitude IS NOT NULL" + ).fetchall(): + old_gps[r["serial_number"]] = (r["latitude"], r["longitude"]) + + old.close() + print(f"Old DB: {len(old_gps)} GPS entries indexed by serial_number") + + # Open current DB and update + cur = sqlite3.connect(DB_PATH) + updated = 0 + skipped_existing = 0 + skipped_no_sn = 0 + skipped_no_match = 0 + + for r in cur.execute( + "SELECT rowid, machine_id, serial_number, latitude, longitude FROM assets" + ).fetchall(): + rowid, machine_id, serial_number, lat, lon = r + + # Skip if already has GPS + if lat and lon and lat != 0 and lon != 0: + skipped_existing += 1 + continue + + if not serial_number: + skipped_no_sn += 1 + continue + + if serial_number in old_gps: + new_lat, new_lon = old_gps[serial_number] + cur.execute( + "UPDATE assets SET latitude = ?, longitude = ? WHERE rowid = ?", + (new_lat, new_lon, rowid) + ) + updated += 1 + else: + skipped_no_match += 1 + + cur.commit() + + # Verify + gps_count = cur.execute( + "SELECT COUNT(*) FROM assets " + "WHERE latitude IS NOT NULL AND longitude IS NOT NULL AND latitude != 0 AND longitude != 0" + ).fetchone()[0] + + total = cur.execute("SELECT COUNT(*) FROM assets").fetchone()[0] + + print(f"\nResults:") + print(f" GPS restored: {updated}") + print(f" Already had GPS: {skipped_existing}") + print(f" No serial number: {skipped_no_sn}") + print(f" No match in old DB: {skipped_no_match}") + print(f" Total with GPS now: {gps_count} / {total}") + + cur.close() + +if __name__ == "__main__": + main() diff --git a/scripts/restore_gps_acct.py b/scripts/restore_gps_acct.py new file mode 100644 index 0000000..f4aa2b8 --- /dev/null +++ b/scripts/restore_gps_acct.py @@ -0,0 +1,97 @@ +#!/usr/bin/env python3 +"""Restore GPS from merged-assets.json account-level data. + +Priority: canteen_connect_guid match > connect_id match > already restored via serial.""" + +import json +import sqlite3 +import sys + +DB_PATH = "/home/oplabs/projects/canteen-asset-tracker/assets.db" +MERGED_PATH = "/home/oplabs/projects/ms-field-service-extraction/web/static/data/merged-assets.json" + +def build_lookups(merged_path): + """Build GPS lookups from merged-assets.json account data.""" + with open(merged_path) as f: + data = json.load(f) + + by_connect_guid = {} # msfs_canteen_connect_guid → (lat, lon) + by_connect_id = {} # msfs_connect_id → (lat, lon) + + for a in data['assets']: + acct = a.get('account') or {} + lat = acct.get('latitude') + lon = acct.get('longitude') + if not (lat and lon and float(lat) != 0 and float(lon) != 0): + continue + + lat, lon = float(lat), float(lon) + + guid = a.get('msfs_canteen_connect_guid') + if guid: + by_connect_guid[guid.upper()] = (lat, lon) + + cid = a.get('msfs_connect_id') + if cid: + by_connect_id[cid] = (lat, lon) + + print(f"Lookups: {len(by_connect_guid)} connect_guid, {len(by_connect_id)} connect_id") + return by_connect_guid, by_connect_id + +def main(): + by_connect_guid, by_connect_id = build_lookups(MERGED_PATH) + + cur = sqlite3.connect(DB_PATH) + + total = cur.execute("SELECT COUNT(*) FROM assets").fetchone()[0] + before = cur.execute( + "SELECT COUNT(*) FROM assets WHERE latitude IS NOT NULL AND longitude IS NOT NULL AND latitude != 0 AND longitude != 0" + ).fetchone()[0] + print(f"Before: {before} / {total} with GPS") + + via_guid = 0 + via_cid = 0 + skipped = 0 + + for r in cur.execute( + "SELECT rowid, canteen_connect_guid, connect_id, latitude, longitude FROM assets" + ).fetchall(): + rowid, guid, cid, lat, lon = r + + # Skip if already has GPS + if lat and lon and lat != 0 and lon != 0: + skipped += 1 + continue + + # Try connect_guid first (most precise) + if guid: + gps = by_connect_guid.get(guid.upper()) + if gps: + cur.execute("UPDATE assets SET latitude = ?, longitude = ? WHERE rowid = ?", (gps[0], gps[1], rowid)) + via_guid += 1 + continue + + # Fallback to connect_id + if cid: + gps = by_connect_id.get(cid) + if gps: + cur.execute("UPDATE assets SET latitude = ?, longitude = ? WHERE rowid = ?", (gps[0], gps[1], rowid)) + via_cid += 1 + + cur.commit() + + after = cur.execute( + "SELECT COUNT(*) FROM assets WHERE latitude IS NOT NULL AND longitude IS NOT NULL AND latitude != 0 AND longitude != 0" + ).fetchone()[0] + + print(f"\nResults:") + print(f" Via connect_guid: {via_guid}") + print(f" Via connect_id: {via_cid}") + print(f" Already had: {skipped}") + print(f" After: {after} / {total} with GPS") + print(f" Still missing: {total - after}") + + cur.close() + +if __name__ == "__main__": + main()