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>
This commit is contained in:
75
MODELO_DATOS.md
Normal file
75
MODELO_DATOS.md
Normal file
@@ -0,0 +1,75 @@
|
||||
# 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).
|
||||
Reference in New Issue
Block a user