ERP a la medida (Python stdlib + SQLite + vanilla JS SPA). Incluye server.py, index.html, utilidades y documentación: README, MODELO_DATOS, API, INSTALACION, CONTEXTO, NEGOCIO, WEB, ONBOARDING, VALOR_SISTEMA, CLAUDE. Secretos y datos (art4hotel.db, secret.key, ACCESOS.html, uploads/, backups/) excluidos vía .gitignore. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
6.5 KiB
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· Tailscale100.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:
- Operación / flujo de producción (kanban, inventario, costos)
- Catálogo / cotizador (propuestas, catálogo PDF)
- 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 cuyoproductocoincide 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-countslo usa para elegirfirst_imagePREFIRIENDO 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, conservaprecio_unitmanual. - 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 clasecat-printingal body →@media printA4 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-countsbatched (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 analyticsPOST /api/upload/{id}?tipo=X&label=Y·GET /api/files/{id}·DELETE /api/files/{id}/{name}
Backup
backup.pypor cron: snapshot DB (online backup, safe c/ WAL) +uploads.tar.gz, 30 días enbackups/- Backups manuales antes de migraciones:
cp art4hotel.db art4hotel.db.bak_<motivo>_<fecha>
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.