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.
192 lines
11 KiB
192 lines
11 KiB
|
4 weeks ago
|
# 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?
|