Files
catalogo-servicios/CLAUDE.md
consultoria-as 38e9e4b91c Catalogo de Servicios (builder): codigo + documentacion extensiva
Builder multi-proveedor de servicios (tour / A&B / transportacion).
Python stdlib + SQLite + vanilla JS SPA. Hereda filosofia del Hub.

Secretos y datos (catalogo.db, secret.key, uploads/) excluidos via .gitignore.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 21:00:50 -07:00

6.6 KiB

Catálogo (borrador) — Contexto para Claude

Builder de catálogo multi-proveedor de servicios (no productos físicos). Hereda la filosofía del Art4Hotel Hub. Proyecto independiente, no toca el Hub.

Qué es

Sistema interno para armar la base de datos de un catálogo de servicios de varios touroperadores / proveedores. Tres tipos de servicio:

  • tour · ayb (A&B / banquetes) · transportacion

Objetivo final (fases siguientes): usar esta DB para propuestas y una página web de catálogo online optimizado. Por ahora el foco es el builder (captura de datos + fotos).

⚠️ Principio clave (del Hub): el servicio = fuente única de verdad

Cada atributo de un servicio impacta hasta 3 funciones. Antes de agregar/cambiar uno, define su impacto en:

  1. Operación — disponibilidad, horarios, capacidad, precio neto
  2. Propuesta / cotizador — lo que ve el cliente, precio público, términos
  3. Página web — catálogo online

Neto vs público: precio_neto = lo que cobra el proveedor · precio_publico = lo que paga el cliente. El margen vive en medio y nunca se mezcla con lo que ve el cliente.

Stack

  • Backend: Python 3 stdlib (http.server + sqlite3), zero deps. WAL + FK on.
  • Frontend: SPA vanilla JS (index.html), sin frameworks.
  • CRUD genérico vía dict TABLES en server.py (un solo handler POST/PUT/DELETE para todas las tablas).
  • Auth: usuario/contraseña (PBKDF2) + cookie de sesión firmada (HMAC). needs_setup en primer acceso.

Acceso al server

  • Host: claude@100.110.177.1 (Tailscale iclaude) / red local 192.168.50.46
  • Path: /mnt/iclaude/catalogo-borrador/
  • Puerto: 4403 (4401 = Hub, 4402 = airbnb-pricing)
  • URL: http://iclaude:4403 / http://192.168.50.46:4403
  • Servicio: sudo systemctl restart catalogo-borrador
  • Deploy: scp index.html server.py claude@100.110.177.1:/mnt/iclaude/catalogo-borrador/ && ssh claude@100.110.177.1 "sudo systemctl restart catalogo-borrador"
  • Logs: sudo journalctl -u catalogo-borrador -n 50 --no-pager

Modelo de datos (SQLite)

  • proveedores — quién ofrece (nombre, tipo_principal, contacto, comision_default, …)
  • serviciosfuente única de verdad (FK proveedor_id). Campos por sección de impacto:
    • 📋 Identidad: nombre, tipo, categoria, codigo, descripcion
    • ⚙️ Operación: horarios, capacidad_min/max, restricciones + atributos (JSON específico por tipo)
    • 💰 Comercial: precio_neto, precio_publico, moneda, unidad, tarifas_adicionales
    • 📄 Condiciones: terminos
    • 🌐 Publicación: mostrar_en_web
  • usuarios — auth

Atributos flexibles por tipo (servicios.atributos, JSON)

En vez de columnas rígidas, los extras específicos van en JSON. Sugeridos por tipo (en index.htmlATRIBUTOS):

  • tour: duracion, punto_encuentro, incluye, no_incluye, idioma
  • ayb: tipo_menu, min_personas, montaje, servicio_incluido, opciones_dieta
  • transportacion: tipo_vehiculo, pasajeros, ruta_zona, chofer, tiempo_espera

Disponibilidad — modos (servicios.modo_disponibilidad + horarios JSON)

Eje independiente del tipo. modo_disponibilidad: salidas | rango | siempre (24/7) | por_evento. Default sugerido por tipo (MODO_DEFAULT: tour→salidas, transportacion→siempre, ayb→por_evento), editable. El editor (renderDisp) cambia los controles según el modo:

  • salidas: editor semanal de días + varias salidas por día → horarios={"Lun":["08:00","14:00"],...}. (+ salida agrega varias; parseHor/fmtHorGroups/compactDias para mostrar.)
  • rango: días + ventana → horarios={"dias":[...],"desde":"06:00","hasta":"22:00"}.
  • siempre / por_evento: horarios={} (sin horario; la reserva es por fecha). dispShort(s) arma el texto de disponibilidad según el modo (usado en vista cliente). Compat: servicios viejos sin modo = salidas con su horarios día-keyed.

Alimentos / Menú (opcional, flexible)

servicios.incluye_alimentos (0/1) + menu_detalle (texto). Fotos del menú: se suben con tipo=menu (prefijo menu_) al mismo uploads/servicio_{id}/; se separan de las fotos del servicio por prefijo (loadPhotos excluye menu_, loadMenuFotos solo menu_). En file-counts el prefijo menu está excluido del first_image (no roba el thumbnail). En vista cliente se muestra el bloque "🍽️ Menú / Alimentos" (detalle + galería) solo si aplica. Pensado para tours que incluyen comida como plus; opcional porque depende del operador.

Campos "reserva-lista" (servicios)

ubicacion (lugar/punto de encuentro/dirección), mapa_url (link Google Maps), checkin (anti no-show, ej. "Llegar 15 min antes"), anticipacion (lead time, ej. "48 h"). Se ven en la vista cliente (bloques Disponibilidad / Dónde / Check-in). Cada modo + estos campos definen qué pedirá el futuro formulario de reserva (lead casi listo).

Vistas (toggle en tab Servicios)

  • ✎ Builder — grid de edición (muestra precio público + margen).
  • 👁 Vista cliente — catálogo limpio agrupado por tipo, como lo vería un cliente. openCliente() abre detalle estilo público. Oculta: precio_neto, margen, comisión, notas internas, proveedor, código.

Diseño / UI

Formal y minimalista: tipografía Inter, paleta blanco/negro/gris (--ink,--muted,--line), acentos sobrios mar (--sea #1f4b54, primario/activos) y arena (--sand, detalles puntuales como A&B). Botón primario negro. Sin serif decorativo.

Archivos / fotos

  • En uploads/servicio_{id}/, prefijo foto_ (fotos) o doc_ (documentos).
  • /api/file-counts elige first_image PREFIRIENDO foto_ y excluyendo docs (mismo patrón que el Hub).

Endpoints

  • GET/POST/PUT/DELETE /api/{proveedores|servicios}
  • GET /api/servicios (join proveedor_nombre) · GET /api/proveedores (con servicios_count)
  • GET /api/dashboard · GET /api/file-counts · GET /api/files/{entidad}
  • POST /api/upload/{entidad}?tipo=foto&label=... · DELETE /api/files/{entidad}/{name}

Convenciones de edición

  • Editar LOCAL aquí (/Users/claudeandrefg/Documents/catalogo-borrador/) y desplegar con scp.
  • No instalar dependencias — stdlib + vanilla JS. Si una feature lo requiere, discutir antes.
  • Para agregar una tabla nueva: CREATE TABLE en init_db() + entrada en TABLES (CRUD automático).

Pendientes / fases siguientes

  1. (Hecho) Builder: proveedores + servicios con fotos y todos los campos.
  2. Builder de propuestas/catálogos (selección de servicios → documento → PDF). Reusar patrón catalogos del Hub.
  3. Página web pública de catálogo online optimizado (sync desde la DB).