Skip to main content

Data Model: Migracions Recents

Aquest document descriu les migracions de base de dades afegides recentment i els canvis corresponents al model de dades.


Migració V45: DanceSong Join Entity

Fitxer: V45__create_dance_song_join_table.sql
Data: Gener 2026

Canvi

Transforma la relació @ManyToMany entre Dance i Song en una join entity DanceSong amb camps addicionals.

Esquema

CREATE TABLE dance_songs (
id BIGSERIAL PRIMARY KEY,
dance_id BIGINT NOT NULL REFERENCES dances(id) ON DELETE CASCADE,
song_id BIGINT NOT NULL REFERENCES songs(id) ON DELETE CASCADE,
role VARCHAR(20) NOT NULL DEFAULT 'PRIMARY',
sort_order INT NOT NULL DEFAULT 0,
notes TEXT,
created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
UNIQUE(dance_id, song_id)
);

Camps nous

CampTipusDescripció
rolePRIMARY | ALTERNATIVEIndica si és la cançó principal o una alternativa
sort_orderINTOrdre de visualització
notesTEXTNotes sobre l'associació

Regla de negoci

Si un ball té cançons associades, exactament una ha de tenir role = PRIMARY.

Validat a DanceService.validateSongsHaveExactlyOnePrimary().

DTOs afectats

// DanceDto.songs ara conté:
record DanceSongDto(
Long id,
Long songId,
String songTitle,
String songArtist,
DanceSongRole role,
Integer sortOrder,
String notes
)

// CreateDanceRequest.songs ara espera:
record DanceSongRequest(
Long songId,
DanceSongRole role, // Obligatori
Integer sortOrder,
String notes
)

Migració V46: LineDanceSpec Model

Fitxer: V46__create_line_dance_spec_tables.sql
Data: Gener 2026

Canvi

Afegeix suport per emmagatzemar l'especificació de passos d'un ball de línia.

Esquema

-- Especificació principal (1:1 amb Dance)
CREATE TABLE line_dance_specs (
dance_id BIGINT PRIMARY KEY REFERENCES dances(id) ON DELETE CASCADE,
status VARCHAR(20) NOT NULL DEFAULT 'DRAFT',
sequence_completeness VARCHAR(20) NOT NULL DEFAULT 'PARTIAL',
source_text TEXT,
notes TEXT,
created_by VARCHAR(255),
last_modified_by VARCHAR(255),
created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
);

-- Components (passos individuals)
CREATE TABLE line_dance_components (
id BIGSERIAL PRIMARY KEY,
spec_dance_id BIGINT NOT NULL REFERENCES line_dance_specs(dance_id) ON DELETE CASCADE,
component_type VARCHAR(20) NOT NULL,
code VARCHAR(10) NOT NULL,
counts INT,
label VARCHAR(100),
sort_order INT NOT NULL DEFAULT 0,
UNIQUE(spec_dance_id, code)
);

-- Seqüència (ordre d'execució)
CREATE TABLE line_dance_sequence_items (
id BIGSERIAL PRIMARY KEY,
spec_dance_id BIGINT NOT NULL REFERENCES line_dance_specs(dance_id) ON DELETE CASCADE,
order_index INT NOT NULL,
component_id BIGINT REFERENCES line_dance_components(id) ON DELETE SET NULL,
restart BOOLEAN NOT NULL DEFAULT FALSE,
note TEXT
);

Relacions

Dance (1) ←──── (1) LineDanceSpec

├──→ (N) LineDanceComponents

└──→ (N) LineDanceSequenceItems ───→ (1) Component

Enums

EnumValors
LineDanceSpecStatusDRAFT, PUBLISHED
SequenceCompletenessNONE, PARTIAL, FULL
ComponentTypeSTEP, TURN, TAG, BRIDGE, OTHER

Endpoints nous

MètodeEndpointDescripció
GET/api/dances/{id}/specObtenir especificació
PUT/api/dances/{id}/specCrear/actualitzar spec
PUT/api/dances/{id}/spec/componentsReemplaçar components
PUT/api/dances/{id}/spec/sequenceReemplaçar seqüència

Tots requereixen rol ADMIN.

DTO principal

record LineDanceSpecDto(
Long danceId,
String danceName,
LineDanceSpecStatus status,
SequenceCompleteness sequenceCompleteness,
String sourceText,
String notes,
List<LineDanceComponentDto> components,
List<LineDanceSequenceItemDto> sequence,
String createdBy,
String lastModifiedBy,
Instant createdAt,
Instant updatedAt
)

Diagrama ER actualitzat

┌─────────────┐       ┌─────────────────┐       ┌───────────┐
│ dances │──1:N──│ dance_songs │──N:1──│ songs │
└─────────────┘ └─────────────────┘ └───────────┘
│ │
│ ├── role (PRIMARY/ALTERNATIVE)
│ ├── sort_order
│ └── notes

│ 1:1

┌─────────────────────┐
│ line_dance_specs │
├─────────────────────┤
│ dance_id (PK, FK) │
│ status │
│ sequence_complete. │
│ source_text │
│ notes │
└─────────────────────┘

├── 1:N ──┐
│ ▼
│ ┌───────────────────────┐
│ │ line_dance_components │
│ ├───────────────────────┤
│ │ id (PK) │
│ │ spec_dance_id (FK) │
│ │ type, code, counts │
│ │ label, sort_order │
│ └───────────────────────┘
│ │
│ │ N:1
│ ▼
└── 1:N ──┐ ↑
▼ │
┌──────────────────────────┐
│ line_dance_sequence_items │
├──────────────────────────┤
│ id (PK) │
│ spec_dance_id (FK) │
│ order_index │
│ component_id (FK) ────────┘
│ restart (boolean) │
│ note │
└──────────────────────────┘

ADRs relacionades