# Art4Hotel Hub — Contexto del proyecto Sistema interno de operaciones para Clod (bolsas/accesorios custom, Los Cabos). Última actualización mayor: 2026-05-31 ## Stack - **Backend**: Python 3 stdlib HTTP server + SQLite (WAL, FK on) - **Frontend**: SPA vanilla JS, sin frameworks (`index.html` ~9000 líneas) - **Deploy**: `claude@192.168.50.46:/mnt/iclaude/art4hotel-hub/` puerto 4401 - **Acceso**: red local `192.168.50.46:4401` · Tailscale `100.110.177.1:4401` - **Deploy cmd**: `scp index.html server.py claude@192.168.50.46:/mnt/iclaude/art4hotel-hub/ && ssh claude@192.168.50.46 "sudo systemctl restart art4hotel-hub"` ## Modelo de datos (SQLite) `ordenes` (pedidos/líneas de producción), `oc` (orden de compra que agrupa pedidos), `productos` (catálogo), `proyectos` (recetas recurrentes), `propuestas` (cotizaciones), `catalogos` (presentaciones PDF), `clientes`, `trabajos`, `modelos`, `materiales`, `inventario`, `tareas`, `bitacora`. CRUD genérico: dict `TABLES` en server.py define fields/int_fields/float_fields/nullable_fields por tabla; un solo handler maneja POST/PUT/DELETE de todas. ## Conceptos clave - **Pedido** (`ordenes`) = línea de producción individual - **Orden (OC)** (`oc`) = agrupa pedidos, lleva factura/cobranza - **Proyecto recurrente** (`proyectos`) = receta autorizada (cliente+producto+trabajo+logo) - **Propuesta** → al aceptarse, botón "Convertir a Orden" crea OC + N pedidos (`oc.propuesta_id`) - **tipo_orden**: OC / Resurtido / Muestra / Defecto / Faltante - **Bodega**: *Con orden* (hoteles, facturable) vs *Sin orden* (resurtido/POS libre) - **Stages**: Nuevo → En 2 Mares / En Taller Sofía → En Almacén → En Vehículo → Entregado ## Producto — modelo unificado (editor de 4 secciones) El producto es la **fuente única de verdad**. Editor `openProductoEdit` organizado por impacto: - **📋 Identidad** (catálogo·web·cotizador): nombre, categoría, talla, medidas, material, `descripcion_web` - **🎨 Personalización** (cotizador·web): `tipos_trabajo_disponibles` (CSV multi-select) — al cotizar SOLO aparecen estos - **⚙️ Operación** (producción·inventario): sku (no editable), costo_base, proveedor, stock_actual, punto_reorden - **🌐 Publicación**: `mostrar_en_web` Quickview `openProductoView` = visual read-only + botón Editar (ARRIBA de la galería) + galería de ejemplos. ### ⚠️ PRINCIPIO: cada atributo de producto impacta hasta 3 funciones Al agregar/cambiar un atributo de producto, **definir su impacto en las 3 antes de implementar**: 1. **Operación / flujo de producción** (kanban, inventario, costos) 2. **Catálogo / cotizador** (propuestas, catálogo PDF) 3. **Página web** (sync a art4hotel.com) Ejemplo: agregar "uso" (boda/empresa/hotel) → afecta filtros web + tal vez segmentación de cotización. ### Campos legacy (en DB, retirados del editor) `color` (datos sucios), `logo_diseno` (pertenece a proyecto/pedido), `modelo` (vacío), `tipo_personalizacion` (ya migrado → `tipos_trabajo_disponibles`). Pendiente: limpieza con script. ## Galería de ejemplos (base + personalización) - Un producto base muestra "cómo se ha personalizado" = pedidos (`ordenes`) con foto cuyo `producto` coincide por nombre. - Curaduría por ejemplo: `ordenes.web_ejemplo` (1=va a web) + `ordenes.web_etiqueta` (etiqueta PÚBLICA: zona/"muestra", **nunca el cliente real** — protege la cartera). - `getEjemplosDeProducto(nombre)` calcula en cliente desde S.ordenes + fileIndex. ## Archivos / fotos - Guardados en `uploads/{entidad}/`, prefijo del tipo en el nombre: `factura_`, `foto_avance_produccion_`, `foto_producto_base_`, `recibo_entrega_`, etc. - **El prefijo es crítico**: `/api/file-counts` lo usa para elegir `first_image` PREFIRIENDO fotos (`foto_`/`mockup`) y EXCLUYENDO documentos (`factura`,`recibo`,`comprobante`,`soporte`,`contrato`,`propuesta`). - Subida con **etiqueta opcional**: `?tipo=X&label=...` → nombre `{tipo}_{ts}_{label}` (prefijo siempre se conserva). Sugerencia automática según tipo+contexto (`suggestFileLabel`). ## Catálogos (Propuestas → 📚 Catálogos) - Tabla `catalogos`: nombre, segmento, cliente_nombre, fecha, items(JSON), show_prices/show_clientes/show_contacto, entrega, minimo_compra, terminos, status. - Builder: picker de Productos / Proyectos / Pedidos-con-foto. Items guardan snapshot + **rehidratación** (`catRehydrateItem`) al abrir → refresca datos vivos del producto, conserva `precio_unit` manual. - Precio unitario **editable inline** por item (vacío = no se muestra). - PDF: portada (logo oficial centrado) → grids 2 productos/página → pie con términos comerciales (entrega·mínimo) + contacto toggleable en cada página. - Imprimir: `catPrintCatalog()` agrega clase `cat-printing` al body → `@media print` A4 vertical. ## Ventas (tab unificada) Sub-vistas: 📊 Dashboard (KPIs, comparativo mes/mes-pasado/año-pasado, top clientes, tiempos de ciclo, pricing por producto) · 📋 Por OC (kanban cobranza) · 📦 Por Entregas (panel "En Vehículo" + histórico). ## Marca / estilo UI - Fuentes: **Outfit** (cuerpo) + **Playfair Display Italic** (display) + **DM Sans** (labels) - Colores: olivo `#5C6B4F`, olivo-osc `#3D4A33`, café `#6B4F3C`, arena `#D4C5A9`, crema `#FAF7F0` - Constantes canónicas: `TRABAJO_OPTS`, `CONDICIONES_PAGO_OPTS`, `PRODUCTO_CATEGORIAS` - Nav: tabs en desktop, dropdown en móvil (≤700px) ## Optimizaciones - `/api/file-counts` batched (1 request) con first_image inteligente - Imágenes `loading="lazy" decoding="async"`, kanban/bodega sin thumbs por default - IDs con `MAX(num)+1` (no count) — evita colisiones ## Endpoints - `GET/POST/PUT/DELETE /api/{table}` - `GET /api/file-counts` → `{entity: {count, first_image}}` - `GET /api/ventas` → dashboard analytics - `POST /api/upload/{id}?tipo=X&label=Y` · `GET /api/files/{id}` · `DELETE /api/files/{id}/{name}` ## Backup - `backup.py` por cron: snapshot DB (online backup, safe c/ WAL) + `uploads.tar.gz`, 30 días en `backups/` - Backups manuales antes de migraciones: `cp art4hotel.db art4hotel.db.bak__` ## Pendientes (al 2026-05-31) - **Web**: filtros por uso (boda/empresa/tienda/hotel — requiere atributo "uso") + secciones por tipo · foto base del modal de producto web recorta en cuadrado · analytics - **Limpieza DB**: retirar columnas legacy (color, logo_diseno, modelo, tipo_personalizacion) - **Operación**: limpieza de campos de pedido poco usados · distinguir 3 paths visualmente ## Sitio web público → ver WEB.md art4hotel.com (GitHub Pages) se alimenta del Hub vía `sync_catalogo.py`. Detalle en `WEB.md`.