Files
catalogo-servicios/MODELO_DATOS.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

76 lines
3.2 KiB
Markdown

# Modelo de Datos — Catálogo de Servicios
Base **SQLite** (`catalogo.db`), modo WAL + foreign keys ON. 3 tablas.
El esquema se crea/migra solo al arrancar (`init_db()` en `server.py`); migraciones idempotentes (`ALTER TABLE` solo si la columna falta).
```
proveedores (1) ──< (N) servicios [FK proveedor_id, ON DELETE SET NULL]
usuarios (login, independiente)
```
---
## `proveedores` — Quién ofrece el servicio
Touroperadores / proveedores.
| Campo | Tipo | Notas |
|---|---|---|
| `id` | INTEGER PK | |
| `nombre` | TEXT | requerido |
| `tipo_principal` | TEXT | `tour` (default) / `ayb` / `transportacion` |
| `contacto`, `telefono`, `email`, `sitio_web` | TEXT | datos de contacto |
| `comision_default` | REAL | comisión base del proveedor |
| `notas` | TEXT | internas |
| `activo` | INTEGER | 1/0 |
| `created_at`, `updated_at` | TEXT | timestamps |
---
## `servicios` — Fuente única de verdad
La tabla central. Campos agrupados por **sección de impacto**.
| Sección | Campos |
|---|---|
| 📋 **Identidad** | `codigo`, `tipo` (tour/ayb/transportacion), `categoria`, `nombre` (req.), `descripcion` |
| ⚙️ **Operación** | `modo_disponibilidad`, `horarios` (JSON), `capacidad_min`, `capacidad_max`, `restricciones`, `atributos` (JSON por tipo) |
| 💰 **Comercial** | `precio_neto`, `precio_publico`, `moneda` (MXN), `unidad` (por_persona/por_grupo/por_vehiculo/por_evento), `tarifas_adicionales` |
| 📄 **Condiciones** | `terminos` |
| 📍 **Reserva-lista** | `ubicacion`, `mapa_url`, `checkin`, `anticipacion` |
| 🍽️ **Alimentos** | `incluye_alimentos` (0/1), `menu_detalle` |
| 🌐 **Publicación** | `mostrar_en_web` (0/1) |
| | `activo`, `notas`, `created_at`, `updated_at`, `proveedor_id` (FK) |
### `atributos` — JSON flexible por tipo
En vez de columnas rígidas, los extras específicos van en JSON. Sugeridos (definidos en `index.html → ATRIBUTOS`):
- **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
### `modo_disponibilidad` + `horarios` (JSON)
Eje **independiente** del `tipo`. Default por tipo (`MODO_DEFAULT`): tour→`salidas`, transportacion→`siempre`, ayb→`por_evento`. Editable.
| Modo | `horarios` |
|---|---|
| `salidas` | `{"Lun":["08:00","14:00"], ...}` (días + varias salidas/día) |
| `rango` | `{"dias":[...],"desde":"06:00","hasta":"22:00"}` |
| `siempre` (24/7) | `{}` |
| `por_evento` | `{}` (reserva por fecha) |
> Compatibilidad: servicios viejos sin `modo` se tratan como `salidas` con su `horarios` día-keyed.
---
## `usuarios` — Login
`id`, `username` (único), `pass_hash` (PBKDF2-SHA256 + salt), `nombre`, `activo`, `created_at`.
Sesión = cookie firmada con HMAC (clave en `secret.key`, NO versionada).
---
## Archivos (no en DB)
En `uploads/servicio_{id}/` con prefijo:
- `foto_` — fotos del servicio
- `menu_` — fotos del menú/alimentos (separadas; `loadPhotos` excluye `menu_`, `loadMenuFotos` solo `menu_`)
- `doc_` — documentos
`/api/file-counts` elige `first_image` **prefiriendo** `foto_` y **excluyendo** docs y `menu` (para no robar el thumbnail).