You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
senzapaura_es/docs/modelo-de-datos.md

192 lines
11 KiB

# Modelo de datos
Diseño de la migración del contenido a PostgreSQL. **Fase 1 —este documento—
está entregada y pendiente de verificación**; no hay código escrito todavía.
Versión presentable, con diagramas entidad-relación:
<https://claude.ai/code/artifact/d87ceb4d-6038-402f-852e-13ff5d86f02f>
Este archivo es la especificación; el artefacto es la misma información puesta
para leerse. Cuando se implemente, la verdad pasa a ser
`src/lib/server/db/schema.ts` y esto queda como el porqué.
## Por qué
Lo que hay hoy en `src/content/**` son registros disfrazados de documento: una
canción tiene veinte campos estructurados en YAML —`registro`, `duracion`,
`interpretes`, `versiones`, `videos`, `etiquetas`— y la letra entera también va
en el frontmatter. El cuerpo en Markdown son cuatro líneas de comentario.
Dos hallazgos concretos, no cuestión de gusto:
**1. Alguien puede perder una canción que pagó.** Cinco tablas apuntan a una
canción por una cadena de texto —`carrito_item`, `pedido_item`, `compra`,
`favorito`, `valoracion`— y ninguna tiene clave foránea, porque el destino no
está en la base sino en un archivo. Renombrar un slug deja huérfana una compra
sin que salte ningún error en ningún sitio.
**2. `estilo` hace dos trabajos distintos.** En el catálogo son las secciones del
artista (baladas románticas, clásica, rock, pop melódico); en el taller, una
«ficha de estilo» es un género hispanoamericano (bolero, tango, cumbia). Son dos
entidades que comparten palabra y hoy comparten nombre en el código. La
clasificación por país es del género, no del estilo, y mientras sean lo mismo no
se puede ni escribir.
A eso se suma que nada se valida —`estilo: bolreo` no falla, la canción
desaparece de su sección—, nada se consulta sin cargar el catálogo entero en
memoria, y cambiar una coma exige reconstruir y desplegar.
Alcance: **41 tablas** (13 ya existen), **48 archivos** que migrar, **22 rutas**
que hoy leen `$lib/content`.
## Decisiones transversales
| Decisión | Elegido | Motivo |
| --------------- | ----------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| Identificadores | `text` (nanoid 21), como las tablas actuales | El slug es texto que se lee y algún día se corrige; una clave primaria no debería cambiar nunca |
| Slugs | únicos + tabla `redireccion` | Renombrar deja de romper enlaces publicados; la dirección vieja responde 301 |
| Prosa | columna `text` con Markdown, compuesto en el servidor | Comprobado: ningún archivo de contenido usa sintaxis de Svelte, así que no se pierde nada al dejar de compilarlo con mdsvex |
| Listas | tabla si se consulta, `text[]` si solo se enseña | Las etiquetas cruzan el catálogo; los temas y rasgos de un género solo se pintan |
| Publicación | `estado` (borrador · publicado · retirado) | Escribir una ficha a medias no puede significar publicarla |
| Fechas | `timestamptz` siempre; `creado_en` y `actualizado_en` | Y en los legales, además, historial: hay que poder demostrar qué decía el día de una compra |
| Enumerados | texto con `CHECK`, no `ENUM` de Postgres | Es lo que genera Drizzle y permite añadir un valor sin una migración que bloquee la tabla |
| Borrados | reales en contenido; `retirado` en lo vendido | Una canción comprada no se borra nunca: la compra tiene que seguir apuntando a algo |
## Las entidades
### 1 · Catálogo
- **`estilo`** _(cambia)_ — id, slug, nombre, resumen, orden, `principal` con
índice parcial único (hoy es un acuerdo de palabra), imagen_id, estado.
- **`album`** _(cambia)_ — + numero_catalogo, `formatos text[]`,
pais_edicion_id. Los campos de `edicion` dejan de estar anidados.
- **`cancion`** _(cambia)_ — album_id nulo en los singles; **el álbum «Singles»
deja de existir como registro**, era un invento para pintar y se resuelve al
consultar. letra, nota, inspiracion y traducción salen del YAML.
- **`persona`** _(nueva)_ — nombre, nombre_legal, ipi. Hoy autores e intérpretes
son cadenas sueltas repetidas en cada archivo.
- **`cancion_persona`** _(nueva)_ — rol (letra · musica · interprete · arreglos ·
produccion), orden.
- **`version`** _(cambia)_ — **el `isrc` se mueve aquí desde la canción**: el
ISRC identifica una grabación y cada arreglo es una grabación distinta. Que
esté en la canción es un fallo del modelo actual.
- **`registro_obra`** _(cambia)_ — iswc, entidad, numero, editorial. 1:1 con la
canción.
- **`autoria`** _(cambia)_ — porcentaje `numeric(5,2)`, no entero: los repartos
reales llevan decimales. Suma 100 comprobado en la base.
- **`etiqueta`, `cancion_etiqueta`** _(cambia)_ — hoy se deducen de texto libre,
así que «desamor» y «Desamor» son dos etiquetas y nadie lo ve.
- **`traduccion`** _(nueva)_ — cancion_id + idioma. Hoy solo cabe una.
- **`video`, `cancion_enlace`, `album_enlace`, `credito_album`** _(cambia)_ —
**dos tablas de enlaces y no una polimórfica**: una clave foránea de verdad
vale más que ahorrarse una tabla.
### 2 · Taller y glosario
- **`pais`** _(nueva)_ — código ISO 3166-1, nombre, gentilicio, region.
- **`genero`** _(nueva)_ — bolero, tango, cumbia. origen_lugar, origen_ano
(ordenable, hoy no lo es), compas, tempo, metrica, estructura, rima,
`temas text[]`, `rasgos text[]`, y **`padre_id` para la jerarquía**: sin ella,
«todas las variantes» es una lista plana de cien nombres sin relación.
- **`genero_pais`** _(nueva)_ — relacion: cuna · adoptado. La cumbia nace
colombiana y se hace mexicana, peruana y argentina; el tango es de las dos
orillas. Un solo país sería mentira.
- **`capitulo`** _(cambia)_ — tipo (principio · ficha), genero_id solo en las
fichas, cuerpo, estado.
- **`termino`** _(nueva)_ — el glosario. termino único, categoria, `definicion`
de una o dos frases (lo que cabe en un globo sin taparle el texto a nadie),
ampliacion, ejemplo.
- **`termino_variante`** _(nueva)_ — «sinalefas», «heptasílabos». Sin esto el
marcado solo acierta en singular, que es casi nunca.
- **`capitulo_termino`** _(nueva)_ — se calcula **al guardar el capítulo, no al
pintarlo**; y siendo tabla, se puede desmarcar una aparición cuando la palabra
esté usada en otro sentido.
Regla editorial: **solo la primera aparición de cada término por página.** Marcar
las veintidós veces que sale «estribillo» convierte el texto en un campo de minas
subrayado.
### 3 · Editorial
- **`entrada`, `entrada_cancion`, `entrada_etiqueta`** _(cambia)_ — hoy la lista
de canciones son slugs sin comprobar: si el tema no existe, la entrada enlaza a
un 404 y nadie se entera.
- **`documento_legal`** + **`version_legal`** _(nueva)_ — historial con
`vigente_desde` y `resumen_cambios`. No es burocracia: es prueba.
- **`pagina`**, **`redireccion`** _(cambia / nueva)_.
### 4 · Cuentas y comercio
- **`usuario`, `identidad`, `sesion`, `codigo_acceso`, `limite`** _(sin cambios)_.
- **`carrito_item`, `pedido_item`, `compra`** _(cambia)_ — `cancion_slug text`
pasa a `cancion_id fk`. En `pedido_item` se congelan título y precio: una
factura tiene que seguir diciendo lo que decía.
- **`datos_facturacion`** _(nueva)_ — tipo, nombre, nif, dirección,
pais_codigo (decide el IVA), predeterminada.
- **`factura`** _(nueva)_ — serie y numero **correlativos y sin huecos**, base,
iva_tipo, iva_cuota, total, y `datos_congelados jsonb`: si el cliente cambia su
dirección, la factura vieja no puede cambiar con él.
- **`descarga`** _(nueva)_ — para poder demostrar la entrega en una reclamación.
### 5 · Interacción
- **`favorito`, `valoracion`** _(cambia)_ — clave foránea, y `CHECK` de 1 a 5 en
la base y no solo al validar.
- **`reproduccion`** _(nueva)_ — con `segundos`: una reproducción de tres
segundos no es una escucha, y contarla igual falsea la cifra. Agregación por
día y borrado del detalle a los noventa días **son parte del diseño**, no un
apaño para después.
### 6 · Medios
- **`medio`** _(nueva)_ — clase, clave, **`publico`** (los fragmentos sí, el
audio completo nunca; hoy eso lo garantiza la carpeta), mime, bytes,
duracion_s, ancho, alto, sha256, alt. Para que la administración pueda subir
audio, un archivo tiene que ser una fila.
### 7 · Bocetos, no se construyen ahora
`lista` + `lista_cancion` (la playlist que sigue sin definirse), `encargo`,
`inscripcion_taller`. Se dejan sitio porque aparecer después obliga a migrar lo
ya cargado.
## Qué cambia en la web
1. **Sveltia CMS deja de servir.** Es un editor sobre git. Hasta que exista la
administración propia —decidido: para después—, el contenido se carga por
script y por SQL.
2. **El Markdown se compone en cada petición**, no al construir. Se cachea.
3. **Cada página consulta la base.** A cambio, cambiar una letra deja de exigir
un despliegue.
## Fases
1. **Este documento.** Sin código. ← estamos aquí
2. **Esquema y migración, con el sitio leyendo todavía de los archivos.** Un
script vuelca los 48 archivos y comprueba que lo volcado coincide. Si algo no
cuadra, se ve antes de que dependa nadie de ello.
3. **Las claves foráneas de las compras.** Lo primero que se cambia de verdad,
porque es lo único que hoy puede costarle dinero a alguien.
4. **Las 22 rutas, de archivos a consultas.** Área por área, con las pruebas
existentes de guía.
5. **Lo nuevo:** géneros por país, glosario con globos, introducción larga del
taller.
6. **La administración.**
## Pendiente de respuesta
Seis decisiones de negocio. Cambiarlas después de cargar el contenido cuesta
mucho más que ahora.
1. ¿Los géneros del taller aspiran a ser un catálogo completo? Hay ocho fichas;
«todas las variantes hispanoamericanas» son más de cien contando subvariantes.
2. ¿Quién escribe las fichas que faltan? Es musicología: un compás equivocado
sale publicado con su nombre.
3. ¿El glosario se marca solo o a mano? «Clave» es un término del son y también
una palabra normal.
4. ¿Facturas con numeración correlativa? Si se vende, sí, y la serie no puede
tener huecos ni empezar tarde.
5. ¿Se conservan las escuchas por persona? Cambia la política de privacidad, que
hoy dice que no se hace seguimiento.
6. ¿Dónde viven los archivos: disco del servidor o almacenamiento aparte?

Powered by TurnKey Linux.