Files
Autoparts-DB/scripts/health_check.py
Nexus Dev 9ff3dc4c8b FASE 4-5-6: Infraestructura, CRM, Service Orders, Notificaciones, Ahorro, Logistica, API Publica
FASE 4:
- Redis cache de stock con fallback graceful
- Multi-moneda (MXN/USD) con contabilidad en MXN
- Proveedores y ordenes de compra completo
- Meilisearch 1.5M+ partes indexadas
- Metabase KPIs con dashboard auto-generado

FASE 5:
- CRM mejorado: activities, tags, loyalty program, analytics
- Imagenes de partes: upload, resize, thumbnails WebP
- Ordenes de servicio Kanban: received->diagnosis->repair->ready->delivered
- Garantias/RMA, alertas de reorden, multi-sucursal
- Stubs BNPL (APLAZO) y ERP Sync (Aspel/Contpaqi)

FASE 6:
- Notificaciones automaticas: push/WhatsApp/email/in-app
- Reportes de ahorro vs retail_price
- Logistica + tracking: DHL, FedEx, Estafeta, 99min, Uber
- API Publica: API keys, rate limiting, catalog search

Migraciones: v1.9-v3.0
Tests: 93/93 pasando
Backup: nexus_backup_20260427_045859.tar.gz
2026-04-27 05:23:30 +00:00

223 lines
6.9 KiB
Python
Executable File

#!/usr/bin/env python3
"""Nexus Autoparts — Post-Installation Health Check
Verifies that all components are running correctly after installation.
Usage: python3 scripts/health_check.py
"""
import sys
import os
import requests
import psycopg2
import redis
# Ensure we can import from project root
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
def info(msg):
print(f"[INFO] {msg}")
def ok(msg):
print(f"[OK] {msg}")
def fail(msg):
print(f"[FAIL] {msg}")
return False
def check_postgresql():
"""Verify PostgreSQL is running and accessible."""
info("Checking PostgreSQL...")
try:
conn = psycopg2.connect("postgresql://nexus@localhost/nexus_autoparts")
cur = conn.cursor()
cur.execute("SELECT version()")
version = cur.fetchone()[0]
cur.close()
conn.close()
ok(f"PostgreSQL running: {version.split()[0]} {version.split()[1]}")
return True
except Exception as e:
return fail(f"PostgreSQL connection failed: {e}")
def check_master_db():
"""Verify master DB has required tables."""
info("Checking master database schema...")
try:
conn = psycopg2.connect("postgresql://nexus@localhost/nexus_autoparts")
cur = conn.cursor()
cur.execute("""
SELECT table_name FROM information_schema.tables
WHERE table_schema = 'public'
AND table_name IN ('tenants', 'brands', 'models', 'years', 'part_categories')
""")
tables = {r[0] for r in cur.fetchall()}
cur.close()
conn.close()
required = {'tenants', 'brands', 'models', 'years', 'part_categories'}
missing = required - tables
if missing:
return fail(f"Missing master tables: {missing}")
ok("Master database schema is complete")
return True
except Exception as e:
return fail(f"Master DB check failed: {e}")
def check_tenant_template():
"""Verify tenant_template database exists."""
info("Checking tenant_template database...")
try:
conn = psycopg2.connect("postgresql://nexus@localhost/tenant_template")
cur = conn.cursor()
cur.execute("SELECT 1 FROM pg_tables WHERE tablename = 'sales'")
if not cur.fetchone():
return fail("tenant_template missing 'sales' table")
cur.close()
conn.close()
ok("tenant_template database exists and has core tables")
return True
except Exception as e:
return fail(f"tenant_template check failed: {e}")
def check_first_tenant():
"""Verify at least one tenant exists."""
info("Checking first tenant...")
try:
conn = psycopg2.connect("postgresql://nexus@localhost/nexus_autoparts")
cur = conn.cursor()
cur.execute("SELECT COUNT(*) FROM tenants WHERE is_active = true")
count = cur.fetchone()[0]
cur.close()
conn.close()
if count == 0:
return fail("No active tenants found")
ok(f"Found {count} active tenant(s)")
return True
except Exception as e:
return fail(f"Tenant check failed: {e}")
def check_pos_health():
"""Verify POS health endpoint responds."""
info("Checking POS health endpoint...")
try:
resp = requests.get("http://localhost:5001/pos/health", timeout=5)
if resp.status_code == 200 and resp.json().get("status") == "ok":
ok("POS health endpoint is responding")
return True
return fail(f"POS health returned: {resp.status_code} {resp.text}")
except requests.exceptions.ConnectionError:
return fail("POS not running on port 5001")
except Exception as e:
return fail(f"POS health check failed: {e}")
def check_redis():
"""Verify Redis is running and accessible."""
info("Checking Redis...")
try:
r = redis.from_url(
os.environ.get('REDIS_URL', 'redis://localhost:6379/0'),
decode_responses=True
)
if r.ping():
info = r.info('server')
ok(f"Redis {info.get('redis_version', '?')} running")
return True
return fail("Redis PING returned False")
except Exception as e:
return fail(f"Redis connection failed: {e}")
def check_meilisearch():
"""Verify Meilisearch is running."""
info("Checking Meilisearch...")
try:
sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), 'pos'))
from services.meili_search import health_check
if health_check():
ok("Meilisearch running")
return True
return fail("Meilisearch health check failed")
except Exception as e:
return fail(f"Meilisearch connection failed: {e}")
def check_metabase():
"""Verify Metabase is running."""
info("Checking Metabase...")
try:
import requests
url = os.environ.get('METABASE_URL', 'http://localhost:3000')
r = requests.get(f"{url}/api/health", timeout=5)
if r.status_code == 200 and r.json().get('status') == 'ok':
ok("Metabase running")
return True
return fail(f"Metabase returned: {r.status_code}")
except Exception as e:
return fail(f"Metabase connection failed: {e}")
def check_web_health():
"""Verify web/dashboard responds."""
info("Checking web dashboard...")
try:
resp = requests.get("http://localhost:5000/", timeout=5)
if resp.status_code == 200:
ok("Web dashboard is responding")
return True
return fail(f"Web returned status: {resp.status_code}")
except requests.exceptions.ConnectionError:
return fail("Web server not running on port 5000")
except Exception as e:
return fail(f"Web check failed: {e}")
def main():
print("=" * 60)
print(" Nexus Autoparts — Health Check")
print("=" * 60)
print()
results = []
results.append(("PostgreSQL", check_postgresql()))
results.append(("Redis Cache", check_redis()))
results.append(("Meilisearch", check_meilisearch()))
results.append(("Metabase", check_metabase()))
results.append(("Master DB Schema", check_master_db()))
results.append(("Tenant Template", check_tenant_template()))
results.append(("First Tenant", check_first_tenant()))
results.append(("POS Health", check_pos_health()))
results.append(("Web Dashboard", check_web_health()))
print()
print("=" * 60)
passed = sum(1 for _, r in results if r)
total = len(results)
print(f" Results: {passed}/{total} checks passed")
print("=" * 60)
if passed < total:
print()
print("Failed checks:")
for name, result in results:
if not result:
print(f" - {name}")
sys.exit(1)
else:
print()
print("All systems operational!")
sys.exit(0)
if __name__ == '__main__':
main()