Skip to content

Commit 9557ad4

Browse files
Merge pull request #131 from pierrick-fonquerne/80-scripts-sql
feat(database): consolidate SQL scripts and normalize schema (#80)
2 parents 45dfe47 + 8f0b2e8 commit 9557ad4

File tree

15 files changed

+1581
-290
lines changed

15 files changed

+1581
-290
lines changed

database/sql/000_migration_history.sql

Lines changed: 0 additions & 25 deletions
This file was deleted.

database/sql/001_create_tables.sql

Lines changed: 0 additions & 110 deletions
This file was deleted.

database/sql/001_init_schema.sql

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
BEGIN;
2+
3+
-- ============================================================================
4+
-- TABLE: roles
5+
-- User roles for authorization (User, Employee, Admin)
6+
-- ============================================================================
7+
CREATE TABLE roles (
8+
id SERIAL PRIMARY KEY,
9+
label VARCHAR(50) NOT NULL UNIQUE
10+
);
11+
12+
INSERT INTO roles (label) VALUES ('User'), ('Employee'), ('Admin');
13+
14+
-- ============================================================================
15+
-- TABLE: users
16+
-- Registered users of the application
17+
-- ============================================================================
18+
CREATE TABLE users (
19+
id SERIAL PRIMARY KEY,
20+
pseudo VARCHAR(50) NOT NULL UNIQUE,
21+
email VARCHAR(255) NOT NULL UNIQUE,
22+
password_hash VARCHAR(255) NOT NULL,
23+
is_suspended BOOLEAN NOT NULL DEFAULT FALSE,
24+
must_change_password BOOLEAN NOT NULL DEFAULT FALSE,
25+
role_id INTEGER NOT NULL REFERENCES roles(id),
26+
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
27+
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
28+
);
29+
30+
CREATE INDEX idx_users_email ON users(email);
31+
CREATE INDEX idx_users_pseudo ON users(pseudo);
32+
CREATE INDEX idx_users_role_id ON users(role_id);
33+
34+
-- Auto-update updated_at on row modification
35+
CREATE OR REPLACE FUNCTION update_updated_at_column()
36+
RETURNS TRIGGER AS $$
37+
BEGIN
38+
NEW.updated_at = CURRENT_TIMESTAMP;
39+
RETURN NEW;
40+
END;
41+
$$ LANGUAGE plpgsql;
42+
43+
CREATE TRIGGER trigger_users_updated_at
44+
BEFORE UPDATE ON users
45+
FOR EACH ROW
46+
EXECUTE FUNCTION update_updated_at_column();
47+
48+
-- ============================================================================
49+
-- TABLE: character_classes
50+
-- Game character classes (Guerrier, Mage, Archer, Voleur)
51+
-- ============================================================================
52+
CREATE TABLE character_classes (
53+
id SERIAL PRIMARY KEY,
54+
name VARCHAR(20) NOT NULL,
55+
description TEXT NOT NULL,
56+
icon_url VARCHAR(255),
57+
CONSTRAINT uq_character_classes_name UNIQUE (name)
58+
);
59+
60+
INSERT INTO character_classes (name, description) VALUES
61+
('Guerrier', 'Un combattant robuste qui excelle au corps à corps et peut porter des armures lourdes.'),
62+
('Mage', 'Un puissant lanceur de sorts qui manie la magie des arcanes mais porte des armures légères.'),
63+
('Archer', 'Un combattant à distance agile doté d''une précision mortelle et d''une armure intermédiaire.'),
64+
('Voleur', 'Un assassin furtif qui frappe depuis les ombres avec des attaques rapides.');
65+
66+
-- ============================================================================
67+
-- TABLE: equipment_slots
68+
-- Equipment slot positions (14 slots, WoW-inspired)
69+
-- ============================================================================
70+
CREATE TABLE equipment_slots (
71+
id SERIAL PRIMARY KEY,
72+
name VARCHAR(30) NOT NULL,
73+
display_order INT NOT NULL,
74+
CONSTRAINT uq_equipment_slots_name UNIQUE (name)
75+
);
76+
77+
INSERT INTO equipment_slots (name, display_order) VALUES
78+
('Tête', 1),
79+
('Épaules', 2),
80+
('Dos', 3),
81+
('Torse', 4),
82+
('Poignets', 5),
83+
('Mains', 6),
84+
('Taille', 7),
85+
('Jambes', 8),
86+
('Pieds', 9),
87+
('Cou', 10),
88+
('Anneau 1', 11),
89+
('Anneau 2', 12),
90+
('Main droite', 13),
91+
('Main gauche', 14);
92+
93+
-- ============================================================================
94+
-- TABLE: characters
95+
-- Player characters created by users
96+
-- ============================================================================
97+
CREATE TABLE characters (
98+
id SERIAL PRIMARY KEY,
99+
name VARCHAR(50) NOT NULL,
100+
class_id INTEGER NOT NULL REFERENCES character_classes(id) ON DELETE RESTRICT,
101+
gender VARCHAR(20) NOT NULL,
102+
status VARCHAR(20) NOT NULL DEFAULT 'draft',
103+
skin_color VARCHAR(7) NOT NULL,
104+
eye_color VARCHAR(7) NOT NULL,
105+
hair_color VARCHAR(7) NOT NULL,
106+
hair_style VARCHAR(50) NOT NULL,
107+
eye_shape VARCHAR(50) NOT NULL,
108+
nose_shape VARCHAR(50) NOT NULL,
109+
mouth_shape VARCHAR(50) NOT NULL,
110+
face_shape VARCHAR(50) NOT NULL,
111+
image BYTEA,
112+
is_shared BOOLEAN NOT NULL DEFAULT FALSE,
113+
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
114+
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
115+
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
116+
117+
CONSTRAINT uq_characters_name_per_user UNIQUE (name, user_id)
118+
);
119+
120+
CREATE INDEX idx_characters_user_id ON characters(user_id);
121+
CREATE INDEX idx_characters_status ON characters(status);
122+
CREATE INDEX idx_characters_gallery ON characters(is_shared, status)
123+
WHERE is_shared = TRUE AND status = 'approved';
124+
125+
-- ============================================================================
126+
-- TABLE: article_types
127+
-- Reference table for article categories
128+
-- ============================================================================
129+
CREATE TABLE article_types (
130+
id SERIAL PRIMARY KEY,
131+
name VARCHAR(50) NOT NULL UNIQUE
132+
);
133+
134+
INSERT INTO article_types (name) VALUES ('Clothing'), ('Armor'), ('Weapon'), ('Accessory');
135+
136+
-- ============================================================================
137+
-- TABLE: articles
138+
-- Customization items linked to a type and an equipment slot
139+
-- ============================================================================
140+
CREATE TABLE articles (
141+
id SERIAL PRIMARY KEY,
142+
name VARCHAR(100) NOT NULL,
143+
type_id INTEGER NOT NULL REFERENCES article_types(id) ON DELETE RESTRICT,
144+
slot_id INTEGER NOT NULL REFERENCES equipment_slots(id) ON DELETE RESTRICT,
145+
image BYTEA,
146+
is_active BOOLEAN NOT NULL DEFAULT TRUE
147+
);
148+
149+
CREATE INDEX idx_articles_type_id ON articles(type_id);
150+
CREATE INDEX idx_articles_slot_id ON articles(slot_id);
151+
CREATE INDEX idx_articles_active ON articles(is_active) WHERE is_active = TRUE;
152+
153+
-- ============================================================================
154+
-- TABLE: character_articles
155+
-- Many-to-many: characters <-> equipped articles
156+
-- ============================================================================
157+
CREATE TABLE character_articles (
158+
character_id INTEGER NOT NULL REFERENCES characters(id) ON DELETE CASCADE,
159+
article_id INTEGER NOT NULL REFERENCES articles(id) ON DELETE CASCADE,
160+
161+
PRIMARY KEY (character_id, article_id)
162+
);
163+
164+
-- ============================================================================
165+
-- TABLE: comments
166+
-- User reviews on shared characters
167+
-- ============================================================================
168+
CREATE TABLE comments (
169+
id SERIAL PRIMARY KEY,
170+
rating INTEGER NOT NULL CHECK (rating >= 1 AND rating <= 5),
171+
text TEXT NOT NULL,
172+
status VARCHAR(20) NOT NULL DEFAULT 'pending',
173+
commented_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
174+
rejection_reason VARCHAR(500),
175+
reviewed_at TIMESTAMP WITH TIME ZONE,
176+
reviewed_by_id INTEGER REFERENCES users(id) ON DELETE SET NULL,
177+
character_id INTEGER NOT NULL REFERENCES characters(id) ON DELETE CASCADE,
178+
author_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
179+
180+
CONSTRAINT uq_comments_one_per_user_per_character UNIQUE (character_id, author_id)
181+
);
182+
183+
CREATE INDEX idx_comments_character_id ON comments(character_id);
184+
CREATE INDEX idx_comments_author_id ON comments(author_id);
185+
CREATE INDEX idx_comments_reviewed_by ON comments(reviewed_by_id);
186+
CREATE INDEX idx_comments_pending ON comments(character_id) WHERE status = 'pending';
187+
188+
COMMIT;

database/sql/002_add_user_audit_columns.sql

Lines changed: 0 additions & 27 deletions
This file was deleted.

0 commit comments

Comments
 (0)