DatabaseCreation: ddl.sql

File ddl.sql, 11.5 KB (added by 231090, 5 days ago)
Line 
1CREATE TYPE user_role_enum AS ENUM (
2 'client',
3 'staff',
4 'owner',
5 'admin'
6 );
7
8CREATE TYPE appointment_status_enum AS ENUM (
9 'pending',
10 'confirmed',
11 'completed',
12 'cancelled'
13 );
14
15CREATE TYPE staff_role_type_enum AS ENUM (
16 'hairdresser',
17 'nail_tech',
18 'esthetician',
19 'makeup_artist',
20 'receptionist'
21 );
22
23CREATE TYPE discount_type_enum AS ENUM (
24 'percentage',
25 'fixed'
26 );
27
28CREATE TYPE payment_method_enum AS ENUM (
29 'cash',
30 'card',
31 'loyalty_points'
32 );
33
34CREATE TYPE day_of_week_enum AS ENUM (
35 'monday',
36 'tuesday',
37 'wednesday',
38 'thursday',
39 'friday',
40 'saturday',
41 'sunday'
42 );
43
44
45
46CREATE TABLE company_category
47(
48 company_category_id SERIAL PRIMARY KEY,
49 category_name VARCHAR(100) NOT NULL UNIQUE
50);
51
52CREATE TABLE company
53(
54 company_id SERIAL PRIMARY KEY,
55 name VARCHAR(150) NOT NULL,
56 email VARCHAR(255) NOT NULL UNIQUE,
57 phone VARCHAR(30) UNIQUE,
58 is_active BOOLEAN NOT NULL DEFAULT TRUE,
59 logo_url TEXT,
60 description TEXT,
61 created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
62);
63
64CREATE TABLE company_company_category
65(
66 company_id INT NOT NULL REFERENCES company (company_id) ON DELETE CASCADE,
67 company_category_id INT NOT NULL REFERENCES company_category (company_category_id) ON DELETE CASCADE,
68 PRIMARY KEY (company_id, company_category_id)
69);
70
71CREATE TABLE company_location
72(
73 location_id SERIAL PRIMARY KEY,
74 company_id INT NOT NULL REFERENCES company (company_id) ON DELETE CASCADE,
75 address VARCHAR(255) NOT NULL,
76 city VARCHAR(100) NOT NULL,
77 phone VARCHAR(30)
78);
79
80CREATE TABLE business_hours
81(
82 hours_id SERIAL PRIMARY KEY,
83 location_id INT NOT NULL REFERENCES company_location (location_id) ON DELETE SET DEFAULT,
84 day_of_week day_of_week_enum NOT NULL,
85 is_closed BOOLEAN NOT NULL DEFAULT FALSE,
86 open_time TIME,
87 close_time TIME,
88 CONSTRAINT chk_business_hours_order CHECK (close_time > open_time),
89 CONSTRAINT chk_closed_times CHECK (
90 (is_closed = TRUE AND open_time IS NULL AND close_time IS NULL) OR
91 (is_closed = FALSE AND open_time IS NOT NULL AND close_time IS NOT NULL)
92 ),
93 UNIQUE (location_id, day_of_week)
94);
95
96
97
98CREATE TABLE "user"
99(
100 user_id SERIAL PRIMARY KEY,
101 first_name VARCHAR(100) NOT NULL,
102 last_name VARCHAR(100) NOT NULL,
103 email VARCHAR(255) NOT NULL UNIQUE,
104 password_hash TEXT NOT NULL,
105 role user_role_enum NOT NULL,
106 is_active BOOLEAN NOT NULL DEFAULT TRUE,
107 profile_image_url TEXT,
108 created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
109);
110
111CREATE TABLE client
112(
113 client_id INT PRIMARY KEY REFERENCES "user" (user_id) ON DELETE CASCADE,
114 loyalty_points INT NOT NULL DEFAULT 0 CHECK (loyalty_points >= 0),
115 date_of_birth DATE,
116 phone VARCHAR(30),
117 notes TEXT
118);
119
120CREATE TABLE owner
121(
122 owner_id INT PRIMARY KEY REFERENCES "user" (user_id) ON DELETE CASCADE,
123 company_id INT NOT NULL REFERENCES company (company_id),
124 owner_since DATE NOT NULL DEFAULT CURRENT_DATE
125);
126
127CREATE TABLE staff
128(
129 staff_id INT PRIMARY KEY REFERENCES "user" (user_id) ON DELETE CASCADE,
130 location_id INT NOT NULL REFERENCES company_location (location_id),
131 date_hired DATE NOT NULL DEFAULT CURRENT_DATE,
132 hourly_rate NUMERIC(10, 2) CHECK (hourly_rate >= 0)
133);
134
135CREATE TABLE staff_type
136(
137 staff_type_id SERIAL PRIMARY KEY,
138 staff_id INT NOT NULL REFERENCES staff (staff_id) ON DELETE CASCADE,
139 role_type staff_role_type_enum NOT NULL,
140 specialty VARCHAR(150),
141 certification VARCHAR(150),
142 years_experience SMALLINT CHECK (years_experience >= 0),
143 extra_info TEXT,
144 UNIQUE (staff_id, role_type)
145);
146
147
148
149CREATE TABLE service_category
150(
151 service_category_id SERIAL PRIMARY KEY,
152 category_name VARCHAR(100) NOT NULL UNIQUE,
153 description TEXT
154);
155
156CREATE TABLE service
157(
158 service_id SERIAL PRIMARY KEY,
159 company_id INT NOT NULL REFERENCES company (company_id) ON DELETE SET NULL,
160 service_category_id INT NOT NULL REFERENCES service_category (service_category_id),
161 service_name VARCHAR(150) NOT NULL,
162 duration_minutes SMALLINT NOT NULL CHECK (duration_minutes > 0 AND duration_minutes % 15 = 0),
163 price NUMERIC(10, 2) NOT NULL CHECK (price >= 0),
164 is_active BOOLEAN NOT NULL DEFAULT TRUE
165);
166
167CREATE TABLE staff_service
168(
169 staff_id INT NOT NULL REFERENCES staff (staff_id) ON DELETE CASCADE,
170 service_id INT NOT NULL REFERENCES service (service_id) ON DELETE CASCADE,
171 notes TEXT,
172 PRIMARY KEY (staff_id, service_id)
173);
174
175
176
177CREATE TABLE staff_availability
178(
179 availability_id SERIAL PRIMARY KEY,
180 staff_id INT NOT NULL REFERENCES staff (staff_id) ON DELETE CASCADE,
181 day_of_week day_of_week_enum NOT NULL,
182 start_time TIME NOT NULL,
183 end_time TIME NOT NULL,
184 CONSTRAINT chk_availability_order CHECK (end_time > start_time),
185 UNIQUE (staff_id, day_of_week)
186);
187
188CREATE TABLE blocked_time
189(
190 block_id SERIAL PRIMARY KEY,
191 staff_id INT NOT NULL REFERENCES staff (staff_id) ON DELETE CASCADE,
192 start_datetime TIMESTAMPTZ NOT NULL,
193 end_datetime TIMESTAMPTZ NOT NULL,
194 reason TEXT,
195 CONSTRAINT chk_blocked_time_order CHECK (end_datetime > start_datetime)
196);
197
198CREATE TABLE appointment
199(
200 appointment_id SERIAL PRIMARY KEY,
201 client_id INT NOT NULL REFERENCES client (client_id) ON DELETE SET DEFAULT,
202 staff_id INT NOT NULL REFERENCES staff (staff_id) ON DELETE SET DEFAULT,
203 location_id INT NOT NULL REFERENCES company_location (location_id) ON DELETE SET DEFAULT,
204 appointment_date DATE NOT NULL,
205 appointment_time TIME NOT NULL,
206 end_time TIME NOT NULL,
207 status appointment_status_enum NOT NULL DEFAULT 'pending',
208 notes TEXT,
209 booked_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
210 cancelled_at TIMESTAMPTZ,
211 cancellation_reason TEXT,
212 CONSTRAINT chk_appointment_time_order CHECK (end_time > appointment_time),
213 CONSTRAINT chk_cancellation CHECK (
214 (status = 'cancelled' AND cancelled_at IS NOT NULL) OR
215 (status <> 'cancelled' AND cancelled_at IS NULL)
216 ),
217 UNIQUE (staff_id, appointment_date, appointment_time)
218);
219
220CREATE TABLE appointment_service
221(
222 appointment_id INT NOT NULL REFERENCES appointment (appointment_id) ON DELETE SET DEFAULT,
223 service_id INT NOT NULL REFERENCES service (service_id),
224 duration_minutes SMALLINT NOT NULL CHECK (duration_minutes > 0),
225 price NUMERIC(10, 2) NOT NULL CHECK (price >= 0),
226 PRIMARY KEY (appointment_id, service_id)
227);
228
229
230
231CREATE TABLE product
232(
233 product_id SERIAL PRIMARY KEY,
234 product_name VARCHAR(150) NOT NULL,
235 brand VARCHAR(100),
236 unit_price NUMERIC(10, 2) NOT NULL CHECK (unit_price >= 0),
237 reorder_level INT NOT NULL DEFAULT 0 CHECK (reorder_level >= 0)
238);
239
240CREATE TABLE appointment_product
241(
242 appointment_id INT NOT NULL REFERENCES appointment (appointment_id) ON DELETE CASCADE,
243 product_id INT NOT NULL REFERENCES product (product_id),
244 quantity_used NUMERIC(10, 3) NOT NULL CHECK (quantity_used > 0),
245 PRIMARY KEY (appointment_id, product_id)
246);
247
248CREATE TABLE inventory
249(
250 inventory_id SERIAL PRIMARY KEY,
251 product_id INT NOT NULL REFERENCES product (product_id),
252 location_id INT NOT NULL REFERENCES company_location (location_id),
253 quantity_on_hand NUMERIC(10, 3) NOT NULL DEFAULT 0 CHECK (quantity_on_hand >= 0),
254 UNIQUE (product_id, location_id)
255);
256
257CREATE TABLE invoice
258(
259 invoice_id SERIAL PRIMARY KEY,
260 appointment_id INT NOT NULL UNIQUE REFERENCES appointment (appointment_id) ON DELETE RESTRICT,
261 client_id INT NOT NULL REFERENCES client (client_id),
262 invoice_date DATE NOT NULL DEFAULT CURRENT_DATE,
263 subtotal NUMERIC(10, 2) NOT NULL CHECK (subtotal >= 0),
264 discount_total NUMERIC(10, 2) NOT NULL DEFAULT 0 CHECK (discount_total >= 0),
265 tax NUMERIC(10, 2) NOT NULL DEFAULT 0 CHECK (tax >= 0),
266 total NUMERIC(10, 2) GENERATED ALWAYS AS (subtotal + tax - discount_total) STORED,
267 payment_method payment_method_enum NOT NULL
268);
269
270CREATE TABLE promo_code
271(
272 promo_id SERIAL PRIMARY KEY,
273 company_id INT NOT NULL REFERENCES company (company_id) ON DELETE CASCADE,
274 code VARCHAR(50) NOT NULL,
275 discount_type discount_type_enum NOT NULL,
276 discount_value NUMERIC(10, 2) NOT NULL CHECK (discount_value > 0),
277 valid_from DATE NOT NULL,
278 valid_until DATE NOT NULL,
279 CONSTRAINT chk_promo_dates CHECK (valid_until >= valid_from),
280 UNIQUE (company_id, code)
281);
282
283CREATE TABLE invoice_promo
284(
285 invoice_id INT NOT NULL REFERENCES invoice (invoice_id) ON DELETE CASCADE,
286 promo_id INT NOT NULL REFERENCES promo_code (promo_id) ON DELETE CASCADE,
287 PRIMARY KEY (invoice_id, promo_id)
288);
289
290
291
292CREATE TABLE review
293(
294 review_id SERIAL PRIMARY KEY,
295 appointment_id INT NOT NULL UNIQUE REFERENCES appointment (appointment_id),
296 client_id INT NOT NULL REFERENCES client (client_id),
297 rating SMALLINT NOT NULL CHECK (rating BETWEEN 1 AND 5),
298 comment TEXT,
299 created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
300);
301
302CREATE TABLE loyalty_transaction
303(
304 transaction_id SERIAL PRIMARY KEY,
305 client_id INT NOT NULL REFERENCES client (client_id),
306 appointment_id INT REFERENCES appointment (appointment_id) ON DELETE SET NULL,
307 points_earned INT NOT NULL DEFAULT 0 CHECK (points_earned >= 0),
308 points_spent INT NOT NULL DEFAULT 0 CHECK (points_spent >= 0),
309 created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
310 CONSTRAINT chk_loyalty_nonzero CHECK (points_earned > 0 OR points_spent > 0)
311);
312
313
314
315CREATE TABLE service_price_history
316(
317 price_history_id SERIAL PRIMARY KEY,
318 service_id INT NOT NULL REFERENCES service (service_id) ON DELETE CASCADE,
319 old_price NUMERIC(10, 2) NOT NULL CHECK (old_price >= 0),
320 new_price NUMERIC(10, 2) NOT NULL CHECK (new_price >= 0),
321 changed_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
322);
323
324CREATE TABLE staff_time_slot
325(
326 slot_id SERIAL PRIMARY KEY,
327 staff_id INT NOT NULL REFERENCES staff (staff_id) ON DELETE CASCADE,
328 slot_start TIMESTAMP NOT NULL,
329 slot_end TIMESTAMP GENERATED ALWAYS AS (slot_start + INTERVAL '15 minutes') STORED,
330 appointment_id INT REFERENCES appointment (appointment_id) ON DELETE SET NULL,
331 CONSTRAINT chk_slot_order CHECK (slot_end > slot_start),
332 UNIQUE (staff_id, slot_start)
333);