#!/usr/bin/env python3 """ Fix test user garage data and split vehicles between private and org branches. This script: 1. Fetches User 28 (tester_pro@profibot.hu) 2. Creates a Private Organization for User 28 (if missing) 3. Creates a Private Branch (Garage) named "Teszt Pro - Saját Garázs" 4. Fetches the 2 vehicles owned by User 28 (MNO-345 and PQR-678) 5. Splits them: Assigns MNO-345 to the newly created Private Branch 6. Keeps PQR-678 in the Org 15 Branch (b2060e1d...) 7. Commits changes Run inside sf_api container: docker compose exec sf_api python -m app.scripts.fix_test_user_garage """ import asyncio import sys import uuid from sqlalchemy import select, update from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.orm import selectinload # Add the backend directory to the path sys.path.insert(0, '/app') from app.db.session import AsyncSessionLocal from app.models.identity import User from app.models.marketplace.organization import Organization, OrganizationMember, Branch, OrgType, OrgUserRole from app.models.vehicle.asset import Asset async def main(): """Main execution logic.""" print("=" * 60) print("FIX TEST USER GARAGE DATA SCRIPT") print("=" * 60) async with AsyncSessionLocal() as db: # 1. Fetch User 28 (tester_pro@profibot.hu) print("\n1. FETCHING TEST USER...") stmt = select(User).where(User.email == "tester_pro@profibot.hu") result = await db.execute(stmt) test_user = result.scalar_one_or_none() if not test_user: print("❌ ERROR: Test user (tester_pro@profibot.hu) not found!") return print(f" ✅ Test user found: ID={test_user.id}, Email={test_user.email}") # 2. Check if user already has a private organization print("\n2. CHECKING FOR PRIVATE ORGANIZATION...") org_stmt = ( select(Organization) .join(OrganizationMember) .where(OrganizationMember.user_id == test_user.id) .where(Organization.org_type == OrgType.individual) .where(Organization.is_deleted == False) ) result = await db.execute(org_stmt) private_org = result.scalar_one_or_none() if not private_org: print(" ⚠️ No private organization found, creating one...") # Create private organization from datetime import datetime, timezone now = datetime.now(timezone.utc) private_org = Organization( full_name=f"Private Organization for {test_user.email}", name=f"Private_{test_user.id}", display_name=f"Teszt Pro - Privát", folder_slug=f"priv_{test_user.id}", org_type=OrgType.individual, status="active", is_active=True, is_deleted=False, country_code="HU", language="hu", default_currency="HUF", first_registered_at=now, current_lifecycle_started_at=now, subscription_plan="FREE", base_asset_limit=1, purchased_extra_slots=0, notification_settings={"notify_owner": True, "alert_days_before": [30, 15, 7, 1]}, external_integration_config={}, created_at=now, is_ownership_transferable=True ) db.add(private_org) await db.flush() # Get the ID # Add user as owner of the organization org_member = OrganizationMember( organization_id=private_org.id, user_id=test_user.id, person_id=test_user.person_id, role=OrgUserRole.OWNER, is_verified=True ) db.add(org_member) await db.commit() print(f" ✅ Created private organization: ID={private_org.id}, Name={private_org.name}") else: print(f" ✅ Private organization already exists: ID={private_org.id}, Name={private_org.name}") # 3. Check/create private branch (garage) print("\n3. CHECKING/CREATING PRIVATE BRANCH (GARAGE)...") branch_stmt = select(Branch).where( Branch.organization_id == private_org.id, Branch.name.ilike("%Teszt Pro - Saját Garázs%"), Branch.is_deleted == False ) result = await db.execute(branch_stmt) private_branch = result.scalar_one_or_none() if not private_branch: private_branch = Branch( id=uuid.uuid4(), organization_id=private_org.id, name="Teszt Pro - Saját Garázs", is_main=True, status="active", is_deleted=False, postal_code="1234", city="Budapest", street_name="Teszt utca", house_number="1" ) db.add(private_branch) await db.commit() print(f" ✅ Created private branch: ID={private_branch.id}, Name={private_branch.name}") else: print(f" ✅ Private branch already exists: ID={private_branch.id}, Name={private_branch.name}") # 4. Fetch the 2 vehicles by license plate (regardless of owner) print("\n4. FETCHING VEHICLES BY LICENSE PLATE...") # Find vehicles by license plate vehicles_stmt = select(Asset).where( Asset.license_plate.in_(["MNO-345", "PQR-678"]) ) result = await db.execute(vehicles_stmt) vehicles = result.scalars().all() print(f" Found {len(vehicles)} vehicles with plates MNO-345 or PQR-678") # 5. Find Org 15 branch (b2060e1d...) print("\n5. FINDING ORG 15 BRANCH...") # First find Org 15 org15_stmt = select(Organization).where( Organization.id == 15, Organization.is_deleted == False ) result = await db.execute(org15_stmt) org15 = result.scalar_one_or_none() if not org15: print("❌ ERROR: Organization 15 not found!") return print(f" ✅ Organization 15 found: ID={org15.id}, Name={org15.name}") # Find a branch in Org 15 org15_branch_stmt = select(Branch).where( Branch.organization_id == 15, Branch.is_deleted == False ).limit(1) result = await db.execute(org15_branch_stmt) org15_branch = result.scalar_one_or_none() if not org15_branch: print("❌ ERROR: No branch found in Organization 15!") return print(f" ✅ Org 15 branch found: ID={org15_branch.id}, Name={org15_branch.name}") # 6. Split vehicles print("\n6. SPLITTING VEHICLES BETWEEN BRANCHES...") updated_count = 0 for vehicle in vehicles: if vehicle.license_plate == "MNO-345": # Assign to private branch vehicle.branch_id = private_branch.id vehicle.current_organization_id = private_org.id print(f" ✅ Assigned MNO-345 to private branch: {private_branch.name}") updated_count += 1 elif vehicle.license_plate == "PQR-678": # Keep in Org 15 branch vehicle.branch_id = org15_branch.id vehicle.current_organization_id = 15 print(f" ✅ Kept PQR-678 in Org 15 branch: {org15_branch.name}") updated_count += 1 if updated_count > 0: await db.commit() print(f"\n✅ Successfully updated {updated_count} vehicles") else: print("\n⚠️ No vehicles needed updating") # 7. Verify the split print("\n7. VERIFICATION...") for plate in ["MNO-345", "PQR-678"]: verify_stmt = select(Asset).where(Asset.license_plate == plate).options(selectinload(Asset.catalog)) result = await db.execute(verify_stmt) vehicle = result.scalar_one_or_none() if vehicle: branch_name = "Unknown" if vehicle.branch_id == private_branch.id: branch_name = "Private Branch" elif vehicle.branch_id == org15_branch.id: branch_name = "Org 15 Branch" print(f" {plate}: Branch ID={vehicle.branch_id} ({branch_name}), Org ID={vehicle.current_organization_id}") else: print(f" {plate}: Not found") print("\n" + "=" * 60) print("SCRIPT COMPLETED SUCCESSFULLY") print("=" * 60) if __name__ == "__main__": asyncio.run(main())