Art4Hotel Hub: código + documentación extensiva

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>
This commit is contained in:
consultoria-as
2026-06-09 00:10:07 -07:00
commit c2ae140078
16 changed files with 12675 additions and 0 deletions

93
CONTEXTO.md Normal file
View File

@@ -0,0 +1,93 @@
# 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_<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`.