Files
Autoparts-DB/docs/FASES_IMPLEMENTADAS.md
consultoria-as a386ca5b4a
Some checks failed
CI / lint-and-test (3.11) (push) Has been cancelled
CI / lint-and-test (3.13) (push) Has been cancelled
Mejoras de sesion: estabilizacion, IA, Nexus Yonke y marketplace B2B
- F0 blindaje: Redis/Celery, pg_hba sin trust LAN, secretos a env 600, backups, webhook auth, jobs muertos
- F1 caja: bugs POS, reembolsos al corte, apartados, CFDI, topes de descuento en cotizacion/apartado
- F2/F7 IA de catalogo: autocategorizacion, dedup de SKUs con embeddings, OCR de facturas, descripciones, claves SAT, limpieza de fitment
- F3 IA en el flujo: vision Yonke, preguntas MeLi, venta cruzada, anomalias, sinonimos, busqueda semantica (rerank/embeddings)
- F4/F8 escala y cartera: /metrics+Prometheus+Grafana, pool, score de credito, churn, metricas multi-tenant
- Nexus Yonke (M1-M6): modelo de datos 1-de-1, alta por donador, vitrina publica, MeLi usado, consignacion, garantia por dias, reportes, etiquetas
- Marketplace B2B entre yonkes (catalogo + pedidos cross-tenant)
- Seguridad: auth en /api/admin/* (35 endpoints), alertas por tenant
- Migraciones v4.27/v4.28; timers expire-demos y rollup-metrics
2026-10-12 00:57:31 +00:00

385 lines
24 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Nexus POS — Resumen de Fases Implementadas
**Fecha:** 2026-06-15
**Versión DB:** v4.4
**Tests:** 92/92 pasando (pytest: 61 consola + 20 Facturapi + 11 Taller; POS requieren PostgreSQL)
**Commit:** `d678872` (HEAD + cambios sin commitear)
---
## FASE 1-2: Fundamentos (pre-existente)
- ✅ CFDI 4.0 con Facturapi
- ✅ VIN Decoder (NHTSA)
- ✅ Lookup por placas mexicanas
- ✅ Carrito unificado multi-bodega
- ✅ Cotizaciones digitales → WhatsApp
- ✅ Auth JWT + roles
## FASE 3: Multi-sucursal + Alertas + Garantías
| Feature | Archivos | Endpoints |
|---------|----------|-----------|
| **Multi-sucursal** | `inventory_engine.py`, `inventory_bp.py` | `GET /pos/api/inventory/stock-by-branch`, `POST /pos/api/inventory/transfers`, `POST /pos/api/inventory/sync-prices` |
| **Alertas de Reorden** | `reorder_engine.py` | `POST /pos/api/inventory/generate-alerts`, `GET /pos/api/inventory/reorder-alerts`, `PUT /pos/api/inventory/reorder-alerts/:id/acknowledge`, `PUT /pos/api/inventory/reorder-alerts/:id/resolve`, `GET /pos/api/inventory/reorder-suggest-po` |
| **Garantías / RMA** | `warranty_engine.py`, `warranty_bp.py` | `POST /pos/api/warranties`, `GET /pos/api/warranties`, `GET /pos/api/warranties/:id`, `GET /pos/api/customers/:id/warranties`, `POST /pos/api/warranty-claims`, `PUT /pos/api/warranty-claims/:id/resolve`, `PUT /pos/api/warranty-claims/:id/close` |
## FASE 4: Infraestructura + Escalabilidad
| Feature | Archivos | Infra |
|---------|----------|-------|
| **Redis Cache** | `redis_stock_cache.py`, `inventory_engine.py` | Redis 8.0.2, TTL 300s, fallback a PostgreSQL |
| **Multi-moneda** | `currency.py`, `pos_engine.py`, `cfdi_builder.py` | MXN base, USD soporte, contabilidad siempre en MXN |
| **Proveedores + POs** | `supplier_engine.py`, `supplier_bp.py` | 11 endpoints: CRUD proveedores + workflow PO completo |
| **Meilisearch** | `meili_search.py`, `catalog_service.py`, `sync_meilisearch.py` | Docker, 1.5M+ partes indexadas, búsqueda 4ms |
| **Metabase KPIs** | `setup_metabase.py`, `docker-compose.metabase.yml` | Docker v0.53, dashboard auto-generado |
## FASE 5: CRM + Service Orders + Imágenes
| Feature | Archivos | Capacidades |
|---------|----------|-------------|
| **CRM Mejorado** | `crm_engine.py`, `crm_bp.py` | Activities timeline, tags de segmentación, loyalty program (bronze/silver/gold/platinum), analytics (LTV, churn risk, categorías favoritas) |
| **Imágenes de Partes** | `image_service.py`, `image_bp.py` | Upload multipart/URL, resize 1200px, thumbnail 300x300, WebP, bulk import |
| **Órdenes de Servicio** | `service_order_engine.py`, `service_order_bp.py` | Kanban: received→diagnosis→waiting_parts→repair→quality_check→ready→delivered, items (refacciones), labor (mano de obra), historial de status |
| **WhatsApp** | `whatsapp_service.py`, `whatsapp_bp.py` | Webhook Baileys, AI chatbot, cotizaciones, voz, imágenes |
| **Flotillas** | `fleet_bp.py` | CRUD vehículos, maintenance schedules, logs, alerts, stats |
| **BNPL stub** | `bnpl_engine.py` | Arquitectura APLAZO/Kueski/Clip |
| **ERP Sync stub** | `erp_sync_engine.py` | Arquitectura Aspel/Contpaqi/SAP/Odoo |
## FASE 6: Notificaciones + Ahorro + Logística + API Pública
| Feature | Archivos | Capacidades |
|---------|----------|-------------|
| **Notificaciones** | `notification_engine.py`, `notification_bp.py` | Templates por evento+canal, dispatch automático (push/WhatsApp/email/in-app), logs con estados, eventos: low_stock, order_ready, maintenance_due, new_sale, po_received, reorder_alert, warranty_expiring |
| **Reportes de Ahorro** | `savings_engine.py`, `savings_bp.py` | Campo `retail_price` en inventory, cálculo automático en checkout, reporte por cliente (LTV ahorro, desglose mensual), reporte global (top clientes, promedio por orden) |
| **Logística + Tracking** | `logistics_engine.py`, `logistics_bp.py` | 6 couriers pre-cargados (DHL, FedEx, Estafeta, 99min, Uber, Pickup), envíos vinculados a ventas/SO/PO, tracking URL auto-generada, historial de estatus |
| **API Pública** | `public_api_engine.py`, `public_api_bp.py` | API keys seguras (SHA-256), scopes (read/write/admin), rate limiting por minuto/día con headers, logging de requests, endpoints: `/api/v1/health`, `/api/v1/catalog/search`, `/api/v1/catalog/parts/:id` |
## FASE 7: Performance Optimización
| Sub-fase | Archivos | Optimizaciones |
|----------|----------|----------------|
| **7a — Quick Wins Frontend** | `nginx/nexus-pos.conf`, `pos/templates/*.html`, `pos/static/js/catalog.js` | gzip nginx, `defer` en scripts, fix `innerHTML +=` (8 lugares), event delegation cart, AbortController, sessionStorage cache years/brands |
| **7b — DB Performance** | `pos/tenant_db.py`, `pos/services/inventory_engine.py`, `pos/services/pos_engine.py`, `pos/migrations/v3.2_db_performance.sql` | Connection pooling (`psycopg2.pool`), tabla `inventory_stock_summary` + triggers O(1), fix N+1 `process_sale`, índices críticos |
| **7c — Redis + Gthread** | `pos/services/catalog_service.py`, `pos/gunicorn.conf.py` | `_classify_cache` en Redis (hit 6%→80%), vehicle info cache en `smart_search()`, gunicorn `gthread` (4 workers × 4 threads) |
| **7d — Lazy Load + Minify** | `pos/static/js/catalog.js`, `nginx/nexus-pos.conf`, `scripts/minify-assets.sh` | `loading="lazy"` en imágenes, minificación auto-serve vía nginx, cache warming script |
| **7e — CSS Inline Extraction** | `scripts/extract-inline-css.py`, 28 templates HTML, 28 archivos `.css`/`.min.css` | CSS inline extraído de 15 templates POS + 13 templates Dashboard a archivos externos, minificación, nginx auto-serve |
**Impacto acumulado FASE 7:**
- Transferencia: -40–60%
- TTI: -200–500ms
- Stock lookups: O(n) → O(1)
- Ventas 20 ítems: 21 queries → 1 query
- Cache hit rate: 6% → 80%+
## Opción C — Consolidación Técnica (COMPLETADA)
| Item | Estado | Commit |
|------|--------|--------|
| **C1: MV `part_vehicle_preview`** | ✅ En producción, refresh automático vía systemd timer (03:00 UTC) | `f893391` |
| **C2: Cache warming script** | ✅ Autónomo con auto-sudo fallback, args CLI | `f893391` |
| **C3: CSS dinámico residual** | ✅ `sidebar.js` → `sidebar.css`, `pos-utils.js` → `common.css` | `042acd6` |
| **C4: Load testing script** | ✅ `scripts/load_test.py` con `locust` | `042acd6` |
| **C5: Docs audit** | ✅ `FASES_IMPLEMENTADAS.md`, `performance_audit_2026.md` | `042acd6` |
## Opción A — Arquitectura Avanzada (COMPLETADA)
| Item | Estado | Commit |
|------|--------|--------|
| **A1: `orjson` como JSON provider** | ✅ Hereda `DefaultJSONProvider`, fix indent en `pos_bp.py` | `a1be8dd` |
| **A2: Virtual scroll** | ✅ `inventory.js`, `customers.js`, `fleet.js` | `a1be8dd` |
| **A3: Celery worker queue** | ✅ `celery_app.py`, `tasks.py`, `tasks_bp.py`, systemd service activo | `a1be8dd` |
| **A4: Quart + asyncpg PoC** | ✅ `async_catalog.py` en puerto 5002, benchmark script | `a1be8dd` |
| **A5: Particionamiento `vehicle_parts`** | ✅ Script `partition_vehicle_parts.py` listo (HASH 16 particiones, dry-run) | `a1be8dd` |
## IA por Voz — Chalán de Nexus (COMPLETADA)
| Componente | Estado |
|------------|--------|
| **STT (Speech-to-Text)** | ✅ POS + Dashboard público, `es-MX`, auto-send, animación micrófono |
| **TTS (Text-to-Speech)** | ✅ Botón 🔊 en burbujas de IA, `speechSynthesis`, preferencia guardada en `localStorage` |
| **Cobertura templates POS** | ✅ 14/14 templates tienen chat widget |
| **Dashboard público** | ✅ Chat público con voz completa (sin cámara) |
## QWEN 3.6 AI Vehicle Fitment (COMPLETADA)
| Componente | Archivo | Descripción |
|------------|---------|-------------|
| **Servicio QWEN** | `pos/services/qwen_fitment.py` | Consulta API OpenAI-compatible (`qwen3.6`) con part_number + name + brand; parsea JSON robusto (vehicles/confidence/notes); valida contra `model_year_engine` |
| **Integración Inventario** | `pos/blueprints/inventory_bp.py` | `create_item()` llama QWEN después de TecDoc auto-match; inserta en `inventory_vehicle_compat` con `source='qwen_ai'` |
| **UI** | `pos/static/js/inventory.js`, `pos/templates/inventory.html` | Toast muestra count de vehículos asignados por IA; tabla de compatibilidad muestra columna "Origen" |
| **Retry / Fallback** | `qwen_fitment.py` | 3 reintentos ante respuesta vacía; fallback sin filtro de motor (descripciones de motor rara vez coinciden entre QWEN y TecDB); búsqueda parcial de modelo (`%Corolla%`) para nombres TecDoc |
**Flujo:**
1. Usuario crea ítem de inventario (part_number, name, brand)
2. TecDoc auto-match ejecuta primero (si hay coincidencia exacta)
3. QWEN 3.6 recibe los datos y devuelve lista de vehículos compatibles en JSON
4. Cada vehículo se busca en la DB maestra (fuzzy match por modelo, fallback sin motor)
5. Los `model_year_engine_id` válidos se insertan en `inventory_vehicle_compat` con `source='qwen_ai'`
6. Frontend muestra toast: "27 vehículo(s) asignado(s) por IA"
**Fail-safe:** Si QWEN no está configurado o la API falla, el ítem se crea normalmente; la asignación de vehículos se omite silenciosamente.
---
## Infraestructura Desplegada
| Servicio | Versión | Puerto | Estado |
|----------|---------|--------|--------|
| PostgreSQL | 17 | 5432 | ✅ Optimizado (8GB shared_buffers, 64MB work_mem, 8GB max_wal_size) |
| Redis | 8.0.2 | 6379 | ✅ Stock cache + classify cache |
| Meilisearch | v1.12 | 7700 | ✅ 1,546,976 documentos |
| Metabase | v0.53 | 3000 | ✅ Dashboard ID 2 |
| Nginx | — | 80/443 | ✅ gzip, cache 6M, auto-serve .min |
| Gunicorn POS | — | 5001 | ✅ systemd `nexus-pos.service`, gthread 4×4 |
| Gunicorn Dashboard | — | 5000 | ✅ systemd `nexus.service` |
| Quart Catalog | — | 5002 | ✅ systemd `nexus-quart.service`, hypercorn |
| Celery | — | — | ✅ 4 prefork workers, broker redis://localhost:6379/1 |
| Prometheus | v2.51 | 9090 | ✅ Docker, node/postgres/redis exporters |
| Grafana | v10.4 | 3001 | ✅ Docker, auto-provisioned Prometheus datasource |
---
## Variables de Entorno Requeridas
```bash
# Base
MASTER_DB_URL=postgresql://user:pass@host/nexus_autoparts
TENANT_DB_URL_TEMPLATE=postgresql://user:pass@host/{db_name}
POS_JWT_SECRET=<32+ bytes hex>
# Redis
REDIS_URL=redis://localhost:6379/0
REDIS_ENABLED=true
REDIS_STOCK_TTL=300
# Meilisearch
MEILI_URL=http://localhost:7700
MEILI_API_KEY=nexus-master-key-change-me
MEILI_ENABLED=true
# Multi-moneda
DEFAULT_CURRENCY=MXN
EXCHANGE_RATE_USD_MXN=17.5
# WhatsApp (opcional)
WHATSAPP_BRIDGE_URL=http://localhost:21465
WHATSAPP_BRIDGE_KEY=
# AI (opcional)
OPENROUTER_API_KEY=
# QWEN AI Fitment (opcional)
QWEN_API_URL=https://api.nan.builders/v1
QWEN_API_KEY=
QWEN_MODEL=qwen3.6
# Metabase (opcional)
METABASE_DB_PASS=
METABASE_URL=http://localhost:3000
```
---
## ✅ Completados recientemente
| # | Mejora | Fecha | Commit |
|---|--------|-------|--------|
| — | **Particionar `vehicle_parts` en producción** | 2026-04-26 | `f24f25e` |
| — | **Quart async catalog en producción** | 2026-04-26 | `b829e4f` |
| — | **Arreglar `scripts/minify-assets.sh`** | 2026-04-26 | `b829e4f` |
| — | **Dashboard outage fix (env vars + static files)** | 2026-04-26 | `27cb4ee` |
| — | **IA por Voz (STT + TTS) en POS y Dashboard** | 2026-04-26 | `afb3b24` |
| — | **Fix chat.js null reference (`chatTtsToggle`)** | 2026-04-29 | `44c3a6c` |
| — | **Optimizar PostgreSQL config + restart** | 2026-04-29 | — |
| — | **Cache warming systemd timer** | 2026-04-29 | `c766571` |
| — | **Monitoreo Prometheus + Grafana** | 2026-04-29 | `4b3b0f8` |
| — | **PWA install prompt** | 2026-04-29 | `3b8224d` |
| — | **Playwright E2E tests** | 2026-04-29 | `c4db5e7` |
| — | **Dashboard in-app charts** | 2026-04-29 | `12989e3` |
| — | **Stubs BNPL / ERP / WhatsApp Cloud / Supplier Portal** | 2026-04-29 | `2cfe4b3` |
| — | **nexus-pos.service systemd** | 2026-04-29 | `c766571` |
| — | **QWEN 3.6 AI Vehicle Fitment** | 2026-04-29 | `623c57b` |
| — | **Migración CFDI de Horux a Facturapi** | 2026-06-14 | `8796cad` |
| — | **Setup/estado masivo de organizaciones Facturapi** | 2026-06-15 | — |
| — | **Módulo de Taller (Workshop Lite)** | 2026-06-15 | — |
## FASE 7: Precios de Proveedor + Multi-sucursal + Factura Global
**Commit:** `2b73c2c` (2026-06-11)
### 7.1 Lista de Precios de Proveedor
| Feature | Archivos | Capacidades |
|---------|----------|-------------|
| **Precios por proveedor** | `supplier_catalog_prices` (master DB) | Precio, moneda, vigencia (effective_from/to), activo/inactivo |
| **Upload masivo** | `supplier_catalog_bp.py` | CSV/Excel con supplier_name, sku, price, currency |
| **Visualización** | `catalog.js`, `catalog_service.py` | `supplier_price` + `supplier_currency` en tarjetas y búsqueda |
| **Endpoints** | `supplier_catalog_bp.py` | `GET/POST/PUT/DELETE /pos/api/supplier-catalog/prices/*` |
### 7.2 Multi-sucursal Completo
| Feature | Archivos | Capacidades |
|---------|----------|-------------|
| **Schema migration v4.0** | `v4.0_multi_branch.sql` | `inventory.branch_id=NULL` (catálogo compartido), tabla `inventory_stock` |
| **Datos fiscales por sucursal** | `branches` (tenant DB) | `rfc`, `razon_social`, `regimen_fiscal`, `codigo_postal`, `serie_cfdi`, `folio_inicial`, `licencia_fiscal`, `certificado_pem`, `llave_pem`, `is_main` |
| **Sincronización de stock** | Trigger `trg_update_inventory_stock` | `inventory_operations` → `inventory_stock` automático |
| **Backend branches** | `config_bp.py` | CRUD completo con campos fiscales, validación de única sucursal `is_main` |
| **Backend inventario** | `inventory_bp.py`, `inventory_engine.py`, `pos_bp.py` | Stock por sucursal vía `inventory_stock`, catálogo compartido, verificación de stock en POS |
| **Backend facturación** | `invoicing_bp.py` | CFDI usa datos fiscales de la sucursal de la venta (`_get_issuer_config`) |
| **Frontend config** | `config.html`, `config.js` | Modal de sucursal expandido con todos los campos fiscales, edición inline |
### 7.3 Factura Global Mensual
| Feature | Archivos | Capacidades |
|---------|----------|-------------|
| **Schema migration v4.1** | `v4.1_global_invoice.sql` | `global_invoice_sales`, `sales.global_invoiced_at` |
| **Builder CFDI global** | `cfdi_builder.py` | `build_global_invoice_xml()` con `InformacionGlobal` SAT-compliant (`Periodicidad="04"`) |
| **Servicio** | `global_invoice.py` | Agrupa ventas PUE ≤$2,000 sin CFDI individual del mes/año solicitado |
| **Endpoints** | `invoicing_bp.py` | `POST /global-invoice`, `GET /global-invoice/<id>`, `GET /global-invoice/eligible-sales` |
| **Frontend** | `invoicing.html`, `invoicing.js` | Botón "Factura Global" con modal de año/mes + vista previa de ventas elegibles |
### 7.4 Mercado Libre — Mejoras
| Feature | Archivos | Capacidades |
|---------|----------|-------------|
| **Importar publicaciones existentes** | `meli_service.py`, `marketplace_external_service.py` | `get_user_items()` + `import_existing_listings()` — importa items del vendedor a `marketplace_listings` intentando match por SKU/part_number |
| **Sync stock POS → ML** | `inventory_engine.py`, `marketplace_external_service.py` | Trigger en `inventory_operations` inserta en `meli_sync_queue`; `process_meli_sync_queue()` actualiza `available_quantity` en ML vía API |
| **Sync órdenes ML → POS** | `marketplace_external_bp.py` | `POST /orders/sync` para sincronización manual; webhook `/webhook/meli` ya maneja notificaciones de órdenes vía Celery |
| **Migration v4.2** | `v4.2_meli_sync_queue.sql` | Tabla `meli_sync_queue` para encolar actualizaciones de stock |
---
## FASE 8: Migración CFDI a Facturapi
**Commit:** `8796cad` (2026-06-14)
**Migración DB:** `v4.3_facturapi.sql`
| Feature | Archivos | Capacidades |
|---------|----------|-------------|
| **Timbrado vía Facturapi** | `facturapi_service.py`, `cfdi_facturapi_builder.py`, `cfdi_queue.py` | Payloads JSON para Facturapi en lugar de XML unsigned; timbrado, descarga XML/PDF, cancelación SAT |
| **Organizaciones Facturapi** | `invoicing_bp.py` | `POST /pos/api/invoicing/facturapi/setup` crea/liga organización; `GET /pos/api/invoicing/facturapi/status` muestra estado del PAC |
| **Subida de CSD** | `invoicing_bp.py`, `invoicing.html`, `invoicing.js` | Upload de `.cer` y `.key` con contraseña directo a Facturapi |
| **Migración de datos** | `v4.3_facturapi.sql`, `scripts/apply_facturapi_to_all_tenants.py` | Renombra `xml_unsigned` → `payload_unsigned`, agrega `external_id`, inserta keys de config |
| **Setup masivo** | `scripts/setup_facturapi_orgs.py` | Crea organizaciones Facturapi para todos los tenants activos usando `FACTURAPI_USER_KEY` |
| **Status masivo** | `scripts/check_facturapi_tenants.py` | Reporte tabular/JSON/CSV del estado de configuración Facturapi por tenant |
| **Tests unitarios** | `pos/tests/test_facturapi_service.py` | 20 tests con mocks; sin llamadas a red ni PostgreSQL |
| **CI** | `.github/workflows/ci.yml` | Lint con ruff sobre archivos cambiados + tests de consola en Python 3.11 y 3.13 |
### Variables de entorno
```bash
# Modo automático (recomendado para multi-tenant)
FACTURAPI_USER_KEY=sk_user_xxxxxxxxxxxxxxxx
# Modo manual por tenant (sobreescribe lo anterior)
# Se almacena en tenant_config: cfdi_facturapi_key, cfdi_facturapi_org_id
```
### Uso
```bash
# 1. Aplicar migración y key a todos los tenants
export FACTURAPI_SECRET_KEY=sk_user_xxx
python3 scripts/apply_facturapi_to_all_tenants.py
# 2. Crear organizaciones Facturapi
export FACTURAPI_USER_KEY=sk_user_xxx
python3 scripts/setup_facturapi_orgs.py
# 3. Ver estado
python3 scripts/check_facturapi_tenants.py
```
---
## FASE 9: Módulo de Taller (Workshop Lite)
**Commit:** (en progreso)
**Migración DB:** `v4.4_workshop.sql`
| Feature | Archivos | Capacidades |
|---------|----------|-------------|
| **Migración DB** | `v4.4_workshop.sql` | `service_orders.sale_id`, tabla `service_catalog`, columna `reserved_quantity`, tipos `SO_RESERVE`/`SO_RELEASE` en `inventory_operations` |
| **Reserva de inventario** | `service_order_engine.py` | `reserve_item()` y `release_item()` para apartar/liberar refacciones del stock de la sucursal |
| **Conversión a venta** | `service_order_engine.py` | `convert_to_sale()` crea una venta en `sales` con refacciones + mano de obra, descuenta inventario y guarda `sale_id` |
| **Catálogo de servicios** | `service_order_engine.py`, `service_order_bp.py` | Conceptos reutilizables de mano de obra (ej. "Cambio de aceite") |
| **Endpoints taller** | `service_order_bp.py` | `POST /:id/items/:item_id/reserve`, `POST /:id/convert-to-sale`, `PUT /:id/assign-mechanic`, CRUD `/service-catalog` |
| **Interfaz Kanban** | `workshop.html`, `workshop.js`, `workshop.css` | Vista por columnas, tarjetas de orden, modal de detalle, cambio de estado, agregar refacciones/mano de obra |
| **Impresión de orden** | `thermal_printer.py`, `service_order_bp.py`, `printer.js`, `workshop.js` | Ticket ESC/POS optimizado para impresoras térmicas 80 mm (58 mm compatible) |
| **Navegación** | `sidebar.js`, plantillas inline | Entrada "Taller" en el menú de gestión |
| **Tests** | `pos/tests/test_service_order_integration.py` | 11 tests con cursores mocks; validan reserva, liberación, conversión a venta y catálogo |
### Flujo de uso
1. El paquetero crea la orden desde `/pos/workshop` (cliente, vehículo, mecánico, falla).
2. El mecánico diagnostica y agrega refacciones y mano deobra.
3. Se reservan las refacciones del inventario de la sucursal.
4. Cuando el vehículo está listo, se convierte la orden en venta.
5. Desde facturación se timbra el CFDI de la venta generada.
---
## Mejoras A5 / A6 / A10 (2026-10-11)
Capacidades que no dependen de gran volumen de ventas históricas.
| # | Feature | Archivos | Qué hace |
|---|---------|----------|----------|
| **A10** | Venta cruzada "esto + esto" | `services/cross_sell.py`, `blueprints/pos_bp.py` (`POST /pos/api/recommendations`), `static/js/pos.js`, `templates/pos.html` | Sugiere complementos del carrito usando `part_kits.KIT_SUGGESTIONS` + co-ocurrencia real en `sale_items` (mismo `sale_id`). Prioriza piezas con stock; panel en el POS al agregar un artículo. Permiso `pos.sell`. |
| **A5** | Anomalías de negocio | `services/anomaly_detector.py`, `blueprints/pos_bp.py` (`GET /pos/api/reports/anomalies`), `scripts/run_anomaly_scan.py` | z-score robusto (MAD) por empleado/SKU sobre `sale_items` + `sales` + `audit_log`: descuentos atípicos, ventas bajo costo, cancelaciones repetidas y ventas fuera de horario (TZ `America/Mexico_City`). Maneja *cold start* (`min_samples`, default 5) y nunca marca `unit_cost = 0` como bajo costo. Permiso `reports.view`. |
| **A6** | Sinónimos + cross-refs en búsqueda | `services/meili_search.py` (`build_synonyms`, `apply_synonyms_to_all`), `scripts/index_meilisearch.py` (`synonyms` mode, `aliases`), `services/catalog_service.py` (`_search_inventory_by_alias`) | Sinónimos ES↔EN (curados + `services.translations.PART_TRANSLATIONS`, 653 términos) aplicados a `nexus_inventory_*` y `nexus_supplier_catalog` sin reindexar. Los SKU alias (`inventory_sku_aliases`) e interchange se indexan en `aliases` y además se consultan por SQL, así la búsqueda por número cruzado funciona de inmediato. |
Comandos de operación (A6):
```bash
# Aplicar solo settings/sinónimos (no reindexa documentos)
python3 scripts/index_meilisearch.py synonyms
# Reindexar un tenant (incluye aliases) o todos
python3 scripts/index_meilisearch.py tenant tenant_capi_autopartes
python3 scripts/index_meilisearch.py all
# Escaneo de anomalías (exit 1 si hay hallazgos de severidad alta)
python3 scripts/run_anomaly_scan.py all 90
```
---
## Mejoras Pendientes (Roadmap Actualizado)
### 🔴 Crítico — Deuda Técnica
*Sin items críticos pendientes.*
### 🟠 Alto — Features de Negocio (requieren integración con terceros)
| # | Mejora | Descripción | Esfuerzo | Notas |
|---|--------|-------------|----------|-------|
| 1 | **WhatsApp Business API (Meta Cloud) real** | Migrar de Baileys a Meta Cloud API. Requiere verificación de cuenta Meta, Business Manager, número de teléfono verificado. | 2-3 semanas | Stub creado (`whatsapp_cloud_bp.py`) |
| 2 | **BNPL real** | Integrar APLAZO/Kueski/Clip con credenciales de sandbox/producción. | 2 semanas | Stub creado (`bnpl_bp.py`) |
| 3 | **ERP Sync real** | Conectar Aspel/CONTPAQi/SAP/Odoo vía API o archivos de intercambio. | 2-3 semanas | Stub creado (`erp_bp.py`) |
| 4 | **Mercado Libre / Amazon sync** | Publicar inventario de bodegas en marketplaces. API de ML Seller + Amazon SP-API. | 3 semanas | **Parcialmente listo** — ver Fase 7.4 |
### 🟡 Medio — Diferenciadores
| # | Mejora | Descripción | Esfuerzo |
|---|--------|-------------|----------|
| 5 | **App móvil nativa (Capacitor)** | Wrap del POS como app iOS/Android. Camera nativa, push notifications, biometrics. | 3-4 semanas |
| 6 | **Crédito basado en comportamiento** | Evaluación automática de línea de crédito por historial de pagos del cliente. | 2 semanas |
| 7 | **Programa de embajadores** | Referidos con recompensas, tracking de conversiones. | 1 semana |
### 🟢 Bajo — Polish
| # | Mejora | Descripción |
|---|--------|-------------|
| 8 | **Backup automatizado** | Último backup 2026-04-27. Automatizar con cron + S3/GCS. |
| 9 | **Grafana dashboards predefinidos** | Actualmente solo datasource auto-provisionado. Falta crear dashboards JSON para PostgreSQL, Redis, Gunicorn. |
| 10 | **Alertas Prometheus** | Alertmanager para notificaciones cuando PostgreSQL, Redis o Gunicorn fallen. |
| 11 | **Tests E2E adicionales** | Playwright: checkout, búsqueda de catálogo, flujo de inventario. |
| 12 | **Service Worker mejorado** | Background sync real para carrito offline, notificaciones push. |
---
## Backup
Último backup: `/home/Autopartes/backups/nexus_backup_20260427_045859.tar.gz` (1.3 GB)