105 KiB
Modelo de datos completo de Senza Paura
Generado el 2026-09-14T20:26:39.479Z desde el esquema PostgreSQL aplicado y contrastado con los contratos TypeScript de la aplicación.
Alcance: 83 tablas, 1 vista, 3 secuencias, 4 funciones de base y 42 migraciones aplicadas.
Fuentes y convenciones
- Esquema declarativo:
src/lib/server/db/schema/. - Historial físico:
drizzle/. - Campos TypeScript en
camelCase; nombres PostgreSQL ensnake_case. textes el identificador opaco habitual.pais.codigoes la excepción: usa ISO 3166-1 alfa-2.- Los importes monetarios son enteros en céntimos y la moneda usa código ISO en minúsculas.
- Las marcas de tiempo son
timestamp with time zone. - Los estados editoriales comunes son
borrador,publicadoyretirado.
Vista conceptual
flowchart LR
BASE[Base y artistas] --> CAT[Catálogo musical]
CAT --> INT[Interacción y escucha]
CTA[Cuentas y suscripciones] --> INT
CTA --> COM[Comercio]
CAT --> COM
COM --> FAC[Facturación]
CAT --> EDI[Editorial y legal]
BASE --> TALLER[Taller de letras]
CAT --> TALLER
CTA --> JUKE[Jukebox]
CAT --> JUKE
La entidad central es cancion. Se relaciona con álbumes, estilos, intérpretes, audios, autoría, etiquetas, ventas, descargas, listas, reproducciones, likes/valoraciones, entradas editoriales, géneros del taller y prompts.
Reglas que definen el modelo
- Una versión musical es otra fila de
cancion;version_de_idapunta a la canción principal. Una versión no puede venderse por separado. valoraciontiene una sola fila por(usuario_id, cancion_id):likeyvalueno se pisan. Quitar un like conservavalueydate.artistaes la identidad pública;personaes la persona física o acreditada.artista_personapermite solistas, grupos y proyectos.compramaterializa el permiso de descarga. El pedido conserva el hecho comercial; la factura conserva el hecho fiscal.- Una factura emitida no se reescribe: las correcciones se modelan como facturas rectificativas.
- La programación del Jukebox vive como franjas JSON versionadas mediante
revisionpara control de concurrencia. - El taller usa vocabularios normalizados y tablas puente para géneros, países, metros, compases, instrumentos, figuras, obras, versos y glosario.
Relaciones principales
erDiagram
USUARIO ||--o{ VALORACION : emite
CANCION ||--o{ VALORACION : recibe
USUARIO ||--o{ FAVORITO : guarda
USUARIO ||--o{ LISTA_REPRODUCCION : crea
LISTA_REPRODUCCION ||--o{ LISTA_REPRODUCCION_CANCION : contiene
CANCION ||--o{ LISTA_REPRODUCCION_CANCION : aparece
ESTILO ||--o{ ALBUM : agrupa
ESTILO ||--o{ CANCION : clasifica
ALBUM ||--o{ CANCION : publica
CANCION ||--o{ CANCION_AUDIO : dispone
MEDIO ||--o{ CANCION_AUDIO : almacena
ARTISTA ||--o{ CANCION_INTERPRETE : interpreta
CANCION ||--o{ CANCION_INTERPRETE : acredita
USUARIO ||--o{ PEDIDO : realiza
PEDIDO ||--o{ PEDIDO_LINEA : contiene
PEDIDO ||--o{ FACTURA : documenta
USUARIO ||--o{ JUKEBOX : configura
Contratos JSON de la aplicación
Contenido editorial por bloques
artista.secciones, album.secciones, cancion.inspiracion_secciones y entrada.secciones contienen una lista ordenada de bloques:
- Base:
{ id, tipo, titulo? }. - Texto:
{ tipo: "texto", texto }. - Código:
{ tipo: "codigo", codigo, lenguaje? }. - Medio:
{ tipo: "video" | "imagen" | "audio", url, pie?, subtitulos?, alt? }.
Presentación editorial
artista.presentacion, album.presentacion, cancion.presentacion y entrada.presentacion usan { plantilla, heroe }, donde heroe es automatico, visible u oculto.
Jukebox
jukebox.franjas y programacion_jukebox.franjas contienen objetos { id, inicio, fin, orden, catalogo, etiquetas?, contenidos }. orden es secuencial o aleatoria; contenidos referencia listas o canciones mediante { tipo, id }; varias etiquetas se combinan como unión.
Comercio abierto
producto.datos, pedido_linea.datos, intencion_pago.datos y factura.datos_congelados conservan atributos variables o una instantánea del momento comercial. Los campos consultables y las cantidades monetarias permanecen normalizados en columnas.
Base y artistas
artista
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
id |
text |
no | — |
codigo |
text |
no | ('ART-'::text || lpad((nextval('artista_codigo_seq'::regclass))::text, 6, '0'::text)) |
slug |
text |
no | — |
tipo |
text |
no | 'persona'::text |
nombre |
text |
no | — |
descripcion_corta |
text |
no | ''::text |
biografia |
text |
no | ''::text |
imagen_id |
text |
sí | — |
pais_codigo |
character(2) |
sí | — |
lugar_origen |
text |
sí | — |
inicio |
integer |
sí | — |
fin |
integer |
sí | — |
sitio_web |
text |
sí | — |
estado |
text |
no | 'borrador'::text |
origen |
text |
no | 'manual'::text |
modelo_origen |
text |
sí | — |
importado_en |
timestamp with time zone |
sí | — |
revisado_por |
text |
sí | — |
revisado_en |
timestamp with time zone |
sí | — |
creado_en |
timestamp with time zone |
no | now() |
actualizado_en |
timestamp with time zone |
sí | — |
secciones |
jsonb |
no | '[]'::jsonb |
presentacion |
jsonb |
no | '{}'::jsonb |
es_virtual |
boolean |
no | false |
nombre_visual |
text |
no | 'texto'::text |
logotipo_id |
text |
sí | — |
logotipo_claro_id |
text |
sí | — |
logotipo_oscuro_id |
text |
sí | — |
Claves y restricciones:
- CHECK artista_estado_conocido:
CHECK (estado = ANY (ARRAY['borrador'::text, 'publicado'::text, 'retirado'::text])) - CHECK artista_nombre_visual_conocido:
CHECK (nombre_visual = ANY (ARRAY['texto'::text, 'logotipo'::text])) - CHECK artista_origen_conocido:
CHECK (origen = ANY (ARRAY['manual'::text, 'importado'::text])) - CHECK artista_periodo_valido:
CHECK (fin IS NULL OR inicio IS NULL OR fin >= inicio) - CHECK artista_presentacion_objeto:
CHECK (jsonb_typeof(presentacion) = 'object'::text) - CHECK artista_secciones_array:
CHECK (jsonb_typeof(secciones) = 'array'::text) - CHECK artista_tipo_conocido:
CHECK (tipo = ANY (ARRAY['persona'::text, 'grupo'::text, 'proyecto'::text, 'virtual'::text])) - FK artista_imagen_fk:
FOREIGN KEY (imagen_id) REFERENCES medio(id) ON DELETE SET NULL - FK artista_logotipo_claro_id_medio_id_fk:
FOREIGN KEY (logotipo_claro_id) REFERENCES medio(id) ON DELETE SET NULL - FK artista_logotipo_id_medio_id_fk:
FOREIGN KEY (logotipo_id) REFERENCES medio(id) ON DELETE SET NULL - FK artista_logotipo_oscuro_id_medio_id_fk:
FOREIGN KEY (logotipo_oscuro_id) REFERENCES medio(id) ON DELETE SET NULL - FK artista_pais_fk:
FOREIGN KEY (pais_codigo) REFERENCES pais(codigo) - PK artista_pkey:
PRIMARY KEY (id)
Índices adicionales: artista_codigo_unico, artista_estado, artista_nombre, artista_slug_unico.
artista_identificador
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
artista_id |
text |
no | — |
sistema |
text |
no | — |
valor |
text |
no | — |
Claves y restricciones:
- FK artista_identificador_artista_fk:
FOREIGN KEY (artista_id) REFERENCES artista(id) ON DELETE CASCADE - PK artista_identificador_pk:
PRIMARY KEY (artista_id, sistema)
Índices adicionales: artista_identificador_externo_unico.
artista_persona
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
artista_id |
text |
no | — |
persona_id |
text |
no | — |
relacion |
text |
no | — |
desde |
integer |
sí | — |
hasta |
integer |
sí | — |
orden |
integer |
no | 0 |
Claves y restricciones:
- CHECK artista_persona_periodo_valido:
CHECK (hasta IS NULL OR desde IS NULL OR hasta >= desde) - CHECK artista_persona_relacion_conocida:
CHECK (relacion = ANY (ARRAY['identidad'::text, 'miembro'::text, 'fundador'::text])) - FK artista_persona_artista_fk:
FOREIGN KEY (artista_id) REFERENCES artista(id) ON DELETE CASCADE - FK artista_persona_persona_fk:
FOREIGN KEY (persona_id) REFERENCES persona(id) ON DELETE CASCADE - PK artista_persona_pk:
PRIMARY KEY (artista_id, persona_id, relacion)
Índices adicionales: artista_persona_persona.
medio
Archivo administrado: imagen, audio, muestra o documento, con metadatos técnicos e integridad SHA-256.
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
id |
text |
no | — |
clase |
text |
no | — |
clave |
text |
no | — |
publico |
boolean |
no | false |
mime |
text |
no | — |
bytes |
integer |
no | — |
duracion_s |
integer |
sí | — |
ancho |
integer |
sí | — |
alto |
integer |
sí | — |
sha256 |
text |
no | — |
alt |
text |
sí | — |
creado_en |
timestamp with time zone |
no | now() |
Claves y restricciones:
- PK medio_pkey:
PRIMARY KEY (id) - UNIQUE medio_clave_unique:
UNIQUE (clave)
Índices adicionales: medio_clase, medio_sha.
pais
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
codigo |
character(2) |
no | — |
nombre |
text |
no | — |
gentilicio |
text |
sí | — |
region |
text |
sí | — |
Claves y restricciones:
- PK pais_pkey:
PRIMARY KEY (codigo)
persona
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
id |
text |
no | — |
slug |
text |
no | — |
nombre |
text |
no | — |
nombre_legal |
text |
sí | — |
ipi |
text |
sí | — |
nacimiento |
integer |
sí | — |
defuncion |
integer |
sí | — |
pais_codigo |
character(2) |
sí | — |
retrato_id |
text |
sí | — |
semblanza |
text |
sí | — |
estado |
text |
no | 'borrador'::text |
creado_en |
timestamp with time zone |
no | now() |
actualizado_en |
timestamp with time zone |
sí | — |
origen |
text |
no | 'manual'::text |
modelo_origen |
text |
sí | — |
importado_en |
timestamp with time zone |
sí | — |
revisado_por |
text |
sí | — |
revisado_en |
timestamp with time zone |
sí | — |
Claves y restricciones:
- FK persona_pais_codigo_pais_codigo_fk:
FOREIGN KEY (pais_codigo) REFERENCES pais(codigo) - FK persona_retrato_id_medio_id_fk:
FOREIGN KEY (retrato_id) REFERENCES medio(id) ON DELETE SET NULL - PK persona_pkey:
PRIMARY KEY (id) - UNIQUE persona_slug_unique:
UNIQUE (slug)
Índices adicionales: persona_nombre, persona_pais.
Catálogo musical
album
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
id |
text |
no | — |
slug |
text |
no | — |
titulo |
text |
no | — |
estilo_id |
text |
no | — |
tipo |
text |
no | 'album'::text |
fecha |
text |
no | — |
portada_id |
text |
sí | — |
sello |
text |
sí | — |
resumen |
text |
no | ''::text |
destacado |
boolean |
no | false |
numero_catalogo |
text |
sí | — |
formatos |
text[] |
sí | — |
pais_edicion_codigo |
character(2) |
sí | — |
estado |
text |
no | 'borrador'::text |
creado_en |
timestamp with time zone |
no | now() |
actualizado_en |
timestamp with time zone |
sí | — |
cuerpo |
text |
no | ''::text |
secciones |
jsonb |
no | '[]'::jsonb |
presentacion |
jsonb |
no | '{}'::jsonb |
Claves y restricciones:
- CHECK album_presentacion_objeto:
CHECK (jsonb_typeof(presentacion) = 'object'::text) - CHECK album_secciones_array:
CHECK (jsonb_typeof(secciones) = 'array'::text) - FK album_estilo_id_estilo_id_fk:
FOREIGN KEY (estilo_id) REFERENCES estilo(id) - FK album_pais_edicion_codigo_pais_codigo_fk:
FOREIGN KEY (pais_edicion_codigo) REFERENCES pais(codigo) - FK album_portada_id_medio_id_fk:
FOREIGN KEY (portada_id) REFERENCES medio(id) ON DELETE SET NULL - PK album_pkey:
PRIMARY KEY (id) - UNIQUE album_slug_unique:
UNIQUE (slug)
Índices adicionales: album_estilo, album_fecha.
album_enlace
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
album_id |
text |
no | — |
plataforma |
text |
no | — |
url |
text |
no | — |
Claves y restricciones:
- FK album_enlace_album_id_album_id_fk:
FOREIGN KEY (album_id) REFERENCES album(id) ON DELETE CASCADE - PK album_enlace_album_id_plataforma_pk:
PRIMARY KEY (album_id, plataforma)
autoria
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
cancion_id |
text |
no | — |
persona_id |
text |
no | — |
rol |
text |
no | — |
porcentaje |
numeric(5,2) |
no | — |
Claves y restricciones:
- FK autoria_cancion_id_cancion_id_fk:
FOREIGN KEY (cancion_id) REFERENCES cancion(id) ON DELETE CASCADE - FK autoria_persona_id_persona_id_fk:
FOREIGN KEY (persona_id) REFERENCES persona(id) - PK autoria_cancion_id_persona_id_rol_pk:
PRIMARY KEY (cancion_id, persona_id, rol) - t autoria_suma_cien_trg:
TRIGGER DEFERRABLE INITIALLY DEFERRED
Disparadores:
autoria_suma_cien_trg:CREATE CONSTRAINT TRIGGER autoria_suma_cien_trg AFTER INSERT OR DELETE OR UPDATE ON autoria DEFERRABLE INITIALLY DEFERRED FOR EACH ROW EXECUTE FUNCTION autoria_suma_cien()
cancion
Tema principal o versión musical. version_de_id apunta a otra canción y separa obra principal de arreglo o grabación.
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
id |
text |
no | — |
slug |
text |
no | — |
titulo |
text |
no | — |
version_de_id |
text |
sí | — |
version_nombre |
text |
sí | — |
version_orden |
integer |
no | 0 |
estilo_id |
text |
no | — |
album_id |
text |
sí | — |
numero |
integer |
sí | — |
duracion_s |
integer |
sí | — |
ano |
integer |
sí | — |
letra |
text |
sí | — |
idioma |
text |
no | — |
inspiracion |
text |
sí | — |
tiene_letra |
boolean |
no | true |
destacada |
boolean |
no | false |
portada_id |
text |
sí | — |
ala_venta |
boolean |
no | false |
estado |
text |
no | 'borrador'::text |
creado_en |
timestamp with time zone |
no | now() |
actualizado_en |
timestamp with time zone |
sí | — |
es_version |
boolean |
sí | (version_de_id IS NOT NULL) |
padre_no_es_version |
boolean |
sí | CASE WHEN (version_de_id IS NULL) THEN NULL::boolean ELSE false END |
version_nota |
text |
sí | — |
codigo |
text |
no | ('CAN-'::text || lpad((nextval('cancion_codigo_seq'::regclass))::text, 6, '0'::text)) |
version_codigo |
text |
sí | — |
formacion_vocal |
formacion_vocal |
sí | — |
acceso |
acceso_cancion |
no | 'publico'::acceso_cancion |
inspiracion_secciones |
jsonb |
no | '[]'::jsonb |
presentacion |
jsonb |
no | '{}'::jsonb |
Claves y restricciones:
- CHECK cancion_estado_conocido:
CHECK (estado = ANY (ARRAY['borrador'::text, 'publicado'::text, 'retirado'::text])) - CHECK cancion_idioma_bcp47:
CHECK (idioma ~ '^[a-z]{2,8}(-[A-Za-z0-9]{1,8})*$'::text) - CHECK cancion_inspiracion_secciones_array:
CHECK (jsonb_typeof(inspiracion_secciones) = 'array'::text) - CHECK cancion_no_es_su_propia_version:
CHECK (version_de_id IS NULL OR version_de_id <> id) - CHECK cancion_presentacion_objeto:
CHECK (jsonb_typeof(presentacion) = 'object'::text) - CHECK cancion_version_codigo_presente:
CHECK (version_de_id IS NULL AND version_codigo IS NULL OR version_de_id IS NOT NULL AND NULLIF(btrim(version_codigo), ''::text) IS NOT NULL) - CHECK cancion_version_no_se_vende:
CHECK (version_de_id IS NULL OR NOT ala_venta) - FK cancion_album_id_album_id_fk:
FOREIGN KEY (album_id) REFERENCES album(id) ON DELETE SET NULL - FK cancion_estilo_id_estilo_id_fk:
FOREIGN KEY (estilo_id) REFERENCES estilo(id) - FK cancion_portada_id_medio_id_fk:
FOREIGN KEY (portada_id) REFERENCES medio(id) ON DELETE SET NULL - FK cancion_version_de_fk:
FOREIGN KEY (version_de_id) REFERENCES cancion(id) ON DELETE CASCADE - FK cancion_version_de_principal:
FOREIGN KEY (version_de_id, padre_no_es_version) REFERENCES cancion(id, es_version) - PK cancion_pkey:
PRIMARY KEY (id) - t cancion_publicable:
TRIGGER DEFERRABLE INITIALLY DEFERRED - UNIQUE cancion_id_es_version_unica:
UNIQUE (id, es_version) - UNIQUE cancion_slug_unique:
UNIQUE (slug)
Índices adicionales: cancion_album, cancion_codigo_unico, cancion_destacada, cancion_estilo, cancion_version_codigo_unico, cancion_version_de.
Disparadores:
cancion_publicable:CREATE CONSTRAINT TRIGGER cancion_publicable AFTER INSERT OR UPDATE ON cancion DEFERRABLE INITIALLY DEFERRED FOR EACH ROW EXECUTE FUNCTION guardar_invariantes_publicacion()
cancion_audio
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
cancion_id |
text |
no | — |
medio_id |
text |
no | — |
uso |
text |
no | — |
formato |
text |
no | — |
bitrate_kbps |
integer |
sí | — |
frecuencia_hz |
integer |
sí | — |
bits_muestra |
integer |
sí | — |
canales |
integer |
sí | — |
orden |
integer |
no | 0 |
Claves y restricciones:
- CHECK cancion_audio_bitrate_valido:
CHECK (bitrate_kbps IS NULL OR bitrate_kbps > 0) - CHECK cancion_audio_bits_validos:
CHECK (bits_muestra IS NULL OR bits_muestra > 0) - CHECK cancion_audio_canales_validos:
CHECK (canales IS NULL OR canales > 0) - CHECK cancion_audio_frecuencia_valida:
CHECK (frecuencia_hz IS NULL OR frecuencia_hz > 0) - CHECK cancion_audio_uso_conocido:
CHECK (uso = ANY (ARRAY['stream'::text, 'descarga'::text, 'master'::text])) - FK cancion_audio_cancion_fk:
FOREIGN KEY (cancion_id) REFERENCES cancion(id) ON DELETE CASCADE - FK cancion_audio_medio_fk:
FOREIGN KEY (medio_id) REFERENCES medio(id) ON DELETE RESTRICT - PK cancion_audio_pk:
PRIMARY KEY (cancion_id, uso, formato) - t cancion_audios_publicables:
TRIGGER DEFERRABLE INITIALLY DEFERRED
Índices adicionales: cancion_audio_cancion, cancion_audio_medio_unico.
Disparadores:
cancion_audios_publicables:CREATE CONSTRAINT TRIGGER cancion_audios_publicables AFTER INSERT OR DELETE OR UPDATE ON cancion_audio DEFERRABLE INITIALLY DEFERRED FOR EACH ROW EXECUTE FUNCTION guardar_invariantes_publicacion()
cancion_enlace
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
cancion_id |
text |
no | — |
plataforma |
text |
no | — |
url |
text |
no | — |
Claves y restricciones:
- FK cancion_enlace_cancion_id_cancion_id_fk:
FOREIGN KEY (cancion_id) REFERENCES cancion(id) ON DELETE CASCADE - PK cancion_enlace_cancion_id_plataforma_pk:
PRIMARY KEY (cancion_id, plataforma)
cancion_etiqueta
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
cancion_id |
text |
no | — |
etiqueta_id |
text |
no | — |
orden |
integer |
no | 0 |
Claves y restricciones:
- FK cancion_etiqueta_cancion_id_cancion_id_fk:
FOREIGN KEY (cancion_id) REFERENCES cancion(id) ON DELETE CASCADE - FK cancion_etiqueta_etiqueta_id_etiqueta_id_fk:
FOREIGN KEY (etiqueta_id) REFERENCES etiqueta(id) ON DELETE CASCADE - PK cancion_etiqueta_cancion_id_etiqueta_id_pk:
PRIMARY KEY (cancion_id, etiqueta_id)
cancion_interprete
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
cancion_id |
text |
no | — |
artista_id |
text |
no | — |
rol |
text |
no | 'principal'::text |
instrumento |
text |
sí | — |
acreditado_como |
text |
sí | — |
orden |
integer |
no | 0 |
Claves y restricciones:
- CHECK cancion_interprete_rol_conocido:
CHECK (rol = ANY (ARRAY['principal'::text, 'invitado'::text, 'coros'::text, 'instrumentista'::text])) - FK cancion_interprete_artista_fk:
FOREIGN KEY (artista_id) REFERENCES artista(id) - FK cancion_interprete_cancion_fk:
FOREIGN KEY (cancion_id) REFERENCES cancion(id) ON DELETE CASCADE - PK cancion_interprete_pk:
PRIMARY KEY (cancion_id, artista_id, rol) - t cancion_creditos_publicables:
TRIGGER DEFERRABLE INITIALLY DEFERRED
Índices adicionales: cancion_interprete_artista.
Disparadores:
cancion_creditos_publicables:CREATE CONSTRAINT TRIGGER cancion_creditos_publicables AFTER INSERT OR DELETE OR UPDATE ON cancion_interprete DEFERRABLE INITIALLY DEFERRED FOR EACH ROW EXECUTE FUNCTION guardar_invariantes_publicacion()
cancion_persona
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
cancion_id |
text |
no | — |
persona_id |
text |
no | — |
rol |
text |
no | — |
orden |
integer |
no | 0 |
Claves y restricciones:
- FK cancion_persona_cancion_id_cancion_id_fk:
FOREIGN KEY (cancion_id) REFERENCES cancion(id) ON DELETE CASCADE - FK cancion_persona_persona_id_persona_id_fk:
FOREIGN KEY (persona_id) REFERENCES persona(id) - PK cancion_persona_cancion_id_persona_id_rol_pk:
PRIMARY KEY (cancion_id, persona_id, rol)
credito_album
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
id |
text |
no | — |
album_id |
text |
no | — |
persona_id |
text |
sí | — |
nombre |
text |
sí | — |
rol |
text |
no | — |
orden |
integer |
no | 0 |
Claves y restricciones:
- FK credito_album_album_id_album_id_fk:
FOREIGN KEY (album_id) REFERENCES album(id) ON DELETE CASCADE - FK credito_album_persona_id_persona_id_fk:
FOREIGN KEY (persona_id) REFERENCES persona(id) - PK credito_album_pkey:
PRIMARY KEY (id)
Índices adicionales: credito_album_album.
estilo
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
id |
text |
no | — |
slug |
text |
no | — |
nombre |
text |
no | — |
resumen |
text |
no | ''::text |
orden |
integer |
no | 0 |
principal |
boolean |
no | false |
imagen_id |
text |
sí | — |
estado |
text |
no | 'borrador'::text |
creado_en |
timestamp with time zone |
no | now() |
actualizado_en |
timestamp with time zone |
sí | — |
cuerpo |
text |
no | ''::text |
Claves y restricciones:
- FK estilo_imagen_id_medio_id_fk:
FOREIGN KEY (imagen_id) REFERENCES medio(id) ON DELETE SET NULL - PK estilo_pkey:
PRIMARY KEY (id) - UNIQUE estilo_slug_unique:
UNIQUE (slug)
Índices adicionales: estilo_orden, estilo_principal_unico.
etiqueta
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
id |
text |
no | — |
slug |
text |
no | — |
nombre |
text |
no | — |
Claves y restricciones:
- PK etiqueta_pkey:
PRIMARY KEY (id) - UNIQUE etiqueta_slug_unique:
UNIQUE (slug)
registro_obra
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
cancion_id |
text |
no | — |
iswc |
text |
sí | — |
isrc |
text |
sí | — |
entidad |
text |
sí | — |
numero |
text |
sí | — |
editorial |
text |
sí | — |
Claves y restricciones:
- FK registro_obra_cancion_id_cancion_id_fk:
FOREIGN KEY (cancion_id) REFERENCES cancion(id) ON DELETE CASCADE - PK registro_obra_pkey:
PRIMARY KEY (cancion_id)
traduccion
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
cancion_id |
text |
no | — |
idioma |
text |
no | — |
texto |
text |
no | — |
Claves y restricciones:
- FK traduccion_cancion_id_cancion_id_fk:
FOREIGN KEY (cancion_id) REFERENCES cancion(id) ON DELETE CASCADE - PK traduccion_cancion_id_idioma_pk:
PRIMARY KEY (cancion_id, idioma)
video
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
id |
text |
no | — |
cancion_id |
text |
no | — |
youtube_id |
text |
no | — |
titulo |
text |
no | — |
orden |
integer |
no | 0 |
Claves y restricciones:
- FK video_cancion_id_cancion_id_fk:
FOREIGN KEY (cancion_id) REFERENCES cancion(id) ON DELETE CASCADE - PK video_pkey:
PRIMARY KEY (id)
Índices adicionales: video_cancion.
Cuentas y suscripciones
codigo_acceso
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
id |
text |
no | — |
email |
text |
no | — |
hash |
text |
no | — |
expira_en |
timestamp with time zone |
no | — |
intentos |
integer |
no | 0 |
usado_en |
timestamp with time zone |
sí | — |
creado_en |
timestamp with time zone |
no | now() |
Claves y restricciones:
- PK codigo_acceso_pkey:
PRIMARY KEY (id)
Índices adicionales: codigo_acceso_email.
identidad
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
id |
text |
no | — |
proveedor |
text |
no | — |
sujeto |
text |
no | — |
usuario_id |
text |
no | — |
email |
text |
sí | — |
creada_en |
timestamp with time zone |
no | now() |
ultimo_acceso_en |
timestamp with time zone |
sí | — |
Claves y restricciones:
- FK identidad_usuario_id_usuario_id_fk:
FOREIGN KEY (usuario_id) REFERENCES usuario(id) ON DELETE CASCADE - PK identidad_pkey:
PRIMARY KEY (id)
Índices adicionales: identidad_proveedor_sujeto, identidad_usuario.
limite
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
clave |
text |
no | — |
intentos |
integer |
no | — |
expira_en |
bigint |
no | — |
Claves y restricciones:
- PK limite_pkey:
PRIMARY KEY (clave)
Índices adicionales: limite_expira.
plan_suscripcion
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
id |
text |
no | — |
codigo |
text |
no | — |
nombre |
text |
no | — |
descripcion |
text |
sí | — |
nivel |
integer |
no | — |
precio_centimos |
integer |
no | — |
moneda |
text |
no | 'eur'::text |
periodicidad |
text |
no | — |
intervalos |
integer |
no | 1 |
referencia_precio_externa |
text |
sí | — |
prestaciones |
jsonb |
no | '[]'::jsonb |
estado |
text |
no | 'borrador'::text |
creado_en |
timestamp with time zone |
no | now() |
actualizado_en |
timestamp with time zone |
no | now() |
incluye_publicidad |
boolean |
no | false |
calidad_escucha |
text |
sí | 'media'::text |
descargas_incluidas |
integer |
no | 0 |
calidad_descarga |
text |
sí | — |
acceso_versiones |
boolean |
no | false |
ambito |
text |
no | 'musica'::text |
acceso_contenido_taller |
boolean |
no | false |
descarga_material_taller |
boolean |
no | false |
acceso_jukebox |
boolean |
no | false |
Claves y restricciones:
- CHECK plan_suscripcion_ambito_conocido:
CHECK (ambito = ANY (ARRAY['musica'::text, 'taller_letras'::text])) - CHECK plan_suscripcion_calidad_descarga_conocida:
CHECK (calidad_descarga IS NULL OR (calidad_descarga = ANY (ARRAY['media'::text, 'alta'::text]))) - CHECK plan_suscripcion_calidad_escucha_conocida:
CHECK (calidad_escucha IS NULL OR (calidad_escucha = ANY (ARRAY['media'::text, 'alta'::text]))) - CHECK plan_suscripcion_calidad_solo_con_descargas:
CHECK (descargas_incluidas > 0 OR calidad_descarga IS NULL) - CHECK plan_suscripcion_capacidades_segun_ambito:
CHECK (ambito = 'musica'::text AND calidad_escucha IS NOT NULL AND NOT acceso_contenido_taller AND NOT descarga_material_taller OR ambito = 'taller_letras'::text AND calidad_escucha IS NULL AND NOT incluye_publicidad AND descargas_incluidas = 0 AND calidad_descarga IS NULL AND NOT acceso_versiones AND NOT acceso_jukebox) - CHECK plan_suscripcion_codigo_no_vacio:
CHECK (btrim(codigo) <> ''::text) - CHECK plan_suscripcion_descargas_no_negativas:
CHECK (descargas_incluidas >= 0) - CHECK plan_suscripcion_estado_conocido:
CHECK (estado = ANY (ARRAY['borrador'::text, 'disponible'::text, 'retirado'::text])) - CHECK plan_suscripcion_intervalos_positivos:
CHECK (intervalos > 0) - CHECK plan_suscripcion_moneda_iso:
CHECK (moneda ~ '^[a-z]{3}$'::text) - CHECK plan_suscripcion_nivel_positivo:
CHECK (nivel > 0) - CHECK plan_suscripcion_nombre_no_vacio:
CHECK (btrim(nombre) <> ''::text) - CHECK plan_suscripcion_periodicidad_conocida:
CHECK (periodicidad = ANY (ARRAY['dia'::text, 'semana'::text, 'mes'::text, 'ano'::text])) - CHECK plan_suscripcion_precio_no_negativo:
CHECK (precio_centimos >= 0) - CHECK plan_suscripcion_prestaciones_array:
CHECK (jsonb_typeof(prestaciones) = 'array'::text) - PK plan_suscripcion_pkey:
PRIMARY KEY (id) - UNIQUE plan_suscripcion_codigo_unique:
UNIQUE (codigo) - UNIQUE plan_suscripcion_referencia_precio_externa_unique:
UNIQUE (referencia_precio_externa)
Índices adicionales: plan_suscripcion_estado_nivel.
sesion
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
id |
text |
no | — |
usuario_id |
text |
no | — |
expira_en |
timestamp with time zone |
no | — |
creada_en |
timestamp with time zone |
no | now() |
Claves y restricciones:
- FK sesion_usuario_id_usuario_id_fk:
FOREIGN KEY (usuario_id) REFERENCES usuario(id) ON DELETE CASCADE - PK sesion_pkey:
PRIMARY KEY (id)
Índices adicionales: sesion_usuario.
suscripcion
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
id |
text |
no | — |
usuario_id |
text |
no | — |
estado |
text |
no | 'pendiente'::text |
inicia_en |
timestamp with time zone |
no | now() |
termina_en |
timestamp with time zone |
sí | — |
proveedor |
text |
sí | — |
referencia_externa |
text |
sí | — |
creada_en |
timestamp with time zone |
no | now() |
actualizada_en |
timestamp with time zone |
no | now() |
plan_id |
text |
sí | — |
Claves y restricciones:
- CHECK suscripcion_estado_conocido:
CHECK (estado = ANY (ARRAY['pendiente'::text, 'activa'::text, 'pausada'::text, 'cancelada'::text, 'vencida'::text])) - CHECK suscripcion_periodo_valido:
CHECK (termina_en IS NULL OR termina_en > inicia_en) - CHECK suscripcion_referencia_completa:
CHECK ((proveedor IS NULL) = (referencia_externa IS NULL)) - FK suscripcion_plan_id_plan_suscripcion_id_fk:
FOREIGN KEY (plan_id) REFERENCES plan_suscripcion(id) ON DELETE RESTRICT - FK suscripcion_usuario_id_usuario_id_fk:
FOREIGN KEY (usuario_id) REFERENCES usuario(id) ON DELETE CASCADE - PK suscripcion_pkey:
PRIMARY KEY (id)
Índices adicionales: suscripcion_proveedor_referencia, suscripcion_usuario_estado.
usuario
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
id |
text |
no | — |
email |
text |
no | — |
nombre |
text |
sí | — |
creado_en |
timestamp with time zone |
no | now() |
ultimo_acceso_en |
timestamp with time zone |
sí | — |
rol |
text |
no | 'persona'::text |
Claves y restricciones:
- CHECK usuario_rol_conocido:
CHECK (rol = ANY (ARRAY['persona'::text, 'admin'::text])) - PK usuario_pkey:
PRIMARY KEY (id) - UNIQUE usuario_email_unique:
UNIQUE (email)
Interacción y escucha
acceso_cancion_usuario
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
usuario_id |
text |
no | — |
cancion_id |
text |
no | — |
concedido_en |
timestamp with time zone |
no | now() |
Claves y restricciones:
- FK acceso_cancion_usuario_cancion_id_cancion_id_fk:
FOREIGN KEY (cancion_id) REFERENCES cancion(id) ON DELETE CASCADE - FK acceso_cancion_usuario_usuario_id_usuario_id_fk:
FOREIGN KEY (usuario_id) REFERENCES usuario(id) ON DELETE CASCADE - PK acceso_cancion_usuario_usuario_id_cancion_id_pk:
PRIMARY KEY (usuario_id, cancion_id)
Índices adicionales: acceso_cancion_usuario_cancion.
favorito
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
usuario_id |
text |
no | — |
marcado_en |
timestamp with time zone |
no | now() |
cancion_id |
text |
no | — |
Claves y restricciones:
- FK favorito_cancion_id_cancion_id_fk:
FOREIGN KEY (cancion_id) REFERENCES cancion(id) ON DELETE CASCADE - FK favorito_usuario_id_usuario_id_fk:
FOREIGN KEY (usuario_id) REFERENCES usuario(id) ON DELETE CASCADE - PK favorito_usuario_id_cancion_id_pk:
PRIMARY KEY (usuario_id, cancion_id)
Índices adicionales: idx_favorito_usuario.
lista_reproduccion
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
id |
text |
no | — |
usuario_id |
text |
no | — |
nombre |
text |
no | — |
creada_en |
timestamp with time zone |
no | now() |
actualizada_en |
timestamp with time zone |
no | now() |
Claves y restricciones:
- CHECK lista_reproduccion_nombre_valido:
CHECK (NULLIF(btrim(nombre), ''::text) IS NOT NULL AND char_length(btrim(nombre)) <= 80) - FK lista_reproduccion_usuario_id_usuario_id_fk:
FOREIGN KEY (usuario_id) REFERENCES usuario(id) ON DELETE CASCADE - PK lista_reproduccion_pkey:
PRIMARY KEY (id)
Índices adicionales: lista_reproduccion_nombre_usuario, lista_reproduccion_usuario.
lista_reproduccion_cancion
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
lista_id |
text |
no | — |
cancion_id |
text |
no | — |
orden |
integer |
no | — |
anadida_en |
timestamp with time zone |
no | now() |
Claves y restricciones:
- CHECK lista_reproduccion_orden_positivo:
CHECK (orden >= 0) - FK lista_reproduccion_cancion_cancion_id_cancion_id_fk:
FOREIGN KEY (cancion_id) REFERENCES cancion(id) ON DELETE CASCADE - FK lista_reproduccion_cancion_lista_id_lista_reproduccion_id_fk:
FOREIGN KEY (lista_id) REFERENCES lista_reproduccion(id) ON DELETE CASCADE - PK lista_reproduccion_cancion_lista_id_cancion_id_pk:
PRIMARY KEY (lista_id, cancion_id)
Índices adicionales: lista_reproduccion_cancion_tema, lista_reproduccion_orden_unico.
reproduccion
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
id |
text |
no | — |
usuario_id |
text |
sí | — |
segundos |
integer |
no | 0 |
dia |
text |
no | — |
creado_en |
timestamp with time zone |
no | now() |
cancion_id |
text |
no | — |
Claves y restricciones:
- FK reproduccion_cancion_id_cancion_id_fk:
FOREIGN KEY (cancion_id) REFERENCES cancion(id) ON DELETE CASCADE - FK reproduccion_usuario_id_usuario_id_fk:
FOREIGN KEY (usuario_id) REFERENCES usuario(id) ON DELETE SET NULL - PK reproduccion_pkey:
PRIMARY KEY (id)
Índices adicionales: reproduccion_cancion, reproduccion_dia, reproduccion_usuario.
valoracion
Interacción unificada por cuenta y canción. like alimenta el contador público; value conserva la puntuación de 1 a 5 para un uso profesional posterior. Son independientes.
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
usuario_id |
text |
no | — |
value |
integer |
sí | — |
date |
timestamp with time zone |
no | now() |
actualizada_en |
timestamp with time zone |
no | now() |
cancion_id |
text |
no | — |
like |
boolean |
no | false |
Claves y restricciones:
- CHECK valoracion_de_uno_a_cinco:
CHECK (value >= 1 AND value <= 5) - FK valoracion_cancion_id_cancion_id_fk:
FOREIGN KEY (cancion_id) REFERENCES cancion(id) ON DELETE CASCADE - FK valoracion_usuario_id_usuario_id_fk:
FOREIGN KEY (usuario_id) REFERENCES usuario(id) ON DELETE CASCADE - PK valoracion_usuario_id_cancion_id_pk:
PRIMARY KEY (usuario_id, cancion_id)
Índices adicionales: idx_valoracion_cancion.
Comercio
carrito
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
id |
text |
no | — |
usuario_id |
text |
sí | — |
creado_en |
timestamp with time zone |
no | now() |
actualizado_en |
timestamp with time zone |
no | now() |
Claves y restricciones:
- FK carrito_usuario_id_usuario_id_fk:
FOREIGN KEY (usuario_id) REFERENCES usuario(id) ON DELETE CASCADE - PK carrito_pkey:
PRIMARY KEY (id)
Índices adicionales: carrito_usuario_unico.
carrito_item
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
carrito_id |
text |
no | — |
anadido_en |
timestamp with time zone |
no | now() |
cancion_id |
text |
no | — |
Claves y restricciones:
- FK carrito_item_cancion_id_cancion_id_fk:
FOREIGN KEY (cancion_id) REFERENCES cancion(id) ON DELETE CASCADE - FK carrito_item_carrito_id_carrito_id_fk:
FOREIGN KEY (carrito_id) REFERENCES carrito(id) ON DELETE CASCADE - PK carrito_item_carrito_id_cancion_id_pk:
PRIMARY KEY (carrito_id, cancion_id)
carrito_producto
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
carrito_id |
text |
no | — |
producto_id |
text |
no | — |
cantidad |
integer |
no | 1 |
anadido_en |
timestamp with time zone |
no | now() |
Claves y restricciones:
- CHECK carrito_producto_cantidad_positiva:
CHECK (cantidad > 0) - FK carrito_producto_carrito_id_carrito_id_fk:
FOREIGN KEY (carrito_id) REFERENCES carrito(id) ON DELETE CASCADE - FK carrito_producto_producto_id_producto_id_fk:
FOREIGN KEY (producto_id) REFERENCES producto(id) ON DELETE CASCADE - PK carrito_producto_carrito_id_producto_id_pk:
PRIMARY KEY (carrito_id, producto_id)
compra
Permiso materializado de descarga de una canción adquirida.
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
usuario_id |
text |
no | — |
pedido_id |
text |
no | — |
comprado_en |
timestamp with time zone |
no | now() |
cancion_id |
text |
no | — |
Claves y restricciones:
- FK compra_cancion_id_cancion_id_fk:
FOREIGN KEY (cancion_id) REFERENCES cancion(id) ON DELETE RESTRICT - FK compra_pedido_id_pedido_id_fk:
FOREIGN KEY (pedido_id) REFERENCES pedido(id) ON DELETE CASCADE - FK compra_usuario_id_usuario_id_fk:
FOREIGN KEY (usuario_id) REFERENCES usuario(id) ON DELETE CASCADE - PK compra_usuario_id_cancion_id_pk:
PRIMARY KEY (usuario_id, cancion_id)
intencion_pago
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
id |
text |
no | — |
usuario_id |
text |
no | — |
huella |
text |
no | — |
datos |
jsonb |
no | — |
sesion_pago_id |
text |
sí | — |
estado |
text |
no | 'abierta'::text |
creado_en |
timestamp with time zone |
no | now() |
Claves y restricciones:
- FK intencion_pago_usuario_id_usuario_id_fk:
FOREIGN KEY (usuario_id) REFERENCES usuario(id) ON DELETE CASCADE - PK intencion_pago_pkey:
PRIMARY KEY (id) - UNIQUE intencion_pago_sesion_pago_id_unique:
UNIQUE (sesion_pago_id)
Índices adicionales: intencion_pago_abierta.
pedido
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
id |
text |
no | — |
usuario_id |
text |
no | — |
sesion_pago_id |
text |
no | — |
estado |
text |
no | 'pendiente'::text |
packs |
integer |
no | — |
total_centimos |
integer |
no | — |
moneda |
text |
no | 'eur'::text |
creado_en |
timestamp with time zone |
no | now() |
pagado_en |
timestamp with time zone |
sí | — |
Claves y restricciones:
- FK pedido_usuario_id_usuario_id_fk:
FOREIGN KEY (usuario_id) REFERENCES usuario(id) ON DELETE CASCADE - PK pedido_pkey:
PRIMARY KEY (id) - UNIQUE pedido_sesion_pago_id_unique:
UNIQUE (sesion_pago_id)
Índices adicionales: pedido_usuario.
pedido_item
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
pedido_id |
text |
no | — |
titulo |
text |
no | — |
cancion_id |
text |
no | — |
Claves y restricciones:
- FK pedido_item_cancion_id_cancion_id_fk:
FOREIGN KEY (cancion_id) REFERENCES cancion(id) ON DELETE RESTRICT - FK pedido_item_pedido_id_pedido_id_fk:
FOREIGN KEY (pedido_id) REFERENCES pedido(id) ON DELETE CASCADE - PK pedido_item_pedido_id_cancion_id_pk:
PRIMARY KEY (pedido_id, cancion_id)
pedido_linea
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
pedido_id |
text |
no | — |
codigo |
text |
no | — |
producto_id |
text |
sí | — |
tipo |
text |
no | — |
nombre |
text |
no | — |
descripcion |
text |
sí | — |
cantidad |
integer |
no | — |
precio_unitario_centimos |
integer |
no | — |
total_centimos |
integer |
no | — |
moneda |
text |
no | — |
modalidad |
text |
no | — |
datos |
jsonb |
no | '{}'::jsonb |
Claves y restricciones:
- CHECK pedido_linea_cantidad_positiva:
CHECK (cantidad > 0) - CHECK pedido_linea_datos_objeto:
CHECK (jsonb_typeof(datos) = 'object'::text) - CHECK pedido_linea_importes_validos:
CHECK (precio_unitario_centimos >= 0 AND total_centimos = (precio_unitario_centimos * cantidad)) - CHECK pedido_linea_modalidad_conocida:
CHECK (modalidad = ANY (ARRAY['pago_unico'::text, 'suscripcion'::text])) - CHECK pedido_linea_moneda_iso:
CHECK (moneda ~ '^[a-z]{3}$'::text) - CHECK pedido_linea_tipo_conocido:
CHECK (tipo = ANY (ARRAY['pack_canciones'::text, 'libro'::text, 'partitura'::text, 'midi'::text, 'stems'::text, 'servicio'::text, 'suscripcion'::text])) - FK pedido_linea_pedido_id_pedido_id_fk:
FOREIGN KEY (pedido_id) REFERENCES pedido(id) ON DELETE CASCADE - FK pedido_linea_producto_id_producto_id_fk:
FOREIGN KEY (producto_id) REFERENCES producto(id) ON DELETE SET NULL - PK pedido_linea_pedido_id_codigo_pk:
PRIMARY KEY (pedido_id, codigo)
Índices adicionales: pedido_linea_tipo.
producto
Oferta comercial genérica; sus datos específicos se conservan en JSON.
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
id |
text |
no | — |
codigo |
text |
no | — |
tipo |
text |
no | — |
nombre |
text |
no | — |
descripcion |
text |
sí | — |
estado |
text |
no | 'borrador'::text |
precio_centimos |
integer |
no | — |
moneda |
text |
no | 'eur'::text |
metadatos |
jsonb |
no | '{}'::jsonb |
creado_en |
timestamp with time zone |
no | now() |
actualizado_en |
timestamp with time zone |
no | now() |
Claves y restricciones:
- CHECK producto_codigo_no_vacio:
CHECK (btrim(codigo) <> ''::text) - CHECK producto_estado_conocido:
CHECK (estado = ANY (ARRAY['borrador'::text, 'disponible'::text, 'retirado'::text])) - CHECK producto_metadatos_objeto:
CHECK (jsonb_typeof(metadatos) = 'object'::text) - CHECK producto_moneda_iso:
CHECK (moneda ~ '^[a-z]{3}$'::text) - CHECK producto_nombre_no_vacio:
CHECK (btrim(nombre) <> ''::text) - CHECK producto_precio_no_negativo:
CHECK (precio_centimos >= 0) - CHECK producto_tipo_conocido:
CHECK (tipo = ANY (ARRAY['libro'::text, 'partitura'::text, 'midi'::text, 'stems'::text, 'servicio'::text])) - PK producto_pkey:
PRIMARY KEY (id) - UNIQUE producto_codigo_unique:
UNIQUE (codigo)
Índices adicionales: producto_tipo_estado.
Facturación
contador_factura
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
serie |
text |
no | — |
ultimo_numero |
integer |
no | 0 |
actualizado_en |
timestamp with time zone |
no | now() |
Claves y restricciones:
- PK contador_factura_pkey:
PRIMARY KEY (serie)
datos_facturacion
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
id |
text |
no | — |
usuario_id |
text |
no | — |
tipo |
text |
no | 'particular'::text |
nombre |
text |
no | — |
nif |
text |
sí | — |
direccion |
text |
sí | — |
cp |
text |
sí | — |
ciudad |
text |
sí | — |
provincia |
text |
sí | — |
pais_codigo |
character(2) |
no | — |
predeterminada |
boolean |
no | false |
creado_en |
timestamp with time zone |
no | now() |
actualizado_en |
timestamp with time zone |
sí | — |
Claves y restricciones:
- FK datos_facturacion_pais_codigo_pais_codigo_fk:
FOREIGN KEY (pais_codigo) REFERENCES pais(codigo) - FK datos_facturacion_usuario_id_usuario_id_fk:
FOREIGN KEY (usuario_id) REFERENCES usuario(id) ON DELETE CASCADE - PK datos_facturacion_pkey:
PRIMARY KEY (id)
Índices adicionales: datos_facturacion_usuario.
descarga
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
id |
text |
no | — |
usuario_id |
text |
no | — |
bajada_en |
timestamp with time zone |
no | now() |
ip |
text |
sí | — |
agente |
text |
sí | — |
cancion_id |
text |
no | — |
Claves y restricciones:
- FK descarga_cancion_id_cancion_id_fk:
FOREIGN KEY (cancion_id) REFERENCES cancion(id) ON DELETE RESTRICT - FK descarga_usuario_id_usuario_id_fk:
FOREIGN KEY (usuario_id) REFERENCES usuario(id) ON DELETE CASCADE - PK descarga_pkey:
PRIMARY KEY (id)
Índices adicionales: descarga_fecha, descarga_usuario.
factura
Documento fiscal inmutable; una rectificativa referencia otra factura.
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
id |
text |
no | — |
pedido_id |
text |
no | — |
serie |
text |
no | — |
numero |
integer |
no | — |
tipo |
text |
no | 'normal'::text |
rectifica_a_id |
text |
sí | — |
fecha |
timestamp with time zone |
no | now() |
base_centimos |
integer |
no | — |
iva_tipo |
integer |
no | — |
iva_cuota_centimos |
integer |
no | — |
total_centimos |
integer |
no | — |
moneda |
text |
no | 'eur'::text |
datos_congelados |
jsonb |
no | — |
pais_codigo |
character(2) |
no | — |
Claves y restricciones:
- CHECK factura_rectificativa_apunta:
CHECK ((tipo = 'rectificativa'::text) = (rectifica_a_id IS NOT NULL)) - FK factura_pais_codigo_pais_codigo_fk:
FOREIGN KEY (pais_codigo) REFERENCES pais(codigo) - FK factura_pedido_id_pedido_id_fk:
FOREIGN KEY (pedido_id) REFERENCES pedido(id) - FK factura_rectifica_fk:
FOREIGN KEY (rectifica_a_id) REFERENCES factura(id) - PK factura_pkey:
PRIMARY KEY (id)
Índices adicionales: factura_fecha, factura_pedido, factura_serie_numero.
Editorial y legal
documento_legal
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
id |
text |
no | — |
slug |
text |
no | — |
titulo |
text |
no | — |
resumen |
text |
no | ''::text |
orden |
integer |
no | 0 |
version_vigente_id |
text |
sí | — |
Claves y restricciones:
- FK documento_legal_version_vigente_fk:
FOREIGN KEY (version_vigente_id) REFERENCES version_legal(id) ON DELETE SET NULL - PK documento_legal_pkey:
PRIMARY KEY (id) - UNIQUE documento_legal_slug_unique:
UNIQUE (slug)
entrada
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
id |
text |
no | — |
slug |
text |
no | — |
titulo |
text |
no | — |
fecha |
text |
no | — |
resumen |
text |
no | ''::text |
cuerpo |
text |
no | ''::text |
imagen_id |
text |
sí | — |
estado |
text |
no | 'borrador'::text |
creado_en |
timestamp with time zone |
no | now() |
actualizado_en |
timestamp with time zone |
sí | — |
secciones |
jsonb |
no | '[]'::jsonb |
presentacion |
jsonb |
no | '{}'::jsonb |
Claves y restricciones:
- CHECK entrada_presentacion_objeto:
CHECK (jsonb_typeof(presentacion) = 'object'::text) - CHECK entrada_secciones_array:
CHECK (jsonb_typeof(secciones) = 'array'::text) - FK entrada_imagen_id_medio_id_fk:
FOREIGN KEY (imagen_id) REFERENCES medio(id) ON DELETE SET NULL - PK entrada_pkey:
PRIMARY KEY (id) - UNIQUE entrada_slug_unique:
UNIQUE (slug)
Índices adicionales: entrada_fecha.
entrada_cancion
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
entrada_id |
text |
no | — |
cancion_id |
text |
no | — |
Claves y restricciones:
- FK entrada_cancion_cancion_id_cancion_id_fk:
FOREIGN KEY (cancion_id) REFERENCES cancion(id) ON DELETE CASCADE - FK entrada_cancion_entrada_id_entrada_id_fk:
FOREIGN KEY (entrada_id) REFERENCES entrada(id) ON DELETE CASCADE - PK entrada_cancion_entrada_id_cancion_id_pk:
PRIMARY KEY (entrada_id, cancion_id)
entrada_etiqueta
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
entrada_id |
text |
no | — |
etiqueta_id |
text |
no | — |
Claves y restricciones:
- FK entrada_etiqueta_entrada_id_entrada_id_fk:
FOREIGN KEY (entrada_id) REFERENCES entrada(id) ON DELETE CASCADE - FK entrada_etiqueta_etiqueta_id_etiqueta_id_fk:
FOREIGN KEY (etiqueta_id) REFERENCES etiqueta(id) ON DELETE CASCADE - PK entrada_etiqueta_entrada_id_etiqueta_id_pk:
PRIMARY KEY (entrada_id, etiqueta_id)
pagina
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
id |
text |
no | — |
slug |
text |
no | — |
titulo |
text |
no | — |
descripcion |
text |
no | ''::text |
cuerpo |
text |
no | ''::text |
estado |
text |
no | 'borrador'::text |
creado_en |
timestamp with time zone |
no | now() |
actualizado_en |
timestamp with time zone |
sí | — |
Claves y restricciones:
- PK pagina_pkey:
PRIMARY KEY (id) - UNIQUE pagina_slug_unique:
UNIQUE (slug)
redireccion
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
desde |
text |
no | — |
hacia |
text |
no | — |
permanente |
boolean |
no | true |
motivo |
text |
sí | — |
creada_en |
timestamp with time zone |
no | now() |
Claves y restricciones:
- PK redireccion_pkey:
PRIMARY KEY (desde)
Índices adicionales: redireccion_hacia.
version_legal
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
id |
text |
no | — |
documento_id |
text |
no | — |
cuerpo |
text |
no | — |
vigente_desde |
timestamp with time zone |
no | now() |
resumen_cambios |
text |
sí | — |
Claves y restricciones:
- FK version_legal_documento_id_documento_legal_id_fk:
FOREIGN KEY (documento_id) REFERENCES documento_legal(id) ON DELETE CASCADE - PK version_legal_pkey:
PRIMARY KEY (id)
Índices adicionales: version_legal_documento.
Taller de letras
acepcion
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
id |
text |
no | — |
termino_id |
text |
no | — |
numero |
integer |
no | — |
categoria |
text |
no | — |
definicion |
text |
no | — |
ampliacion |
text |
sí | — |
ejemplo |
text |
sí | — |
Claves y restricciones:
- FK acepcion_termino_id_termino_id_fk:
FOREIGN KEY (termino_id) REFERENCES termino(id) ON DELETE CASCADE - PK acepcion_pkey:
PRIMARY KEY (id)
Índices adicionales: acepcion_numero.
animo
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
id |
text |
no | — |
codigo |
text |
no | — |
nombre |
text |
no | — |
gems |
text |
sí | — |
valencia |
integer |
sí | — |
energia |
integer |
sí | — |
descripcion |
text |
sí | — |
Claves y restricciones:
- PK animo_pkey:
PRIMARY KEY (id) - UNIQUE animo_codigo_unique:
UNIQUE (codigo)
cancion_genero
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
cancion_id |
text |
no | — |
genero_id |
text |
no | — |
Claves y restricciones:
- FK cancion_genero_cancion_id_cancion_id_fk:
FOREIGN KEY (cancion_id) REFERENCES cancion(id) ON DELETE CASCADE - FK cancion_genero_genero_id_genero_id_fk:
FOREIGN KEY (genero_id) REFERENCES genero(id) ON DELETE CASCADE - PK cancion_genero_cancion_id_genero_id_pk:
PRIMARY KEY (cancion_id, genero_id)
capitulo
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
id |
text |
no | — |
slug |
text |
no | — |
titulo |
text |
no | — |
tipo |
text |
no | — |
genero_id |
text |
sí | — |
orden |
integer |
no | 0 |
resumen |
text |
no | ''::text |
cuerpo |
text |
no | ''::text |
estado |
text |
no | 'borrador'::text |
creado_en |
timestamp with time zone |
no | now() |
actualizado_en |
timestamp with time zone |
sí | — |
Claves y restricciones:
- FK capitulo_genero_id_genero_id_fk:
FOREIGN KEY (genero_id) REFERENCES genero(id) ON DELETE SET NULL - PK capitulo_pkey:
PRIMARY KEY (id) - UNIQUE capitulo_slug_unique:
UNIQUE (slug)
Índices adicionales: capitulo_tipo.
capitulo_acepcion
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
capitulo_id |
text |
no | — |
acepcion_id |
text |
no | — |
automatico |
boolean |
no | true |
confirmado |
boolean |
no | false |
Claves y restricciones:
- FK capitulo_acepcion_acepcion_id_acepcion_id_fk:
FOREIGN KEY (acepcion_id) REFERENCES acepcion(id) ON DELETE CASCADE - FK capitulo_acepcion_capitulo_id_capitulo_id_fk:
FOREIGN KEY (capitulo_id) REFERENCES capitulo(id) ON DELETE CASCADE - PK capitulo_acepcion_capitulo_id_acepcion_id_pk:
PRIMARY KEY (capitulo_id, acepcion_id)
compas
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
id |
text |
no | — |
codigo |
text |
no | — |
nombre |
text |
sí | — |
numerador |
integer |
no | — |
denominador |
integer |
no | — |
nota |
text |
sí | — |
Claves y restricciones:
- PK compas_pkey:
PRIMARY KEY (id) - UNIQUE compas_codigo_unique:
UNIQUE (codigo)
genero
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
id |
text |
no | — |
slug |
text |
no | — |
nombre |
text |
no | — |
resumen |
text |
no | ''::text |
origen_lugar |
text |
sí | — |
origen_ano |
integer |
sí | — |
tempo |
text |
sí | — |
rima |
text |
sí | — |
metrica_nota |
text |
sí | — |
compas_nota |
text |
sí | — |
rasgos |
text[] |
sí | — |
estado |
text |
no | 'borrador'::text |
origen |
text |
no | 'manual'::text |
modelo_origen |
text |
sí | — |
importado_en |
timestamp with time zone |
sí | — |
revisado_por |
text |
sí | — |
revisado_en |
timestamp with time zone |
sí | — |
creado_en |
timestamp with time zone |
no | now() |
actualizado_en |
timestamp with time zone |
sí | — |
Claves y restricciones:
- PK genero_pkey:
PRIMARY KEY (id) - UNIQUE genero_slug_unique:
UNIQUE (slug)
Índices adicionales: genero_nombre, genero_origen_ano.
genero_alias
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
id |
text |
no | — |
genero_id |
text |
no | — |
nombre |
text |
no | — |
pais_codigo |
character(2) |
sí | — |
nota |
text |
sí | — |
Claves y restricciones:
- FK genero_alias_genero_id_genero_id_fk:
FOREIGN KEY (genero_id) REFERENCES genero(id) ON DELETE CASCADE - FK genero_alias_pais_codigo_pais_codigo_fk:
FOREIGN KEY (pais_codigo) REFERENCES pais(codigo) - PK genero_alias_pkey:
PRIMARY KEY (id)
Índices adicionales: genero_alias_nombre.
genero_compas
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
genero_id |
text |
no | — |
compas_id |
text |
no | — |
principal |
boolean |
no | false |
nota |
text |
sí | — |
Claves y restricciones:
- FK genero_compas_compas_id_compas_id_fk:
FOREIGN KEY (compas_id) REFERENCES compas(id) - FK genero_compas_genero_id_genero_id_fk:
FOREIGN KEY (genero_id) REFERENCES genero(id) ON DELETE CASCADE - PK genero_compas_genero_id_compas_id_pk:
PRIMARY KEY (genero_id, compas_id)
genero_instrumento
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
genero_id |
text |
no | — |
instrumento_id |
text |
no | — |
importancia |
text |
no | 'habitual'::text |
papel |
text |
sí | — |
orden |
integer |
no | 0 |
Claves y restricciones:
- FK genero_instrumento_genero_id_genero_id_fk:
FOREIGN KEY (genero_id) REFERENCES genero(id) ON DELETE CASCADE - FK genero_instrumento_instrumento_id_instrumento_id_fk:
FOREIGN KEY (instrumento_id) REFERENCES instrumento(id) - PK genero_instrumento_genero_id_instrumento_id_pk:
PRIMARY KEY (genero_id, instrumento_id)
genero_metro
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
genero_id |
text |
no | — |
metro_id |
text |
no | — |
predominante |
boolean |
no | false |
Claves y restricciones:
- FK genero_metro_genero_id_genero_id_fk:
FOREIGN KEY (genero_id) REFERENCES genero(id) ON DELETE CASCADE - FK genero_metro_metro_id_metro_id_fk:
FOREIGN KEY (metro_id) REFERENCES metro(id) - PK genero_metro_genero_id_metro_id_pk:
PRIMARY KEY (genero_id, metro_id)
genero_origen
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
genero_id |
text |
no | — |
origen_id |
text |
no | — |
tipo |
text |
no | — |
principal |
boolean |
no | false |
nota |
text |
sí | — |
orden |
integer |
no | 0 |
Claves y restricciones:
- CHECK genero_origen_no_reflexivo:
CHECK (genero_id <> origen_id) - FK genero_origen_genero_id_genero_id_fk:
FOREIGN KEY (genero_id) REFERENCES genero(id) ON DELETE CASCADE - FK genero_origen_origen_id_genero_id_fk:
FOREIGN KEY (origen_id) REFERENCES genero(id) ON DELETE CASCADE - PK genero_origen_genero_id_origen_id_tipo_pk:
PRIMARY KEY (genero_id, origen_id, tipo)
Índices adicionales: genero_origen_origen, genero_origen_principal_unico.
Disparadores:
genero_sin_ciclos_trg:CREATE TRIGGER genero_sin_ciclos_trg BEFORE INSERT OR UPDATE ON genero_origen FOR EACH ROW EXECUTE FUNCTION genero_sin_ciclos()
genero_pais
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
genero_id |
text |
no | — |
pais_codigo |
character(2) |
no | — |
relacion |
text |
no | 'adoptado'::text |
nota |
text |
sí | — |
Claves y restricciones:
- FK genero_pais_genero_id_genero_id_fk:
FOREIGN KEY (genero_id) REFERENCES genero(id) ON DELETE CASCADE - FK genero_pais_pais_codigo_pais_codigo_fk:
FOREIGN KEY (pais_codigo) REFERENCES pais(codigo) - PK genero_pais_genero_id_pais_codigo_pk:
PRIMARY KEY (genero_id, pais_codigo)
genero_persona
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
genero_id |
text |
no | — |
persona_id |
text |
no | — |
papel |
text |
no | — |
nota |
text |
sí | — |
orden |
integer |
no | 0 |
Claves y restricciones:
- FK genero_persona_genero_id_genero_id_fk:
FOREIGN KEY (genero_id) REFERENCES genero(id) ON DELETE CASCADE - FK genero_persona_persona_id_persona_id_fk:
FOREIGN KEY (persona_id) REFERENCES persona(id) - PK genero_persona_genero_id_persona_id_papel_pk:
PRIMARY KEY (genero_id, persona_id, papel)
genero_seccion
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
id |
text |
no | — |
genero_id |
text |
no | — |
clave |
text |
no | — |
titulo |
text |
no | — |
cuerpo |
text |
no | — |
orden |
integer |
no | 0 |
Claves y restricciones:
- FK genero_seccion_genero_id_genero_id_fk:
FOREIGN KEY (genero_id) REFERENCES genero(id) ON DELETE CASCADE - PK genero_seccion_pkey:
PRIMARY KEY (id)
Índices adicionales: genero_seccion_clave.
genero_tema
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
genero_id |
text |
no | — |
etiqueta_id |
text |
no | — |
orden |
integer |
no | 0 |
Claves y restricciones:
- FK genero_tema_etiqueta_id_etiqueta_id_fk:
FOREIGN KEY (etiqueta_id) REFERENCES etiqueta(id) ON DELETE CASCADE - FK genero_tema_genero_id_genero_id_fk:
FOREIGN KEY (genero_id) REFERENCES genero(id) ON DELETE CASCADE - PK genero_tema_genero_id_etiqueta_id_pk:
PRIMARY KEY (genero_id, etiqueta_id)
instrumento
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
id |
text |
no | — |
slug |
text |
no | — |
nombre |
text |
no | — |
familia |
text |
no | — |
subfamilia |
text |
sí | — |
pais_codigo |
character(2) |
sí | — |
descripcion |
text |
sí | — |
afinacion |
text |
sí | — |
imagen_id |
text |
sí | — |
muestra_id |
text |
sí | — |
estado |
text |
no | 'borrador'::text |
origen |
text |
no | 'manual'::text |
modelo_origen |
text |
sí | — |
importado_en |
timestamp with time zone |
sí | — |
revisado_por |
text |
sí | — |
revisado_en |
timestamp with time zone |
sí | — |
Claves y restricciones:
- FK instrumento_imagen_id_medio_id_fk:
FOREIGN KEY (imagen_id) REFERENCES medio(id) ON DELETE SET NULL - FK instrumento_muestra_id_medio_id_fk:
FOREIGN KEY (muestra_id) REFERENCES medio(id) ON DELETE SET NULL - FK instrumento_pais_codigo_pais_codigo_fk:
FOREIGN KEY (pais_codigo) REFERENCES pais(codigo) - PK instrumento_pkey:
PRIMARY KEY (id) - UNIQUE instrumento_slug_unique:
UNIQUE (slug)
Índices adicionales: instrumento_familia.
metro
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
id |
text |
no | — |
codigo |
text |
no | — |
nombre |
text |
no | — |
silabas |
integer |
sí | — |
termino_id |
text |
sí | — |
nota |
text |
sí | — |
Claves y restricciones:
- FK metro_termino_fk:
FOREIGN KEY (termino_id) REFERENCES termino(id) ON DELETE SET NULL - PK metro_pkey:
PRIMARY KEY (id) - UNIQUE metro_codigo_unique:
UNIQUE (codigo)
modelo_ia
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
id |
text |
no | — |
codigo |
text |
no | — |
familia |
text |
no | — |
version |
text |
no | — |
nombre |
text |
no | — |
vigente |
boolean |
no | true |
nota_sintaxis |
text |
sí | — |
esquema |
jsonb |
sí | — |
Claves y restricciones:
- PK modelo_ia_pkey:
PRIMARY KEY (id) - UNIQUE modelo_ia_codigo_unique:
UNIQUE (codigo)
Índices adicionales: modelo_ia_familia.
obra_referencia
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
id |
text |
no | — |
slug |
text |
no | — |
titulo |
text |
no | — |
ano |
integer |
sí | — |
genero_id |
text |
sí | — |
nota |
text |
sí | — |
cita |
text |
sí | — |
estado |
text |
no | 'borrador'::text |
origen |
text |
no | 'manual'::text |
modelo_origen |
text |
sí | — |
importado_en |
timestamp with time zone |
sí | — |
revisado_por |
text |
sí | — |
revisado_en |
timestamp with time zone |
sí | — |
Claves y restricciones:
- FK obra_referencia_genero_id_genero_id_fk:
FOREIGN KEY (genero_id) REFERENCES genero(id) ON DELETE SET NULL - PK obra_referencia_pkey:
PRIMARY KEY (id) - UNIQUE obra_referencia_slug_unique:
UNIQUE (slug)
Índices adicionales: obra_referencia_genero.
obra_referencia_enlace
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
obra_id |
text |
no | — |
plataforma |
text |
no | — |
url |
text |
no | — |
Claves y restricciones:
- FK obra_referencia_enlace_obra_id_obra_referencia_id_fk:
FOREIGN KEY (obra_id) REFERENCES obra_referencia(id) ON DELETE CASCADE - PK obra_referencia_enlace_obra_id_plataforma_pk:
PRIMARY KEY (obra_id, plataforma)
obra_referencia_persona
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
obra_id |
text |
no | — |
persona_id |
text |
no | — |
papel |
text |
no | — |
orden |
integer |
no | 0 |
Claves y restricciones:
- FK obra_referencia_persona_obra_id_obra_referencia_id_fk:
FOREIGN KEY (obra_id) REFERENCES obra_referencia(id) ON DELETE CASCADE - FK obra_referencia_persona_persona_id_persona_id_fk:
FOREIGN KEY (persona_id) REFERENCES persona(id) - PK obra_referencia_persona_obra_id_persona_id_papel_pk:
PRIMARY KEY (obra_id, persona_id, papel)
prompt
Prompt probado para un modelo de IA, género, ánimo y, opcionalmente, una canción resultante.
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
id |
text |
no | — |
modelo_ia_id |
text |
no | — |
genero_id |
text |
sí | — |
animo_id |
text |
sí | — |
idioma |
text |
no | 'en'::text |
contenido |
jsonb |
no | — |
notas |
text |
sí | — |
valoracion |
integer |
sí | — |
ejemplo_id |
text |
sí | — |
preferido |
boolean |
no | false |
visibilidad |
text |
no | 'privado'::text |
estado |
text |
no | 'borrador'::text |
creado_en |
timestamp with time zone |
no | now() |
actualizado_en |
timestamp with time zone |
sí | — |
cancion_id |
text |
sí | — |
Claves y restricciones:
- FK prompt_animo_id_animo_id_fk:
FOREIGN KEY (animo_id) REFERENCES animo(id) - FK prompt_cancion_id_cancion_id_fk:
FOREIGN KEY (cancion_id) REFERENCES cancion(id) ON DELETE CASCADE - FK prompt_ejemplo_id_medio_id_fk:
FOREIGN KEY (ejemplo_id) REFERENCES medio(id) ON DELETE SET NULL - FK prompt_genero_id_genero_id_fk:
FOREIGN KEY (genero_id) REFERENCES genero(id) ON DELETE CASCADE - FK prompt_modelo_ia_id_modelo_ia_id_fk:
FOREIGN KEY (modelo_ia_id) REFERENCES modelo_ia(id) - PK prompt_pkey:
PRIMARY KEY (id)
Índices adicionales: prompt_animo, prompt_cancion, prompt_genero, prompt_modelo.
termino
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
id |
text |
no | — |
slug |
text |
no | — |
termino |
text |
no | — |
Claves y restricciones:
- PK termino_pkey:
PRIMARY KEY (id) - UNIQUE termino_slug_unique:
UNIQUE (slug) - UNIQUE termino_termino_unique:
UNIQUE (termino)
termino_variante
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
termino_id |
text |
no | — |
forma |
text |
no | — |
Claves y restricciones:
- FK termino_variante_termino_id_termino_id_fk:
FOREIGN KEY (termino_id) REFERENCES termino(id) ON DELETE CASCADE - PK termino_variante_termino_id_forma_pk:
PRIMARY KEY (termino_id, forma)
verso
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
id |
text |
no | — |
genero_id |
text |
no | — |
titulo |
text |
no | — |
ilustra |
text |
no | — |
fuente |
text |
no | 'ejemplo'::text |
analisis |
text |
sí | — |
medida |
text |
sí | — |
rima |
text |
sí | — |
obra_id |
text |
sí | — |
cancion_id |
text |
sí | — |
orden |
integer |
no | 0 |
estado |
text |
no | 'borrador'::text |
origen |
text |
no | 'manual'::text |
modelo_origen |
text |
sí | — |
importado_en |
timestamp with time zone |
sí | — |
revisado_por |
text |
sí | — |
revisado_en |
timestamp with time zone |
sí | — |
Claves y restricciones:
- CHECK verso_cita_acredita:
CHECK (fuente <> 'cita'::text OR obra_id IS NOT NULL) - CHECK verso_propio_apunta:
CHECK (fuente <> 'propio'::text OR cancion_id IS NOT NULL) - FK verso_cancion_id_cancion_id_fk:
FOREIGN KEY (cancion_id) REFERENCES cancion(id) ON DELETE SET NULL - FK verso_genero_id_genero_id_fk:
FOREIGN KEY (genero_id) REFERENCES genero(id) ON DELETE CASCADE - FK verso_obra_id_obra_referencia_id_fk:
FOREIGN KEY (obra_id) REFERENCES obra_referencia(id) ON DELETE SET NULL - PK verso_pkey:
PRIMARY KEY (id)
Índices adicionales: verso_genero.
verso_linea
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
verso_id |
text |
no | — |
numero |
integer |
no | — |
texto |
text |
no | — |
silabas |
text[] |
sí | — |
tonicas |
integer[] |
sí | — |
medida |
integer |
sí | — |
rima |
text |
sí | — |
Claves y restricciones:
- CHECK verso_linea_medida_creible:
CHECK (medida IS NULL OR medida >= 1 AND medida <= 20) - FK verso_linea_verso_id_verso_id_fk:
FOREIGN KEY (verso_id) REFERENCES verso(id) ON DELETE CASCADE - PK verso_linea_verso_id_numero_pk:
PRIMARY KEY (verso_id, numero)
Jukebox
jukebox
Programación independiente y versionada de una cuenta.
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
id |
text |
no | — |
usuario_id |
text |
no | — |
numero |
integer |
no | — |
zona_horaria |
text |
no | — |
franjas |
jsonb |
no | — |
revision |
integer |
no | 1 |
actualizada_en |
timestamp with time zone |
no | now() |
nombre |
text |
no | ''::text |
descripcion |
text |
no | ''::text |
Claves y restricciones:
- CHECK jukebox_franjas_array:
CHECK (jsonb_typeof(franjas) = 'array'::text) - CHECK jukebox_revision_positiva:
CHECK (revision > 0) - FK jukebox_usuario_id_fkey:
FOREIGN KEY (usuario_id) REFERENCES usuario(id) ON DELETE CASCADE - PK jukebox_pkey:
PRIMARY KEY (id)
Índices adicionales: jukebox_usuario_numero.
programacion_jukebox
Programación histórica por cuenta, conservada por compatibilidad con el modelo anterior de un único Jukebox.
| Columna | Tipo PostgreSQL | Nulo | Valor por defecto |
|---|---|---|---|
usuario_id |
text |
no | — |
zona_horaria |
text |
no | 'Europe/Madrid'::text |
franjas |
jsonb |
no | '[]'::jsonb |
revision |
integer |
no | 1 |
actualizada_en |
timestamp with time zone |
no | CURRENT_TIMESTAMP |
Claves y restricciones:
- CHECK programacion_jukebox_franjas_array:
CHECK (jsonb_typeof(franjas) = 'array'::text) - CHECK programacion_jukebox_revision_positiva:
CHECK (revision > 0) - FK programacion_jukebox_usuario_id_fkey:
FOREIGN KEY (usuario_id) REFERENCES usuario(id) ON DELETE CASCADE - PK programacion_jukebox_pkey:
PRIMARY KEY (usuario_id)
Vistas
cancion_principal
| Columna | Tipo PostgreSQL | Nulo |
|---|---|---|
id |
text |
sí |
slug |
text |
sí |
titulo |
text |
sí |
version_de_id |
text |
sí |
version_nombre |
text |
sí |
version_orden |
integer |
sí |
estilo_id |
text |
sí |
album_id |
text |
sí |
numero |
integer |
sí |
duracion_s |
integer |
sí |
ano |
integer |
sí |
letra |
text |
sí |
idioma |
text |
sí |
inspiracion |
text |
sí |
tiene_letra |
boolean |
sí |
destacada |
boolean |
sí |
portada_id |
text |
sí |
ala_venta |
boolean |
sí |
estado |
text |
sí |
creado_en |
timestamp with time zone |
sí |
actualizado_en |
timestamp with time zone |
sí |
es_version |
boolean |
sí |
padre_no_es_version |
boolean |
sí |
version_nota |
text |
sí |
codigo |
text |
sí |
version_codigo |
text |
sí |
formacion_vocal |
formacion_vocal |
sí |
acceso |
acceso_cancion |
sí |
Definición:
SELECT id,
slug,
titulo,
version_de_id,
version_nombre,
version_orden,
estilo_id,
album_id,
numero,
duracion_s,
ano,
letra,
idioma,
inspiracion,
tiene_letra,
destacada,
portada_id,
ala_venta,
estado,
creado_en,
actualizado_en,
es_version,
padre_no_es_version,
version_nota,
codigo,
version_codigo,
formacion_vocal,
acceso
FROM cancion
WHERE version_de_id IS NULL;
Enumeraciones PostgreSQL
acceso_cancion:ninguna,publico,exclusiva,privada.formacion_vocal:hombre,mujer,dueto-femenino,dueto-masculino,dueto-mixto,multiple-mixto,multiple-femenino,multiple-masculino.
Los demás vocabularios cerrados se almacenan como text y aparecen en las restricciones CHECK de cada tabla.
Funciones de base de datos
| Función | Argumentos | Resultado | Lenguaje |
|---|---|---|---|
autoria_suma_cien |
— | trigger |
plpgsql |
comprobar_grabacion_publicable |
identificador text |
void |
plpgsql |
genero_sin_ciclos |
— | trigger |
plpgsql |
guardar_invariantes_publicacion |
— | trigger |
plpgsql |
Las funciones asociadas a disparadores se localizan además bajo la tabla afectada, en el apartado “Disparadores”.
Secuencias
| Secuencia | Tipo | Inicio | Incremento | Ciclo |
|---|---|---|---|---|
artista_codigo_seq |
bigint |
1 | 1 | no |
artista_virtual_codigo_seq |
bigint |
1 | 1 | no |
cancion_codigo_seq |
bigint |
1 | 1 | no |
Mantenimiento
Este documento se regenera desde la base aplicada:
node --env-file=.env scripts/db/documentar-modelo.mjs
Después de una migración, regénéralo y revisa también los contratos JSON si cambió su estructura TypeScript.