Fase 1 de la migracion del contenido a PostgreSQL: las 41 entidades con sus campos, sus relaciones y el motivo de cada decision. Sin codigo. De analizarlo salieron dos cosas que no se buscaban: - Cinco tablas apuntan a una cancion por una cadena de texto y ninguna tiene clave foranea, porque el destino esta en un archivo. Renombrar un slug deja huerfana una compra en silencio. Por eso ese arreglo es la fase 3 y no la ultima. - `estilo` hace dos trabajos: las secciones del catalogo y los generos del taller. El pais que hay que clasificar es del genero, y mientras sean lo mismo esa clasificacion no se puede ni escribir. Y el ISRC estaba en la cancion cuando identifica una grabacion, asi que pasa a la version. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>master
parent
3f1a651006
commit
2fcc90dfcc
@ -0,0 +1,191 @@
|
||||
# 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?
|
||||
Loading…
Reference in new issue