From 2ac9b90afcd39734450b8bdfcffdb7e1ce055c7d Mon Sep 17 00:00:00 2001 From: consultoria-as Date: Wed, 1 Apr 2026 21:22:55 +0000 Subject: [PATCH] docs: add catalog vehicle navigation design spec MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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) --- .../2026-04-01-catalog-vehiculo-design.md | 211 ++++++++++++++++++ 1 file changed, 211 insertions(+) create mode 100644 docs/plans/2026-04-01-catalog-vehiculo-design.md diff --git a/docs/plans/2026-04-01-catalog-vehiculo-design.md b/docs/plans/2026-04-01-catalog-vehiculo-design.md new file mode 100644 index 0000000..dac2066 --- /dev/null +++ b/docs/plans/2026-04-01-catalog-vehiculo-design.md @@ -0,0 +1,211 @@ +# Catálogo POS con Navegación por Vehículo — Design Spec + +**Date:** 2026-04-01 +**Status:** Approved +**Goal:** Rediseñar el catálogo del POS para navegar el catálogo TecDoc completo (1.5M+ partes) por vehículo (Marca → Modelo → Año → Motor → Categoría → Subcategoría → Partes), mostrando stock local + stock de bodegas + alternativas aftermarket. + +--- + +## 1. Arquitectura + +### Dos fuentes de datos + +- **nexus_autoparts DB** (servidor central): catálogo TecDoc (brands, models, years, engines, model_year_engine, part_categories, part_groups, parts, vehicle_parts, part_cross_references, aftermarket_parts, warehouse_inventory) +- **tenant DB** (por refaccionaria): inventario local (inventory, inventory_operations) + +El catalog_bp.py consulta ambas DBs. Para nexus_autoparts usa una conexión directa (misma máquina). Para el tenant usa get_tenant_conn() existente. + +### Flujo de navegación + +``` +Marca (619) → Modelo (13K) → Año (78) → Motor (30K MYE) → Categoría (36) → Subcategoría (493) → Partes + ↓ + Panel lateral: + - Stock local + - Stock bodegas + - Alternativas + - [Agregar al carrito] +``` + +### Conexión entre tablas + +``` +brands → models (brand_id) → model_year_engine (model_id + year_id + engine_id) + ↓ + vehicle_parts (model_year_engine_id) + ↓ + parts (id_part) → part_groups (group_id) → part_categories (category_id) + ↓ + part_cross_references + aftermarket_parts (alternativas) +``` + +--- + +## 2. Endpoints (9 total) + +Todos bajo `/pos/api/catalog/`. Requieren auth JWT del tenant. + +### Navegación jerárquica + +**GET /pos/api/catalog/brands** +- Source: nexus_autoparts.brands +- Response: `{data: [{id_brand, name_brand}]}` ordenado alfabéticamente +- Solo marcas que tienen model_year_engine con partes vinculadas + +**GET /pos/api/catalog/models?brand_id=X** +- Source: nexus_autoparts.models WHERE brand_id = X +- Response: `{data: [{id_model, name_model}]}` + +**GET /pos/api/catalog/years?model_id=X** +- Source: nexus_autoparts.model_year_engine JOIN years WHERE model_id = X +- Response: `{data: [{id_year, year_car}]}` ordenado DESC (más reciente primero) +- Solo años que tienen MYE entries para ese modelo + +**GET /pos/api/catalog/engines?model_id=X&year_id=Y** +- Source: nexus_autoparts.model_year_engine JOIN engines WHERE model_id AND year_id +- Response: `{data: [{id_mye, name_engine, trim_level}]}` + +**GET /pos/api/catalog/categories?mye_id=X** +- Source: nexus_autoparts.vehicle_parts JOIN parts JOIN part_groups JOIN part_categories WHERE mye_id +- Response: `{data: [{id_part_category, name_part_category, part_count}]}` +- Solo categorías que tienen partes para ese vehículo + +**GET /pos/api/catalog/groups?mye_id=X&category_id=Y** +- Source: nexus_autoparts.vehicle_parts JOIN parts JOIN part_groups WHERE mye_id AND category_id +- Response: `{data: [{id_part_group, name_part_group, part_count}]}` + +### Partes con disponibilidad + +**GET /pos/api/catalog/parts?mye_id=X&group_id=Y** +- Source: nexus_autoparts (partes) + tenant DB (stock local) +- Para cada parte: + 1. Datos base de nexus_autoparts.parts + 2. Stock local: busca en tenant_db.inventory WHERE part_number = oem_part_number OR catalog_part_id = part_id + 3. Indicador de disponibilidad en bodegas (count de warehouse_inventory con stock > 0) +- Response: `{data: [{id_part, oem_part_number, name_part, description, local_stock, local_price, bodega_count}]}` +- Paginado (default 30 per page) + +**GET /pos/api/catalog/part/\** +- Source: nexus_autoparts + tenant DB + warehouse_inventory +- Response detallada: + ```json + { + "part": {id, oem_part_number, name_part, description, image_url, group_name, category_name}, + "local": {stock, price_1, price_2, price_3, inventory_id} | null, + "bodegas": [{business_name, price, stock, location}], + "alternatives": [{part_number, manufacturer, name, local_stock, bodega_count}] + } + ``` +- Alternativas: busca en part_cross_references + aftermarket_parts para el mismo part_id + +### Búsqueda inteligente + +**GET /pos/api/catalog/search?q=...** +- Lógica: + - Si q contiene números + guiones (regex `\d.*-|-.* \d`): busca en parts.oem_part_number ILIKE + - Si es texto: busca en parts.name_part ILIKE + parts.description ILIKE +- Enriquece con stock local del tenant +- Response: `{data: [{id_part, oem_part_number, name_part, local_stock, local_price, vehicle_info}]}` +- vehicle_info: obtiene marca+modelo del primer vehicle_parts match +- Límite: 50 resultados + +--- + +## 3. UI del Catálogo + +### Layout principal + +- Barra superior: búsqueda inteligente + botón carrito con badge +- Breadcrumb de navegación (click para regresar a cualquier nivel) +- Área principal: cards/lista según el nivel de navegación +- Panel lateral derecho: detalle de parte seleccionada (slide-in) +- Banner inferior: status de conexión (online/offline) + +### Niveles de navegación + +1. **Marcas**: grid de cards con nombre (logo futuro). Filtro de texto rápido +2. **Modelos**: lista filtrable con búsqueda inline +3. **Años**: botones horizontales ordenados DESC +4. **Motores**: cards con nombre del motor y trim +5. **Categorías**: cards con nombre y conteo de partes +6. **Subcategorías**: cards con nombre y conteo +7. **Partes**: grid de cards con OEM, nombre, marca, badge de stock (verde/amarillo/rojo/gris) + +### Badges de stock en lista de partes + +- ✅ Verde: hay stock local +- ⚠️ Amarillo: sin stock local pero hay en bodegas +- ❌ Rojo: sin stock en ningún lado (pero hay alternativas) +- ⬜ Gris: no disponible en absoluto + +### Panel lateral de detalle + +Al clickear una parte: +- Nombre completo, número OEM, descripción +- **Mi stock**: cantidad + precio (price_1/2/3 según tier del cliente seleccionado) +- **En bodegas**: tabla de bodegas con stock y precio +- **Alternativas** (si sin stock local ni bodegas): lista de cross-references con su disponibilidad +- Selector de cantidad + **botón "Agregar al carrito"** +- Selector de fuente: "De mi stock" o "Pedir a bodega X" (si no tiene local) + +### Carrito + +- Mismo carrito que ya existe (localStorage) +- Al agregar, indica la fuente (local o bodega) +- "Ir a cobrar" → POS con carrito pre-cargado + +### Breadcrumb + +``` +Inicio > Toyota > Corolla > 2020 > 1.8L 4cyl > Frenos > Pastillas +``` +Click en cualquier nivel navega de regreso. + +### Búsqueda inteligente + +- Un campo único arriba +- Al escribir, detecta si es número de parte o texto +- Resultados en dropdown con: OEM, nombre, vehículo compatible +- Click en resultado abre el panel lateral directamente + +--- + +## 4. Modo offline (fallback) + +- Cuando las llamadas a `/pos/api/catalog/brands` fallan (timeout o error de red): + - Muestra banner "Modo offline — mostrando solo tu inventario" + - Cambia a modo inventario local (grid plano del inventario del tenant) + - Búsqueda funciona solo contra inventario local + - Carrito sigue funcionando normalmente +- Cuando regresa la conexión: + - Auto-detecta (fetch periódico o evento online) + - Restaura navegación TecDoc completa + - Quita banner offline + +--- + +## 5. Estilo visual + +- Usa tokens.css existente (ambos temas: industrial y modern) +- Mismo sidebar compartido (sidebar.js) +- Cards de navegación usan componentes existentes del design system +- Panel lateral usa el componente panel-deslizante del design system +- Badges de stock usan los colores semánticos (--color-success, --color-warning, --color-error) +- Responsive: sidebar colapsa en mobile, panel lateral se convierte en modal + +--- + +## 6. Archivos a modificar/crear + +### Backend +- **Reescribir**: `/home/Autopartes/pos/blueprints/catalog_bp.py` — 9 endpoints nuevos +- **Crear**: `/home/Autopartes/pos/services/catalog_service.py` — lógica de consulta a nexus_autoparts + enriquecimiento con stock local + +### Frontend +- **Reescribir**: `/home/Autopartes/pos/templates/catalog.html` — nueva UI con navegación jerárquica +- **Reescribir**: `/home/Autopartes/pos/static/js/catalog.js` — lógica de navegación, búsqueda, panel lateral, carrito + +### Sin cambios +- app.py (ruta /pos/catalog ya existe) +- sidebar.js, app-init.js, tokens.css (compartidos, sin cambios) +- Otros blueprints y páginas (sin impacto)