- 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
- 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
- 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
- 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
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.
- 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
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.
- 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
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.
- 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
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>