- Register all missing migrations in runner.py
- Make v4.3 idempotent (rename xml_unsigned only if exists)
- Make v3.3 idempotent (skip warehouse_inventory/purchase_order_items ops when tables/columns missing)
- Mark v3.3.1 and v3.9 as master-only (SKIP)
- Mark v3.5.1 as optional (skip if whatsapp tables missing)
- Runner skips files marked with '-- : SKIP'
- Replace ID Producto input with autocomplete search by name/part number/barcode
- Support Enter key for barcode/part number exact match
- Keep hidden inventory_id field for API compatibility
- Bump inventory.js cache version
- get_org_status now returns has_key, has_org_id, pending_steps, error
- add find_organization_by_rfc and create_organization helpers
- add /facturapi/setup endpoint to link/create Facturapi org
- frontend shows detailed PAC status and setup button
- support using tenant sk_user_* key when FACTURAPI_USER_KEY env is absent
- Month view now groups by weeks of the current calendar month
- Labels are Sem 1, Sem 2, Sem 3, Sem 4
- Historical sales grouped by day-of-month into the 4 week buckets
- Bump dashboard.js to ?v=7
- Replace placeholder setPeriod() with functional period switcher
- loadChart() supports Hoy (1 day), Semana (7 days), Mes (4 weeks), Año (12 months)
- Includes both normal POS sales and imported historical sales
- Updates chart title, total label and legend dynamically
- Bump dashboard.js to ?v=6
- Add 'Histórico' tab inside Reports page with date/customer filters
- Show historical sales KPIs and detail table in reports
- Add historical sales summary cards to Dashboard
- Load current month totals and total imported records
- Add scripts/import_atlas_data.py to load Atlas data from Excel files
- Import 6,206 inventory items, 251 customers and 4,582 historical sales
- Create historical_sales table in tenant DB
- Add /pos/historical-sales page and /pos/api/historical-sales endpoint
- Link in reports sidebar for easy access
- process_sale now falls back to main branch when g.branch_id is missing
- Accept branch_id from request body as override
- Make update_inventory_stock trigger skip operations with NULL branch_id
- Applied updated trigger to all active tenant DBs
- Add v3.4-v3.8 and v4.2 to migration registry
- Remove v3.9 (master-only supplier_catalog_prices table)
- Ensures new tenants like La Casita get all schema updates
- ML's new User Products model requires family_name in item body
- Use product name as family_name (generic product description)
- Keep title for backward compatibility with legacy sellers
- Add upload_image() to MeliService using ML /pictures endpoint
- Add get_listing_price() to fetch exact ML fees
- Auto-upload inventory images to ML before validate/publish
- Show fee breakdown and net earnings in validate modal
- Fallback to approximate fees (13-18%) if ML API fails
- Add address and cp to list_customers() backend response
- Show razon_social as subtitle in customer table rows
- Add razon_social and cp fields to detail panel
- Update customers.html detail panel layout
- Use cp instead of codigo_postal
- Use folio_inicio/folio_actual instead of folio_inicial
- Add direccion_fiscal and email fields
- Remove non-existent certificado_pem, llave_pem, licencia_fiscal
- Fixes 500 error on /api/config/branches
- meli_service.py: agrega get_user_items() para obtener publicaciones del vendedor
- marketplace_external_service.py:
- import_existing_listings(): importa publicaciones existentes de ML a marketplace_listings
- process_meli_sync_queue(): procesa cola de sincronizacion de stock a ML
- Actualiza stock en ML via update_item(available_quantity)
- marketplace_external_bp.py:
- POST /listings/import-existing - importa publicaciones existentes
- POST /sync-stock - procesa cola de stock manualmente
- POST /orders/sync - sincroniza ordenes manualmente
- inventory_engine.py: inserta en meli_sync_queue tras cada operacion de inventario
- migration v4.2: crea tabla meli_sync_queue
Prueba en tenant_refaccionaria_rached: 52 publicaciones importadas exitosamente
- Actualiza FASES_IMPLEMENTADAS.md con Fase 7 (precios proveedor, multi-sucursal, factura global)
- Agrega docs/MULTI_BRANCH.md con arquitectura y endpoints
- Agrega docs/GLOBAL_INVOICE.md con requerimiento SAT y flujo de uso
Fase 1: Lista de precios de proveedor
- Tabla supplier_catalog_prices en master DB
- Endpoints GET/POST/PUT/DELETE /supplier-catalog/prices
- Upload CSV/Excel de precios de proveedor
- Visualizacion de supplier_price en catalogo y POS
Fase 2: Multi-sucursal completo
- Migracion v4.0: inventory.branch_id=NULL, tabla inventory_stock
- Campos fiscales en branches (RFC, regimen, CP, serie CFDI, certificados)
- Trigger trg_update_inventory_stock para sincronizar stock por sucursal
- Backend config_bp.py con CRUD de sucursales fiscales
- Backend inventory_bp.py y pos_bp.py refactorizados para inventario compartido
- Backend invoicing_bp.py usa datos fiscales de la sucursal de la venta
- Frontend config.html/js con modal de sucursales expandido
Fase 3: Factura global mensual
- Migracion v4.1: tablas global_invoice_sales, sales.global_invoiced_at
- build_global_invoice_xml() con InformacionGlobal SAT-compliant
- Servicio global_invoice.py para agrupar ventas PUE <=000
- Endpoints POST/GET /global-invoice y /global-invoice/eligible-sales
- Frontend invoicing.html/js con boton y modal de factura global
- Convert sidebar.js IIFE to window.renderSidebar() so it can be re-rendered
- Call window.renderSidebar(data) from app-init.js after fetching modules
- Ensures sidebar reflects actual tenant module config, not stale localStorage
- Add GET/PUT /pos/api/config/modules endpoints in POS config_bp.py
- Update sidebar.js to filter nav items based on enabled modules
- Add Modules section to POS config.html with toggles for WhatsApp, Marketplace, MercadoLibre
- Add module load/save logic to POS config.js
- Preload modules in app-init.js for sidebar caching
- Add tenant module management to Instance Manager
- get_tenant_modules / update_tenant_modules in tenant_service.py
- GET/PUT /api/tenants/<id>/modules endpoints in tenants_bp.py
- Add modules modal to manager index.html
- Add module editing UI and logic to manager.js
- Add toggle-switch CSS to manager.css
- Remove transition: background-color/color from body in all CSS files
- These transitions caused visible flash when navigating between pages
- The browser would animate from old theme colors to new theme colors
- The inline anti-flash script now applies the correct theme before any CSS renders
- Without the hardcoded attribute, the browser never paints with the wrong theme
- Remove setTimeout re-application of theme in app-init.js that caused flash
- Fix quotations.html: add missing i18n.js and correct script load order
- Fix whatsapp.html: add missing app-init.js before sidebar.js
- Ensure i18n.js always loads before sidebar.js for proper translation
- Add skip-validation checkbox for accounts where ML validation fails due to config
- Detect 'User has not mode' errors and show detailed actionable help box
- Include direct links to ML seller config and support
- build_item_payload now sends only mode in shipping payload by default
- Let ML determine free_shipping/local_pick_up based on account config
- Better error message for mandatory free shipping scenario
- Add get_shipping_preferences to meli_service.py
- Add check_meli_shipping_config to validate ME2 adoption before publishing
- Include local_pick_up and free_shipping in item payload
- Translate ME2/mode errors to actionable Spanish messages
- Check shipping config in both validate_items and publish_items
- Batch scroll renders with requestAnimationFrame to avoid multiple DOM updates per frame
- Add will-change, contain and content-visibility CSS for smoother compositing
- Add cache-bust to virtual-scroll.js
- Add MercadoLibre OAuth, listings, orders, webhooks and category search
- New marketplace_external_bp.py, meli_service.py, marketplace_external_service.py
- New marketplace_external.html/js with ML management UI
- Inventory: bulk publish to ML with category autocomplete, listing type and shipping selectors
- Inventory: new .btn--meli styles, select/label CSS fixes
- WhatsApp bridge: rate limiting, 440/515/408 error handling, stale watchdog
- DB migration v3.4_meli_integration.sql for marketplace_listings, orders, sync_queue
- Add Celery tasks for ML sync and webhook processing
- Sidebar: MercadoLibre navigation link
Cards/Grid:
- Add min-width:0 to .device-grid to prevent grid overflow
- Add max-width:100%, overflow:hidden, word-break:break-word to .device-card
- Add min-width:0 and overflow-wrap to .device-card__body
- Bump config.css cache-bust to v=2
Onboarding:
- Add GET/POST /pos/api/config/onboarding-status endpoints in config_bp.py
- onboarding.js now checks server first before showing wizard
- On finish, POSTs completion to server (tenant_config table)
- Falls back to localStorage for fast path and offline resilience
- Bump onboarding.js cache-bust to v=2 in catalog.html
- Add min-width:0 and overflow-wrap:break-word to .device-card
- Add min-width:0 and overflow-wrap:break-word to .device-card__body
- Prevents grid items from expanding beyond their cell when content is wide
- Bump config.css cache-bust to v=2
The sidebar injected by sidebar.js is position:fixed with width:260px,
but most pages lacked margin-left on their main content, causing text
to be hidden behind the sidebar.
Affected pages:
- accounting, config, inventory, invoicing (.main)
- catalog, customers, diagrams, reports (.main-content)
Already fixed: dashboard, quotations
Not affected: fleet, whatsapp (use pos-main-offset), pos (no sidebar)
- Add 'Corte Z' button in secondary actions panel
- Add modal showing register summary before closing:
- opening amount, total sales, cash sales, change given
- cash movements in/out, cancellations, expected cash
- payment method breakdown and movement detail list
- loadCutX() fetches current register summary (read-only)
- confirmCutZ() calls POST /pos/api/register/cut-z with counted amount
- Auto-fills closing amount with expected cash
- Shows toast with difference after closing
- Resets register state to 'Sin caja abierta' after close
- Bump pos.css and pos.js cache-bust to v=3
- Add 'Open Register' modal with register number and opening amount inputs
- loadRegister now shows clickable warning when no register is open
- checkout() opens register modal instead of plain alert when no register
- Add openRegister() API call to POST /pos/api/register/open
- Expose showOpenRegisterModal, closeOpenRegisterModal, openRegister globally
- Add cache-bust query params to pos.css and pos.js
- Add GET /operations endpoint with filtering by type, pagination, date range
- Join with inventory, employees, branches for rich display
- Add tbody IDs and footer/pagination IDs to operation tables in HTML
- Add loadOperations() JS function with renderOperationRow() per type
- Integrate loadOperations into switchTab for auto-load on tab change
- Update recordPurchase/Adjustment/Transfer to refresh respective lists
- Expose loadOperations globally for HTML inline script access
- Add ID column to stock table header and renderInventoryRow
- Add 'Entrada' button on each stock row to open purchase modal pre-filled
- Show inventory ID in product detail popup
- recordPurchase: close modal, clear form, reload stats and stock list on success
- Fix colspan 11 -> 12 for empty state rows
- Expose loadInventoryStats globally so inventory.js can call it after CRUD
- Fix token key: use pos_token (not access_token) to match auth scheme
- After successful POST /items: close modal, clear form inputs, reload stats
- Bump inventory.js cache-bust query param v3 -> v4
- Add POS_INTERNAL_URL config for cross-VM API calls
- create_demo now calls POS /internal/whatsapp-bridge after tenant creation
- delete_tenant now destroys bridge container before dropping DB
- Graceful fallback if bridge provisioning fails
- Add Dockerfile.whatsapp-bridge with Baileys + env var support
- Modify whatsapp-bridge-server.js to accept PORT, TENANT_ID, WEBHOOK_BASE
- Add internal_bp.py with endpoints to provision/destroy bridges via Docker
- Register internal_bp in app.py
- Each tenant gets isolated container, port, and volume
- Refactor whatsapp_service.py to accept bridge_url parameter
- whatsapp_bp.py: remove hardcoded tenant_id=11, use g.tenant_id
- whatsapp_bp.py: webhook now accepts ?tenant_id param with fallback
- config_bp.py: add GET/PUT /config/whatsapp endpoints
- Each tenant can now have its own Baileys bridge URL and settings
- Complete Flask-based control panel for multi-tenant POS instances
- Dashboard with global stats, system health, and recent demos
- Demo provisioning in 1 click with auto-expiration tracking
- Tenant management: activate/deactivate, reset data, delete
- Health monitoring: PostgreSQL, Redis, disk, memory, systemd services
- Migration orchestration UI for running schema updates across all tenants
- JWT authentication with manager_users table
- Dark theme SPA frontend with real-time search and actions
- systemd service file included
Brand catalog now follows the same navigation as the regular catalog:
1. Brands -> 2. Models -> 3. Years -> 4. Engines -> 5. Categories -> 6. Parts
Backend:
- Add /mye-parts endpoint for MYE-specific parts with category filter
- Uses existing /models, /years, /engines, /categories endpoints
Frontend:
- Complete rewrite of brand-catalog.js with breadcrumb navigation
- State machine: brands -> models -> years -> engines -> categories -> parts
- Search and pagination preserved at parts level
- Breadcrumb allows jumping back to any previous step
Add updatefound listener in catalog.html that reloads the page
automatically when a new service worker is activated. This ensures
users get the latest HTML and JS without manual hard refresh.
- Bump cache to nexus-pos-v6 to force invalidation
- HTML pages now use network-first instead of cache-first
This ensures users always get the latest HTML with correct
JS/CSS references (?v=3) instead of stale cached HTML
- Remove HTML pages from APP_SHELL precache (only static assets)
- Keep cache-first for JS/CSS/images
- Add #brandCatalogSearch container in HTML for search inputs
- Move brand search input out of renderBrandList so it persists while typing
- Move parts search input out of renderPartsList so it persists while typing
- Reset now clears search container
- Bump JS cache bust to v=3
Update service worker cache name to nexus-pos-v5 to force cache
invalidation. Add brand-catalog.js to APP_SHELL precache list.
This should resolve stale cached JS causing parse errors.
/vehicle-brands now uses get_brands_for_mode('oem') to return the same
36 North American brands (Mexico/USA/Canada) as the regular catalog flow,
instead of all 619 brands in the database.
brand-catalog.js was missing Authorization header on fetch calls,
causing 401 Unauthorized errors. Now reads pos_token from localStorage
and includes Bearer token in every request. Also handles 401 responses
by redirecting to /pos/login. Bump JS cache bust to v=2.
Backend:
- Add 'search' param to /brand-parts endpoint (filters oem_part_number and name via ILIKE)
- Keep count query accurate with search filter
Frontend (brand-catalog.js):
- Brand search input: filters 619 brands locally while typing
- Parts pagination: Previous/Next buttons with page counter (50 per page)
- Parts search within category: search input + Enter key triggers backend search
- Visual polish: stock badges, empty-state messages, responsive layout
- Loading states and breadcrumbs improved
Remove broken location blocks for static files that had no proxy_pass,
which caused all .js/.css files to return 404 or HTML.
Add explicit /pos/static/ location with proxy_pass + cache headers.
Update nexus-pos.conf in repo to match live config.
- Add QWEN (qwen3.6) as primary AI backend with short system prompt
- Hermes remains as fallback with 45s timeout
- Increase QWEN timeout to 35s, max_tokens to 4000
- Add conversation history loading from whatsapp_messages (last 4 msgs)
- Persist detected vehicle in whatsapp_sessions table
- Add 'limpiar chat' / 'nuevo chat' / 'reset' commands to clear history
- Fix CSS conflict: rename whatsapp chat-panel classes to wa-chat-panel
- Fix JS ID conflicts with chat.js widget (waChatPanel, waChatMessages, etc.)
- Improve no-stock response: conversational with alternatives
- Split search_query by | for multi-part lookups
- Add DEMO_PROMPTS.md and DEMO_PROMPTS_V2.md
- Added save_qwen_fitment() in inventory_vehicle_compat.py to centralize
inserting QWEN results into inventory_vehicle_compat
- Simplified inventory_bp.py create_item() and auto_match_item_vehicles()
to use the centralized function, removing duplicated INSERT logic
inventory_vehicle_compat.get_compatibility was trying to JOIN tenant
inventory_vehicle_compat with master tables (model_year_engine, brands,
models, years, engines) on a single tenant connection. Those tables only
exist in the master DB, causing the query to fail silently.
Fix: split into two queries:
1. Fetch MYE IDs from tenant's inventory_vehicle_compat
2. Resolve vehicle details from master DB via ANY(%s)
3. Merge results
Also fixes the argument mismatch: inventory_bp passed (tenant, master,
item_id) but the function only accepted 2 args.
Replaced simple exact-match with 8-layer fallback strategy:
1. Exact normalized part number (parts.oem_part_number)
2. Exact normalized aftermarket part number
3. Exact normalized cross-reference number
4. Partial ILIKE match on OEM numbers
5. Partial ILIKE match on aftermarket numbers
6. Partial ILIKE match on cross-reference numbers
7. Separator-stripped fallback (KYB-343412 → KYB343412)
8. Name-based search on parts.name_part / parts.name_es
and aftermarket_parts.name_aftermarket_parts when no part_number hit
Brand-aware filtering: when brand hint is provided and not 'GENERAL',
only returns MYEs for vehicles of that brand.
Limits: max 20 part IDs per layer, max 200 MYEs total.
Test: BPR5ES + TOYOTA → matched True, 2 parts, 200 MYEs inserted.
- tenant_db.py: add rollback() before returning conn to pool to prevent
'idle in transaction (aborted)' state that exhausts the pool
- tenant_db.py: increase pool maxconn from 10 to 20 for better concurrency
- inventory_vehicle_compat.py: fix column name cross_ref_number ->
cross_reference_number to match actual schema
Nginx auto-serves .min.js when .js is requested with try_files.
The browser had the old file cached with 6M expiry. Adding ?v=2
forces clients to fetch the new version with autoMatchCompat exposed.
- catalog_bp.py: /search and /part/<id> no longer blocked by CATALOG_OEM_ENABLED
These endpoints query the master parts DB and enrich with local stock;
they should work in both local and OEM modes.
- inventory.js: expose autoMatchCompat and removeCompat to window for
onclick handlers in dynamically generated HTML.
- Regenerated inventory.min.js
- 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>
Eliminado: diagrams_bp, ruta /pos/diagrams, link en sidebar,
boton "Ver diagramas" en catalogo. Los archivos SVG y blueprint
se mantienen en el repo por si se reactivan en el futuro.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Blueprint with API endpoints: list, detail, SVG serve, vehicle-linked diagrams
- Interactive SVG viewer with zoom/pan (mouse wheel, drag, touch, keyboard)
- Clickable hotspots that highlight on hover and show part detail panel
- Parts sidebar listing all callout numbers with catalog search integration
- 3 placeholder SVG diagrams: braking system, suspension, engine components
- Seeded diagrams, hotspots, and vehicle_diagrams in DB
- Added to sidebar nav, i18n (ES/EN), and "Ver diagramas" link in catalog
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Kiosk mode: fullscreen, wake lock, auto-login, context menu block, PWA/Capacitor detection
- AI vision: camera photos analyzed by Gemma 3 27B vision model via OpenRouter
- AI part classification: auto-suggest name/brand/category when entering part number
- Public catalog chatbot: /api/chat endpoint with rate limiting, chat widget on catalog page
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Reemplaza /instance/status → /status, /instance/create → /connect, etc.
Lee QR de data.qr (formato del bridge) ademas de data.base64 (Evolution).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Reemplaza Evolution API con bridge Node.js propio usando Baileys.
QR se genera en ~10 segundos. Auto-reply con chatbot IA.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Switch from Meta Business Cloud API to Evolution API for WhatsApp integration.
Evolution API is self-hosted, free, and connects via WhatsApp Web QR code scan.
- Add docker-compose for Evolution API deployment
- Rewrite whatsapp_service.py for Evolution API endpoints
- Add instance management (create, QR, status, logout) to blueprint
- Add QR code scanning UI with connection status indicator
- Add duplicate message prevention in webhook handler
- Update config.py with EVOLUTION_API_URL/KEY (remove old Meta vars)
- Add setup documentation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Demo/sample rows in HTML tables were visible on first render before JS
populated real data. Replaced all hardcoded tbody rows and finance cards
with empty containers that JS populates from API on load.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- i18n.js with 130+ translation keys for es/en, loaded in all 11 templates
- sidebar.js uses t() for all nav labels, adds MX/US language toggle
- app-init.js role labels use i18n
- currency.py service with convert() and format_currency()
- config.py adds DEFAULT_CURRENCY and EXCHANGE_RATE_USD_MXN settings
- config_bp.py adds GET/PUT /pos/api/config/currency endpoints
- config.html adds currency/exchange-rate section (Section 8)
- config.js adds loadCurrency/saveCurrency with localStorage sync
- pos.js fmt() reads pos_currency from localStorage for USD/MXN display
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Gunicorn production server with auto-scaled workers, run.sh, updated systemd service
- Marketplace B2B: cross-tenant inventory search, ordering, seller management with full UI
- Subscription billing: plan limits enforced on products/employees/branches, billing API + upgrade flow
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add thermal_printer.py service generating raw ESC/POS bytes for 58mm/80mm printers
- Add /pos/api/sales/<id>/print endpoint (escpos_raw or browser mode)
- Add printer.js with WebUSB and Web Serial support for direct browser-to-printer
- Add thermal print button in ticket modal with connect/print workflow
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Chat now fetches tenant inventory summary (brands, counts, low-stock)
and injects it into the AI system prompt so responses prioritize local
stock. VIN decoder uses free NHTSA vPIC API to decode 17-char VINs and
auto-fills the vehicle selector dropdowns when a catalog match is found.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1. Spanish translations for TecDoc catalog (translations.py) applied to
catalog_service.py and dashboard server.py endpoints
2. Printable quotation HTML endpoint (/pos/api/quotations/<id>/pdf) with
@media print CSS for clean browser-to-PDF output
3. Web Push notifications to owner/admin on sale cancellation, stock zero,
and cash register differences > $500. Includes service worker, VAPID
key management, and subscription endpoints.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1. Auto dark mode: detect system prefers-color-scheme, auto-switch industrial/modern theme
2. Email quotation endpoint: POST /quotations/:id/email sends HTML email via SMTP
3. Camera barcode scanner: BarcodeDetector API with getUserMedia overlay in catalog
4. Returns with warranty: POST /returns endpoint with stock restoration and sale status tracking
5. Partial offline catalog: cache top 500 parts in IndexedDB, search when offline
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1. Symptom diagnosis: AI now detects vehicle symptoms and suggests probable parts
2. Smart quotations: "cotizame frenos completos" returns multiple search_queries (pipe-separated), backend searches each term and deduplicates
3. Photo identification: camera button in chat widget uploads image and sends placeholder prompt (ready for vision model)
4. Multilanguage: AI detects user language and responds accordingly, search_query always in English
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Build debug APK (8.3MB) con Capacitor + Android SDK 34.
Carga desde nexus.consultoria-as.com/pos con PWA offline.
Incluye plugins: camera, push notifications, haptics, status bar.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Set up Capacitor to wrap the Nexus POS web app as a native mobile app.
The app loads from the remote server URL so no bundling is needed.
Includes native-bridge.js for camera, push notifications, haptics,
and status bar integration when running inside the native shell.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add full fleet management (Feature 13): database migration for fleet_vehicles,
fleet_maintenance_schedules, and fleet_maintenance_logs tables; REST API blueprint
with CRUD, scheduling, logging, alerts, and stats endpoints; frontend with tabbed
UI (vehicles grid, maintenance schedules, history, overdue alerts); sidebar nav entry.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add full WhatsApp Cloud API integration for Nexus POS:
- Service layer (whatsapp_service.py): send text, templates, quotations,
order confirmations, stock alerts; process incoming webhooks with AI auto-reply
- Blueprint (whatsapp_bp.py): public webhook endpoints for Meta verification +
incoming messages; authenticated endpoints for send, send-quote, conversations
- Conversation UI (whatsapp.html + whatsapp.js): split-panel messenger with
conversation list, chat bubbles, send input, quote sending; both themes
- Migration v1.4: whatsapp_messages table with phone/direction/status indexes
- Config: WHATSAPP_TOKEN, WHATSAPP_PHONE_ID, WHATSAPP_VERIFY_TOKEN env vars
- Sidebar: WhatsApp nav item under Gestion with message-bubble icon
- Ready for Meta Business credentials (infrastructure complete, no API keys needed)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add POST/DELETE /items/{id}/image endpoints with Pillow processing (resize 800px, thumbnail 300px, JPEG 85%)
- Validate file type (jpg/png/webp) and size (max 5MB)
- Show image in product detail modal with upload/delete buttons
- Enrich catalog parts list with local inventory image when available
- Image directory created automatically on first upload (pos/static/images/parts/)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace static demo data with live API calls across all four report tabs:
- Ventas: sales by period/employee/payment method with date filters
- Inventario: valuation, ABC classification, low stock, no movement
- Clientes: accounts receivable aging report
- Financieros: income statement, balance sheet, trial balance, register history
All tabs use lazy loading (fetch on first visit) and JWT auth.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace all hardcoded/demo data with live API calls:
- KPIs from /pos/api/register/daily-summary (ventas, tickets, promedio, cajas)
- Inventory alerts from /pos/api/inventory/alerts (zero, low, over stock)
- Top products aggregated from /pos/api/sales detail items
- Weekly bar chart from 7-day daily summaries
- Recent sales table with real items from sale detail endpoint
- Auto-refresh every 2 minutes, manual refresh button
- Dynamic greeting with time-of-day and JWT user name
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace hardcoded demo data in the config page with real API calls.
Branches and employees now load from /pos/api/config/* endpoints,
with create modals for both. Business data tab reads tenant_config
(read-only). Theme selector was already working and is preserved.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Proxy was using resp.raw.headers (urllib3) which could miss Content-Type;
switched to resp.headers. SW now skips /pos/api/auth/ to prevent stale
token caching, scopes fetch to /pos/ only, and bumps cache to v2.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
3 reintentos con espera 5s/10s/15s. Si agota reintentos,
muestra mensaje amigable en vez de error.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
El servidor principal proxea /pos/* al POS en puerto 5001.
Elimina la necesidad de exponer puerto 5001 a internet.
Botones "Acceder al POS" en landing ahora usan /pos/login (mismo dominio).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Manejo de historial con pushState/popState. Cada nivel de navegacion
se registra en el historial del navegador. El boton atras regresa al
nivel anterior en vez de salir del catalogo.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remueve codigos de generacion, numeros romanos, tipos de carroceria.
Deduplica por display_name. Toyota: 236 → 73 modelos limpios.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- catalog.js: state → nav (variable correcta del catalogo)
- vsClearAll: resetea nav en vez de state inexistente
- favicon.ico: sirve icon-192.png del PWA
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Al seleccionar ano, solo muestra marcas/modelos disponibles para ese ano.
Toyota 2020: 92 modelos vs 625 sin filtro.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Validacion _validate_model() verifica que el modelo termine en ':free'.
Si alguien cambia MODEL a uno de pago, el chatbot lanza error en vez
de generar costos. Alternativas documentadas en comentario.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Barra de 4 dropdowns arriba del catalogo que se habilitan en cascada.
Al completar los 4, muestra categorias y partes para ese vehiculo.
Boton de limpiar para resetear. Endpoint /years-all para cargar anos.
Estilos con design system tokens (ambos temas).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
El chatbot ahora busca primero en el inventario local del tenant
y luego en el catalogo TecDoc. Resultados muestran badge:
- Verde "MI INVENTARIO" para partes locales
- Azul "CATALOGO" para partes del catalogo TecDoc
Busqueda local funciona en español e inglés.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Al abrir el detalle de un producto, se cargan automaticamente:
- Disponibilidad en bodegas (stock + precio)
- Partes equivalentes aftermarket (cross-references del catalogo TecDoc)
Usa catalog_part_id o busqueda por part_number contra el catalogo central.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- System prompt: SIEMPRE devuelve search_query en ingles
- Diccionario de traducciones (balatas→Brake Pad, etc.)
- Busca directo sin preguntar mas info
- Fallback: extrae keywords si AI no da search_query
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- FAB movido a bottom:140px (arriba del carrito)
- Panel a bottom:200px
- Fondo usa --color-bg-elevated (opaco, no transparente)
- Bubbles usan --color-surface-2 con fallback
- Variables CSS inexistentes reemplazadas con equivalentes de tokens.css
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Subdominio desconocido ya no redirige a dominio externo. En su lugar,
continua sin tenant y el login pide el tenant manualmente.
Agregados 'nexus', 'pos', 'app', 'dashboard' a subdominios reservados.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Nginx wildcard config: *.nexusautoparts.com routes to POS app with X-Tenant-Subdomain header
- middleware_tenant.py: resolves subdomain -> tenant_id via nexus_master.tenants.subdomain
- auth_bp: login and employee list endpoints accept tenant from subdomain, URL param, or body
- login.html: auto-detects tenant from subdomain, shows business name, falls back to ?tenant=ID
- tenant_manager: generates subdomain slug from business name on provision_tenant()
- Migration v1.2: adds subdomain column + unique index to tenants table
- setup-nginx.sh: one-command install script for the nginx config
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds install.sh and uninstall.sh for one-command deployment of Nexus POS
on Debian 12+, Ubuntu 22.04+, and Raspberry Pi OS. The installer handles
PostgreSQL setup, tenant provisioning, systemd service, and nginx reverse
proxy with interactive business configuration.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Filtra marcas por mercado regional. 4 opciones:
- Mexico/USA/Canada (36 marcas)
- Europa (27 marcas)
- Asia (15 marcas)
- Todos (546 marcas)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Removidas paginas viejas (demo, tienda, admin, pos, captura, cuentas).
Nueva landing page con estilo del design system (tokens.css, 2 temas).
Catalogo publico sin auth con navegacion Marca>Modelo>Ano>Motor>Categoria>Partes.
Endpoints /api/catalog/* publicos con filtro NORTH_AMERICA_BRANDS (36 marcas).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Contabilidad: Nueva Poliza modal + Exportar placeholder
- Facturacion: Nueva Factura modal (sale_id input) + Nota Credito placeholder
- Inventario: click en producto abre detalle con historial
- Dashboard: Ver Detalles navega a paginas relevantes, campana a alertas
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Eliminadas marcas de otros mercados (China, Australia, etc.)
Solo se muestran las relevantes para Norteamerica.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
vehicle_parts tiene 14B+ rows. Las queries de brands, models, years,
engines ahora solo usan model_year_engine (mucho mas rapido).
vehicle_parts solo se consulta para categories/groups/parts donde
se filtra por un mye_id especifico.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Catalog redesign: TecDoc hierarchical navigation
(Brand→Model→Year→Engine→Category→Parts) with local stock +
bodega availability + aftermarket alternatives. Offline fallback
to local inventory.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Chips de filtro se cargan desde API /catalog/brands
- Muestran marcas reales (Bosch, KYB, NGK...) con conteo
- Boton 'Todos' para quitar filtro
- Filtrado por brand via API en vez de category_id
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Reescrito sidebar.js para coincidir exactamente con el design system:
- Logo NA con clip-path en tema industrial, border-radius en moderno
- Secciones: Principal, Gestion, Sistema
- SVG icons de Feather (mismo trazo 1.75px)
- Border-left accent en item activo
- Toggle de tema con iconos luna/sol
- Footer con avatar, nombre, rol, y boton logout
- 260px width, colapsa a 56px en mobile
- Usa CSS variables del tokens.css
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Script inline en <head> aplica el tema guardado ANTES de que
el CSS se renderice. Elimina el flash blanco→oscuro o viceversa.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- app-init.js: aplica tema guardado en localStorage, oculta theme-bars
que tapaban contenido (position:fixed), sobrescribe setTheme() de
cada pagina para usar version persistente
- sidebar.js: toggle de tema (sol/luna) integrado en el sidebar
- Tema se mantiene al navegar entre paginas
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Nuevo sidebar.js compartido que reemplaza el sidebar de cada pagina
con una version consistente:
- Misma estructura y orden de links en todas las paginas
- Nombre y rol del empleado real (de POS_USER)
- Link activo resaltado segun pagina actual
- Boton de logout
- Responsive (colapsa a iconos en <768px)
- Elimina inconsistencias de estilo entre paginas
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Reemplazados todos los href="#" en nav-items y nav-links con
las rutas reales (/pos/dashboard, /pos/sale, /pos/catalog, etc.)
en catalog, inventory, customers, dashboard, config, reports.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Nuevo app-init.js: auth check, inyecta nombre/rol real del empleado
en sidebar, header, y status bar de TODAS las páginas
- Eliminados 6 productos demo hardcodeados del catálogo
- Sidebar muestra nombre real del usuario logueado
- Links de navegación marcan la página activa correctamente
- Función posLogout() global para cerrar sesión
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Nuevo endpoint GET /pos/api/auth/employees/<tenant_id>
- Login carga empleados dinamicamente del tenant
- Si hay 1 solo empleado, se auto-selecciona
- Removidos 6 usuarios hardcodeados del design system
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Invoicing JS now targets panel-facturas/notas/complementos/cancelaciones/config
panels, modalDetalleOverlay/modalCancelOverlay modals, and switchTab() calls.
Loads CFDI queue data dynamically into data-table tbodies replacing demo rows.
Accounting JS now targets panel-cxc/cxp/balance/resultados/flujo/conciliacion/cierre
panels and finance-card elements. Wires aging, balance sheet, income statement,
and period close to real API endpoints.
Both files include auth check, live clock, and global switchTab binding.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Reemplaza enlaces del design system (dashboard.html, pos.html, etc.)
con rutas reales del POS (/pos/dashboard, /pos/sale, etc.).
Limpia archivos backup.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 07:52:03 +00:00
574 changed files with 131816 additions and 26457 deletions
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.