- Added all brands with vehicles >= 1980 relevant to Mexico-USA-Canada
- Covers: American, Japanese, Korean, German, UK, Italian, French,
Swedish, Spanish, Chinese (with MX presence), Indian, and commercial
- All 96 brands verified against master DB with year >= 1980
- Fixed column names: brands.name_brand, models.name_model, engines.name_engine
- Added fuzzy model matching with ILIKE %%pattern%% for TecDoc-style names
- Removed erroneous double cur.fetchone() that always returned None
- Added retry logic (3 attempts) for QWEN API empty responses
- Added fallback engine-less query when engine description doesn't match DB
- Protected _extract_json against None input
- bnpl_bp.py: APLAZO/Kueski/Clip application workflow (mock)
- erp_bp.py: Aspel/CONTPAQi/SAP/Odoo sync jobs (mock)
- whatsapp_cloud_bp.py: Meta Cloud API webhook, messages, templates
- supplier_portal_bp.py: demand by zone/branch and top-parts analytics
- app.py: register all new blueprints
The chat.js init() template did not include #chatTtsToggle, causing
a runtime TypeError when hasTTS was true. Added the toggle button
inside .chat-header-actions, matching chat-public.js structure.
Regenerated chat.min.js.
- Corrige UNIQUE constraint que fallaba por duplicados → índice normal
- Aumenta BATCH_SIZE a 10M + synchronous_commit=off para velocidad
- Particionamiento completado: 2.16B filas en 16 particiones
- vehicle_parts_old conservada como rollback (254 GB)
- Minify script y Quart producción ya commiteados
- Agrega ruta genérica en server.py para servir CSS/JS/HTML desde root
- Configura DATABASE_URL y JWT_SECRET en nexus.service systemd
- Agrega trust en pg_hba.conf para postgres@localhost en nexus_autoparts
- Agrega TTS (speechSynthesis) a chat.js del POS para leer respuestas IA
- Copia lógica de voz completa (STT + TTS) a dashboard/chat-public.js
- Extiende estilos TTS en chat.css y chat-public.css
- Agrega chat widget a 13 templates POS que no lo tenían
- Corrige duplicado de chat.css en diagrams.html
- Minifica assets actualizados
- 73/73 tests pasan
Cambios implementados:
1. Lazy loading de imágenes:
- catalog.js: loading="lazy" decoding="async" en part cards y detail panel
- inventory.js: lazy loading en imagen de detalle de item
2. Minificación de assets:
- scripts/minify-assets.sh: minifica JS (terser) y CSS para POS y Dashboard
- 25 archivos .min.js + 5 .min.css generados en pos/static/
- 14 archivos .min.js + 8 .min.css generados en dashboard/
3. Nginx auto-serve minified:
- try_files $1.min.js antes de servir .js original
- try_files $1.min.css antes de servir .css original
- Transparente para los templates HTML (cero cambios en HTML)
4. Cache warming script:
- scripts/warm_vehicle_cache.py: pobla Redis con vehicle info por batches
- Mitiga DISTINCT ON + 4 JOINs sobre 2B filas
- Corre en background, procesa ~1.5M parts
Tests: 73/73 pasando
Cambios implementados:
1. Redis cache para _classify_cache (catalog_service.py):
- Reemplaza dict in-memory por Redis compartido entre workers
- TTL 5 minutos para clasificación Nexpart
- classify_cache_clear() y classify_cache_stats() actualizados
- Hit rate pasa de ~6% (15 cachés separados) a ~80%+ (cache unificado)
2. Redis cache para vehicle info en smart_search():
- Verifica Redis antes de ejecutar DISTINCT ON + 4 JOINs sobre 2B filas
- Cache miss: query solo para los part_ids faltantes
- TTL 1 hora por part_id
- Impacto: búsquedas repetidas pasan de 500ms–2s a < 50ms
3. Gunicorn gthread (gunicorn.conf.py):
- worker_class = 'gthread' con 4 threads por worker
- 4 workers × 4 threads = 16 requests concurrentes
- max_requests = 1000 para reciclar workers y prevenir memory leaks
Tests: 73/73 pasando
Cambios implementados:
1. Connection pooling (tenant_db.py):
- psycopg2.pool.ThreadedConnectionPool para master y tenants
- Wrapper _PooledConnection que devuelve al pool en .close()
- Cero cambios en blueprints (backward compatible)
2. Tabla inventory_stock_summary + triggers (v3.2):
- O(1) stock lookup en vez de SUM() sobre historial completo
- Trigger AFTER INSERT en inventory_operations recalcula stock
- Poblada inicialmente en ambos tenants
- Refactor en 6 archivos de servicios para usar la nueva tabla
3. Fix N+1 en process_sale (pos_engine.py):
- Precarga retail_price en bulk query FOR UPDATE
- Elimina SELECT individual por item en loop
4. Índices críticos:
- idx_parts_name_part + pattern_ops (master)
- idx_inv_ops_inventory_branch_created (tenants)
- idx_wi_part_stock_positive (master, ya existía desde Fase 1)
Tests: 73/73 pasando (compat + fase3 + fase5 + fase6)
Migración: v3.2_db_performance.sql
- Nueva tabla inventory_vehicle_compat (v3.1)
- Motor inventory_vehicle_compat.py: auto-match + gestión manual
- catalog_service.get_parts_local() ahora incluye piezas locales vinculadas
- inventory_bp: auto-match en create/update + endpoints REST /vehicles
- Frontend catalog.js: badge 'Stock Local' para piezas nativas del tenant
- Frontend inventory.js: panel de vehículos compatibles con auto-match
- Tests: test_compatibility.py (9/9 pasan)
Piezas locales aparecen en navegación por vehículo aunque no estén en TecDoc.
Auto-match busca part_number en parts/aftermarket_parts y copia MYEs compatibles.
La doc previa describía Evolution API, pero el stack real desde abril
es Baileys directo en /opt/whatsapp-bridge/. Se documenta el systemd
unit que ahora supervisa el proceso y se agrega troubleshooting.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Segmento de mercado, comparativa de competencia y script de ventas
para fase inicial BCN (Tijuana, Rosarito, Tecate, Ensenada).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replaced hardcoded values (4,817 SKUs, $2.4M, 1,284 clients, $842,190
invoiced, $2,847,320 assets, etc.) with $0 / 0 placeholders with IDs
so the JS can populate them from real API data.
Affected: inventory.html, customers.html, invoicing.html, accounting.html
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>