#!/usr/bin/env python3 """Fleet Data Discovery Script Queries the database to audit fleet vehicle data: - Total vehicles in vehicle.assets - Total asset assignments in fleet.asset_assignments - Organization IDs with existing assignments - Vehicles with current_organization_id set """ import asyncio import sys from sqlalchemy import select, func from app.db.session import AsyncSessionLocal from app.models.vehicle.asset import Asset, AssetAssignment async def main(): print("=" * 60) print(" FLEET DATA DISCOVERY AUDIT") print("=" * 60) async with AsyncSessionLocal() as session: # 1. Total vehicles in vehicle.assets result = await session.execute(select(func.count(Asset.id))) total_vehicles = result.scalar() print(f"\n Total vehicles (vehicle.assets): {total_vehicles}") # 2. Vehicles with current_organization_id set result = await session.execute( select(func.count(Asset.id)).where(Asset.current_organization_id.isnot(None)) ) vehicles_with_org = result.scalar() print(f" Vehicles with current_organization_id: {vehicles_with_org}") # 3. Total asset assignments in fleet.asset_assignments result = await session.execute(select(func.count(AssetAssignment.id))) total_assignments = result.scalar() print(f" Total asset assignments (fleet): {total_assignments}") # 4. Distinct organization_ids in asset_assignments result = await session.execute( select(AssetAssignment.organization_id).distinct() ) org_ids = [row[0] for row in result.fetchall()] print(f" Organizations with assignments: {len(org_ids)}") if org_ids: print(f" Organization IDs: {org_ids}") # 5. Distinct current_organization_id in assets result = await session.execute( select(Asset.current_organization_id).distinct().where( Asset.current_organization_id.isnot(None) ) ) asset_org_ids = [row[0] for row in result.fetchall()] print(f" Organizations with vehicles (direct): {len(asset_org_ids)}") if asset_org_ids: print(f" Organization IDs: {asset_org_ids}") # 6. Sample vehicles with current_organization_id result = await session.execute( select(Asset.id, Asset.license_plate, Asset.vin, Asset.current_organization_id) .where(Asset.current_organization_id.isnot(None)) .limit(10) ) samples = result.fetchall() if samples: print(f"\n Sample vehicles (up to 10):") print(f" {'ID':<38} {'Plate':<12} {'VIN':<18} {'OrgID':<6}") print(f" {'-'*38} {'-'*12} {'-'*18} {'-'*6}") for s in samples: plate = s.license_plate or "N/A" vin = (s.vin or "N/A")[:17] print(f" {str(s.id):<38} {plate:<12} {vin:<18} {str(s.current_organization_id or ''):<6}") else: print("\n No vehicles with current_organization_id found.") # 7. Sample asset_assignments result = await session.execute( select(AssetAssignment.id, AssetAssignment.asset_id, AssetAssignment.organization_id, AssetAssignment.status) .limit(10) ) assign_samples = result.fetchall() if assign_samples: print(f"\n Sample asset_assignments (up to 10):") print(f" {'ID':<38} {'AssetID':<38} {'OrgID':<6} {'Status':<10}") print(f" {'-'*38} {'-'*38} {'-'*6} {'-'*10}") for a in assign_samples: print(f" {str(a.id):<38} {str(a.asset_id):<38} {str(a.organization_id):<6} {a.status:<10}") print("\n" + "=" * 60) print(" AUDIT COMPLETE") print("=" * 60) if __name__ == "__main__": asyncio.run(main())