- Cleaned 137+ fake engine-displacement models from supplier imports (v3/v4 scripts: Chevrolet, Ford, Chrysler, Dodge, Jeep, Nissan, etc.) - Removed 1,251+ corrupted models (INT. prefixes, year-suffix, torque specs, empty names, trailing-year variants) - Migrated supplier tables to master DB (supplier_catalog, supplier_catalog_compat, supplier_catalog_interchange) - Fixed _get_mye_ids_with_parts() to query supplier_catalog_compat from master DB so supplier-only vehicles appear for all tenants - Added fuzzy model matcher with parenthesis stripping, noise suffix removal, compact matching, prefix/substring fallback, model aliases, and ±3 year proximity - Matched compat rows: KEEP GREEN +14,152, KNADIAN +3,021, VAZLO +127,500, LUK +477, RAYBESTOS +1,743 - Added KNADIAN catalog importer with year-range expansion and future-year filtering - Added VAZLO catalog importer with position parsing and SKU-in-model cleanup - Added Keep Green, LUK, Yokomitsu, Raybestos catalog importers - Cache clearing after cleanups (_classify_cache_*, nexus:mye_ids:*, nexus:brand_mye_counts:*) Final match rates: - KEEP GREEN: 90.3% - VAZLO: 93.6% - YOKOMITSU: 100.0% - KNADIAN: 57.4% - LUK: 51.0% - RAYBESTOS: 55.9%
119 lines
3.6 KiB
Python
Executable File
119 lines
3.6 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
# /home/Autopartes/pos/migrations/runner.py
|
|
"""Apply schema migrations to all tenant databases."""
|
|
|
|
import os
|
|
import sys
|
|
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|
|
|
from tenant_db import get_master_conn, get_tenant_conn_by_dbname
|
|
|
|
MIGRATIONS_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
|
|
# Migration registry: version -> filename
|
|
MIGRATIONS = {
|
|
'v1.0': 'v1.0_initial.sql',
|
|
'v1.1': 'v1.1_pos_tables.sql',
|
|
'v1.3': 'v1.3_fleet.sql',
|
|
'v1.4': 'v1.4_whatsapp.sql',
|
|
'v1.5': 'v1.5_returns.sql',
|
|
'v1.7': 'v1.7_plates.sql',
|
|
'v1.8': 'v1.8_performance_indexes.sql',
|
|
'v1.9': 'v1.9_redis_cache.sql',
|
|
'v2.0': 'v2.0_multi_currency.sql',
|
|
'v2.1': 'v2.1_suppliers.sql',
|
|
'v2.2': 'v2.2_alerts_warranty.sql',
|
|
'v2.3': 'v2.3_metabase.sql',
|
|
'v2.4': 'v2.4_crm_enhanced.sql',
|
|
'v2.5': 'v2.5_service_orders.sql',
|
|
'v2.6': 'v2.6_bnpl_erp.sql',
|
|
'v2.7': 'v2.7_notifications.sql',
|
|
'v2.8': 'v2.8_savings.sql',
|
|
'v2.9': 'v2.9_logistics.sql',
|
|
'v3.0': 'v3.0_public_api.sql',
|
|
'v3.1': 'v3.1_inventory_vehicle_compat.sql',
|
|
'v3.2': 'v3.2_db_performance.sql',
|
|
'v3.8': 'v3.8_supplier_catalog.sql',
|
|
}
|
|
|
|
|
|
def get_all_tenants():
|
|
"""Get all tenants with their current schema version."""
|
|
conn = get_master_conn()
|
|
cur = conn.cursor()
|
|
cur.execute("""
|
|
SELECT t.id, t.db_name, t.name, COALESCE(v.version, 'v0.0') as version
|
|
FROM tenants t
|
|
LEFT JOIN tenant_schema_version v ON t.id = v.tenant_id
|
|
WHERE t.is_active = true
|
|
""")
|
|
tenants = cur.fetchall()
|
|
cur.close()
|
|
conn.close()
|
|
return tenants
|
|
|
|
|
|
def apply_migration(db_name, version):
|
|
"""Apply a single migration to a tenant DB."""
|
|
filename = MIGRATIONS[version]
|
|
filepath = os.path.join(MIGRATIONS_DIR, filename)
|
|
|
|
if not os.path.exists(filepath):
|
|
print(f" ERROR: Migration file not found: {filepath}")
|
|
return False
|
|
|
|
conn = get_tenant_conn_by_dbname(db_name)
|
|
cur = conn.cursor()
|
|
try:
|
|
with open(filepath) as f:
|
|
cur.execute(f.read())
|
|
conn.commit()
|
|
return True
|
|
except Exception as e:
|
|
conn.rollback()
|
|
print(f" ERROR: {e}")
|
|
return False
|
|
finally:
|
|
cur.close()
|
|
conn.close()
|
|
|
|
|
|
def run_migrations():
|
|
"""Apply pending migrations to all tenants."""
|
|
tenants = get_all_tenants()
|
|
sorted_versions = sorted(MIGRATIONS.keys())
|
|
|
|
print(f"Found {len(tenants)} active tenants")
|
|
print(f"Available migrations: {sorted_versions}")
|
|
|
|
for tenant_id, db_name, name, current_version in tenants:
|
|
print(f"\n[{name}] (db={db_name}, current={current_version})")
|
|
|
|
for version in sorted_versions:
|
|
if version <= current_version:
|
|
continue
|
|
|
|
print(f" Applying {version}...", end=' ')
|
|
if apply_migration(db_name, version):
|
|
# Update version in master
|
|
master_conn = get_master_conn()
|
|
master_cur = master_conn.cursor()
|
|
master_cur.execute("""
|
|
INSERT INTO tenant_schema_version (tenant_id, version)
|
|
VALUES (%s, %s)
|
|
ON CONFLICT (tenant_id) DO UPDATE SET version = %s, updated_at = NOW()
|
|
""", (tenant_id, version, version))
|
|
master_conn.commit()
|
|
master_cur.close()
|
|
master_conn.close()
|
|
print("OK")
|
|
else:
|
|
print("FAILED — stopping migrations for this tenant")
|
|
break
|
|
|
|
print("\nDone.")
|
|
|
|
|
|
if __name__ == '__main__':
|
|
run_migrations()
|