-
Notifications
You must be signed in to change notification settings - Fork 0
/
MarketNexus.sql
706 lines (609 loc) · 29.2 KB
/
MarketNexus.sql
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
--SET TIME ZONE 'Europe/Rome';
SHOW TIMEZONE;
SELECT VERSION();
-- CREATE DATABASE IF NOT EXISTS MarketNexus;
--CONNECT MarketNexus;
DROP SCHEMA IF EXISTS MarketNexus CASCADE;
CREATE SCHEMA IF NOT EXISTS MarketNexus;
COMMENT ON SCHEMA MarketNexus IS 'MarketNexus SQL DataBase Schema.';
SELECT CURRENT_DATABASE();
SET SEARCH_PATH TO MarketNexus;
SELECT CURRENT_SCHEMA();
SELECT CURRENT_CATALOG;
SELECT CURRENT_TIMESTAMP;
DROP TYPE IF EXISTS ROLES;
CREATE TYPE ROLES AS ENUM (
'SELLER',
'SELLER_AND_BUYER',
'BUYER'
);
COMMENT ON TYPE ROLES IS 'MarketNexus Users Credentials Roles.';
CREATE
OR REPLACE FUNCTION UPDATEDAT_SET_TIMESTAMP_FUNCTION() RETURNS TRIGGER AS
$$
BEGIN
NEW.updated_at = CURRENT_TIMESTAMP;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
COMMENT ON FUNCTION UPDATEDAT_SET_TIMESTAMP_FUNCTION IS 'Function that allows to update the updated_at TIMESTAMP fields.';
--CREATE SEQUENCE nome_sequenza START 1;
--COMMENT ON SEQUENCE nome_sequenza IS '';
CREATE TABLE IF NOT EXISTS MarketNexus.Nations
(
id SERIAL NOT NULL PRIMARY KEY,
name VARCHAR(30) NOT NULL,
CONSTRAINT nations_name_unique UNIQUE (name),
CONSTRAINT nations_id_min_value_check CHECK (MarketNexus.Nations.id >= 1),
CONSTRAINT nations_name_min_length_check CHECK (LENGTH(MarketNexus.Nations.name) >= 3)
);
ALTER TABLE MarketNexus.Nations
OWNER TO postgres;
COMMENT ON TABLE MarketNexus.Nations IS 'MarketNexus Users Nation origin.';
INSERT INTO MarketNexus.Nations (name)
VALUES ('Italy'),
('France'),
('Germany'),
('United States'),
('Spain'),
('United Kingdom'),
('Japan'),
('China'),
('India');
CREATE TABLE IF NOT EXISTS MarketNexus.product_categories
(
id SERIAL NOT NULL PRIMARY KEY,
name VARCHAR(30) NOT NULL,
description VARCHAR(60) NOT NULL,
CONSTRAINT productcategories_name_unique UNIQUE (name),
CONSTRAINT productcategories_id_min_value_check CHECK (MarketNexus.product_categories.id >= 1),
CONSTRAINT productcategories_name_min_length_check CHECK (LENGTH(MarketNexus.product_categories.name) >= 3),
CONSTRAINT productcategories_description_min_length_check CHECK (LENGTH(MarketNexus.product_categories.description) >= 3)
);
ALTER TABLE MarketNexus.product_categories
OWNER TO postgres;
COMMENT ON TABLE MarketNexus.product_categories IS 'MarketNexus Product Categories.';
INSERT INTO MarketNexus.product_categories (name, description)
VALUES ('Electronics', 'Electronics products.'),
('Clothing', 'Clothing products.'),
('Books', 'Books products.'),
('Appliances', 'Sales Appliances products.'),
('Footwear', 'Footwear products.'),
('Sports', 'Sports products.'),
('Beauty', 'Beauty products.'),
('Games', 'Games products.'),
('Food', 'Food products.');
CREATE TABLE IF NOT EXISTS MarketNexus.Products
(
id SERIAL NOT NULL PRIMARY KEY,
name VARCHAR(30) NOT NULL,
description VARCHAR(60) NOT NULL,
price NUMERIC(10, 2) NOT NULL,
image_relative_paths TEXT[] NOT NULL,
category INTEGER NOT NULL,
CONSTRAINT products_productcategories_fk FOREIGN KEY (category) REFERENCES MarketNexus.product_categories (id) ON DELETE CASCADE,
CONSTRAINT products_id_min_value_check CHECK (MarketNexus.Products.id >= 1),
CONSTRAINT products_name_min_length_check CHECK (LENGTH(MarketNexus.Products.name) >= 3),
CONSTRAINT products_name_valid_check CHECK (MarketNexus.Products.name ~ '^[^\\\\/:*?"<>|]*$'::TEXT),
CONSTRAINT products_price_min_value_check CHECK (MarketNexus.Products.price > 0),
CONSTRAINT products_price_max_value_check CHECK (MarketNexus.Products.price <= 1000),
CONSTRAINT products_description_min_length_check CHECK (LENGTH(MarketNexus.Products.description) >= 3),
CONSTRAINT products_category_min_value_check CHECK (MarketNexus.Products.category >= 1)
);
CREATE OR REPLACE FUNCTION MarketNexus.VALIDATE_PRODUCTS_IMAGE_PATHS_FUNCTION() RETURNS TRIGGER AS
$$
DECLARE
image_path TEXT;
BEGIN
FOREACH image_path IN ARRAY NEW.image_relative_paths
LOOP
IF image_path !~ '^/images/products/[1-9][0-9]*/-?\d+\.jpeg$' THEN
RAISE EXCEPTION 'Invalid image path: %', image_path;
END IF;
END LOOP;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER VALIDATE_PRODUCTS_IMAGE_PATHS_TRIGGER
BEFORE INSERT OR UPDATE
ON MarketNexus.Products
FOR EACH ROW
EXECUTE FUNCTION VALIDATE_PRODUCTS_IMAGE_PATHS_FUNCTION();
ALTER TABLE MarketNexus.Products
OWNER TO postgres;
COMMENT ON TABLE MarketNexus.Products IS 'MarketNexus Users Products.';
INSERT INTO MarketNexus.Products (name, price, description, category, image_relative_paths)
VALUES ('Smartphone', 599.99, 'High-end smartphone.', 1,
'{/images/products/1/1.jpeg, /images/products/1/2.jpeg, /images/products/1/3.jpeg}'),
('T-shirt', 29.99, 'Cotton T-shirt.', 2, '{/images/products/2/1.jpeg, /images/products/2/2.jpeg}'),
('Java Programming Book', 49.99, 'Learn Java programming.', 3, '{/images/products/3/1.jpeg}'),
('Laptop', 999.99, 'Powerful laptop.', 1, '{/images/products/4/1.jpeg, /images/products/4/2.jpeg}'),
('Running Shoes', 79.99, 'Lightweight running shoes.', 2,
'{/images/products/5/1.jpeg, /images/products/5/2.jpeg}'),
('Python Book', 39.99, 'Master Python programming.', 3,
'{/images/products/6/1.jpeg, /images/products/6/2.jpeg}'),
('Coffee Maker', 89.99, 'Automatic coffee maker.', 4, '{/images/products/7/1.jpeg, /images/products/7/2.jpeg}');
CREATE OR REPLACE FUNCTION CHECK_ROLE_ROLES_ENUM_FUNCTION(role TEXT) RETURNS BOOLEAN AS
$$
BEGIN
RETURN role IN (SELECT TEXT_ROLE::TEXT
FROM (SELECT UNNEST(ENUM_RANGE(NULL::ROLES)) AS TEXT_ROLE) AS TEXT_ROLES);
END;
$$ LANGUAGE PLPGSQL;
CREATE TABLE IF NOT EXISTS MarketNexus.Credentials
(
id SERIAL NOT NULL PRIMARY KEY,
password VARCHAR(72) NOT NULL,
username VARCHAR(10) NOT NULL,
role VARCHAR(30) NOT NULL DEFAULT 'SELLER_AND_BUYER',
is_online BOOLEAN NOT NULL DEFAULT FALSE,
inserted_at TIMESTAMP WITH TIME ZONE DEFAULT pg_catalog.TIMEZONE('UTC'::TEXT, CURRENT_TIMESTAMP) NOT NULL,
updated_at TIMESTAMP WITH TIME ZONE DEFAULT pg_catalog.TIMEZONE('UTC'::TEXT, CURRENT_TIMESTAMP) NOT NULL,
CONSTRAINT credentials_username_unique UNIQUE (username),
CONSTRAINT credentials_role_min_length_check CHECK (LENGTH(MarketNexus.Credentials.role) >= 3),
CONSTRAINT credentials_role_valid_check CHECK (MarketNexus.CHECK_ROLE_ROLES_ENUM_FUNCTION(role)),
CONSTRAINT credentials_username_min_length_check CHECK (LENGTH(MarketNexus.Credentials.username) >= 3),
CONSTRAINT credentials_password_min_check CHECK (LENGTH(MarketNexus.Credentials.password) >= 60),
CONSTRAINT credentials_id_min_value_check CHECK (MarketNexus.Credentials.id >= 1),
--CONSTRAINT credentials_insertedat_min_value_check CHECK (MarketNexus.Credentials.inserted_at <= CURRENT_TIMESTAMP),
CONSTRAINT credentials_insertedat_updatedat_value_check CHECK (MarketNexus.Credentials.inserted_at <=
MarketNexus.Credentials.updated_at)
);
CREATE
OR REPLACE TRIGGER CREDENTIALS_UPDATEDAT_TRIGGER
BEFORE
UPDATE
ON MarketNexus.Credentials
FOR EACH ROW
EXECUTE
FUNCTION MarketNexus.UPDATEDAT_SET_TIMESTAMP_FUNCTION();
COMMENT ON TABLE MarketNexus.Credentials IS 'MarketNexus Users Credentials.';
ALTER TABLE MarketNexus.Credentials
OWNER TO postgres;
INSERT INTO MarketNexus.Credentials (username, password, role)
VALUES ('Lamb', '$2a$10$1xyrTM4fzIZINm3GBh7H6.IyMc0RFFzplC/emdv3aXctk3k7U55oG', 'SELLER_AND_BUYER'),
('JohnDoe', '$2a$10$1xyrTM4fzIZINm3GBh7H6.IyMc0RFFzplC/emdv3aXctk3k7U55oG', 'SELLER_AND_BUYER'),
('Giuseppe', '$2a$10$1xyrTM4fzIZINm3GBh7H6.IyMc0RFFzplC/emdv3aXctk3k7U55oG', 'SELLER_AND_BUYER'),
('KatyPerry', '$2a$10$1xyrTM4fzIZINm3GBh7H6.IyMc0RFFzplC/emdv3aXctk3k7U55oG', 'SELLER'),
('SanJay', '$2a$10$1xyrTM4fzIZINm3GBh7H6.IyMc0RFFzplC/emdv3aXctk3k7U55oG', 'BUYER'),
('Queen', '$2a$10$1xyrTM4fzIZINm3GBh7H6.IyMc0RFFzplC/emdv3aXctk3k7U55oG', 'BUYER'),
('King', '$2a$10$1xyrTM4fzIZINm3GBh7H6.IyMc0RFFzplC/emdv3aXctk3k7U55oG', 'SELLER');
-- N.B. = La password è criptata da spring boot con l'algoritmo bscrypt e va da 60 caratteri a 72.
CREATE TABLE IF NOT EXISTS MarketNexus.Users
(
id SERIAL NOT NULL PRIMARY KEY,
name VARCHAR(30) NOT NULL,
surname VARCHAR(30) NOT NULL,
email VARCHAR(50) NOT NULL,
birthdate DATE,
balance NUMERIC(10, 2) NOT NULL,
show_is_online BOOLEAN DEFAULT TRUE,
credentials INTEGER NOT NULL,
nation INTEGER NOT NULL,
CONSTRAINT users_email_unique UNIQUE (email),
CONSTRAINT users_credentials_unique UNIQUE (credentials),
CONSTRAINT users_credentials_fk FOREIGN KEY (credentials) REFERENCES MarketNexus.Credentials (id) ON DELETE CASCADE,
CONSTRAINT users_nations_fk FOREIGN KEY (nation) REFERENCES MarketNexus.Nations (id) ON DELETE CASCADE,
CONSTRAINT users_name_min_length_check CHECK (LENGTH(MarketNexus.Users.name) >= 3),
CONSTRAINT users_id_min_value_check CHECK (MarketNexus.Users.id >= 1),
CONSTRAINT users_surname_min_length_check CHECK (LENGTH(MarketNexus.Users.surname) >= 3),
CONSTRAINT users_birthdate_min_value_check CHECK (MarketNexus.Users.birthdate >=
(CURRENT_TIMESTAMP - INTERVAL '100 years')),
CONSTRAINT users_birthdate_max_value_check CHECK (MarketNexus.Users.birthdate <= CURRENT_TIMESTAMP),
CONSTRAINT users_email_min_length_check CHECK (LENGTH(MarketNexus.Users.email) >= 3),
CONSTRAINT users_email_valid_check CHECK (MarketNexus.Users.email ~
'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'::TEXT),
CONSTRAINT users_balance_min_value_check CHECK (MarketNexus.Users.balance >= 0),
CONSTRAINT users_balance_max_value_check CHECK (MarketNexus.Users.balance <= 10000),
CONSTRAINT users_credentials_min_value_check CHECK (MarketNexus.Users.credentials >= 1),
CONSTRAINT users_nation_min_value_check CHECK (MarketNexus.Users.nation >= 1)
);
COMMENT ON TABLE MarketNexus.Users IS 'MarketNexus Users.';
ALTER TABLE MarketNexus.Users
OWNER TO postgres;
INSERT INTO MarketNexus.Users (name, surname, email, birthdate, balance, credentials, nation)
VALUES ('Matteo', 'Lambertucci', 'matteolambertucci3@gmail.com', '2002-04-02', 220, 1, 1),
('John', 'Doe', 'johndoe@test.it', '2020-03-17', 2000, 2, 6),
('Giuseppe', 'Rossi', 'giusepperossi@test.it', '2020-11-02', 2000.05, 3, 1),
('Katy', 'Perry', 'katyperry@test.it', '2000-01-12', 100.16, 4, 4),
('San', 'Jay', 'sanjay@test.it', '2000-01-12', 0, 5, 9),
('Queen', 'Elizabeth', 'queen@test.it', '1950-02-10', 0, 6, 6),
('King', 'Carlo', 'king@test.it', '1970-12-10', 0, 7, 6);
CREATE TABLE IF NOT EXISTS MarketNexus.Sales
(
id SERIAL NOT NULL PRIMARY KEY,
_user INTEGER NOT NULL,
product INTEGER NOT NULL,
quantity INTEGER NOT NULL,
is_sold BOOLEAN NOT NULL DEFAULT FALSE,
sale_price NUMERIC(10, 2) NOT NULL,
inserted_at TIMESTAMP WITH TIME ZONE DEFAULT pg_catalog.TIMEZONE('UTC'::TEXT, CURRENT_TIMESTAMP) NOT NULL,
updated_at TIMESTAMP WITH TIME ZONE DEFAULT pg_catalog.TIMEZONE('UTC'::TEXT, CURRENT_TIMESTAMP) NOT NULL,
CONSTRAINT sales_user_product_unique UNIQUE (_user, product),
CONSTRAINT sale_users_fk FOREIGN KEY (_user) REFERENCES MarketNexus.Users (id) ON DELETE CASCADE,
CONSTRAINT sale_products_fk FOREIGN KEY (product) REFERENCES MarketNexus.Products (id) ON DELETE CASCADE,
CONSTRAINT sale_id_min_value_check CHECK (MarketNexus.Sales.id >= 1),
CONSTRAINT sale_user_min_value_check CHECK (MarketNexus.Sales._user >= 1),
CONSTRAINT sale_product_min_value_check CHECK (MarketNexus.Sales.product >= 1),
CONSTRAINT sale_quantity_min_value_check CHECK (MarketNexus.Sales.quantity >= 0),
CONSTRAINT sale_quantity_max_value_check CHECK (MarketNexus.Sales.quantity <= 10),
CONSTRAINT sale_saleprice_min_value_check CHECK (MarketNexus.Sales.sale_price > 0),
CONSTRAINT sale_saleprice_max_value_check CHECK (MarketNexus.Sales.sale_price <= 10000),
--CONSTRAINT sale_insertedat_min_value_check CHECK (MarketNexus.Sales.inserted_at <= CURRENT_TIMESTAMP),
CONSTRAINT sale_insertedat_updatedat_value_check CHECK (MarketNexus.Sales.inserted_at <=
MarketNexus.Sales.updated_at)
);
CREATE
OR REPLACE TRIGGER SALE_UPDATEDAT_TRIGGER
BEFORE
UPDATE
ON MarketNexus.Sales
FOR EACH ROW
EXECUTE
FUNCTION MarketNexus.UPDATEDAT_SET_TIMESTAMP_FUNCTION();
CREATE
OR REPLACE FUNCTION CHECK_SALE_SALEPRICE_VALUE_FUNCTION()
RETURNS TRIGGER AS
$$
BEGIN
IF (SELECT (TRUNC(s.sale_price) = TRUNC(p.price * s.quantity)) AS are_equals
FROM MarketNexus.Products p
JOIN MarketNexus.Sales s ON p.id = s.product
WHERE s.id = NEW.ID) THEN
RETURN NEW;
ELSE
RAISE EXCEPTION 'Sale sale_price error with this Sale ID: % and this sale_price: %.' , NEW.ID, NEW.sale_price;
END IF;
END;
$$ LANGUAGE PLPGSQL;
CREATE
OR REPLACE TRIGGER SALE_SALEPRICE_VALUE_TRIGGER
AFTER
INSERT OR UPDATE
ON MarketNexus.Sales
FOR EACH ROW
EXECUTE
FUNCTION MarketNexus.CHECK_SALE_SALEPRICE_VALUE_FUNCTION();
CREATE
OR REPLACE FUNCTION CHECK_SALE_USER_CREDENTIALS_ROLE_FUNCTION()
RETURNS TRIGGER AS
$$
BEGIN
IF ((SELECT CASE
WHEN (c.role = 'SELLER_AND_BUYER' OR c.role = 'SELLER') THEN TRUE
ELSE FALSE END AS are_equals
FROM MarketNexus.Sales s
JOIN MarketNexus.Users u ON s._user = u.id
JOIN MarketNexus.Credentials c ON u.credentials = c.id
WHERE s.id = NEW.ID) = TRUE) THEN
RETURN NEW;
ELSE
RAISE EXCEPTION 'User Sale Credentials role error, with this Sale ID: % .' , NEW.ID;
END IF;
END;
$$ LANGUAGE PLPGSQL;
CREATE
OR REPLACE TRIGGER SALE_USER_CREDENTIALS_ROLE_TRIGGER
AFTER
INSERT OR UPDATE
ON MarketNexus.Sales
FOR EACH ROW
EXECUTE
FUNCTION MarketNexus.CHECK_SALE_USER_CREDENTIALS_ROLE_FUNCTION();
COMMENT ON TABLE MarketNexus.Sales IS 'Publication of a Sale (Product in Sale) by the MarketNexus Users.';
ALTER TABLE MarketNexus.Sales
OWNER TO postgres;
INSERT INTO MarketNexus.Sales(_user, product, quantity, sale_price)
VALUES (1, 2, 2, 59.98),
(2, 3, 3, 149.97),
(2, 4, 1, 999.99),
(2, 5, 2, 159.98),
(2, 6, 2, 79.98),
(2, 7, 2, 179.98);
INSERT INTO MarketNexus.Sales(_user, product, quantity, sale_price, inserted_at)
VALUES (1, 1, 1, 599.99, CURRENT_TIMESTAMP - INTERVAL '1 days');
CREATE TABLE IF NOT EXISTS MarketNexus.Carts
(
id SERIAL NOT NULL PRIMARY KEY,
cart_price NUMERIC(10, 2) NOT NULL,
_user INTEGER NOT NULL,
inserted_at TIMESTAMP WITH TIME ZONE DEFAULT pg_catalog.TIMEZONE('UTC'::TEXT, CURRENT_TIMESTAMP) NOT NULL,
CONSTRAINT carts_user_insertedat_unique UNIQUE (_user, inserted_at),
CONSTRAINT carts_users_fk FOREIGN KEY (_user) REFERENCES MarketNexus.Users (id) ON DELETE CASCADE,
CONSTRAINT carts_id_min_value_check CHECK (MarketNexus.Carts.id >= 1),
CONSTRAINT carts_cartprice_min_value_check CHECK (MarketNexus.Carts.cart_price >= 0),
CONSTRAINT carts_user_min_value_check CHECK (MarketNexus.Carts._user >= 1)
--CONSTRAINT carts_insertedat_min_value_check CHECK (MarketNexus.Carts.inserted_at <= CURRENT_TIMESTAMP),
);
COMMENT ON TABLE MarketNexus.Carts IS 'MarketNexus User Cart.';
ALTER TABLE MarketNexus.Carts
OWNER TO postgres;
INSERT INTO MarketNexus.Carts(cart_price, _user)
VALUES (0, 1),
(0, 2),
(0, 3),
(0, 4),
(0, 5),
(0, 6),
(0, 7);
CREATE TABLE IF NOT EXISTS MarketNexus.cart_line_items
(
id SERIAL NOT NULL PRIMARY KEY,
quantity INTEGER NOT NULL,
cartlineitem_price NUMERIC(10, 2) NOT NULL,
cart INTEGER NOT NULL,
sale INTEGER NOT NULL,
inserted_at TIMESTAMP WITH TIME ZONE DEFAULT pg_catalog.TIMEZONE('UTC'::TEXT, CURRENT_TIMESTAMP) NOT NULL,
updated_at TIMESTAMP WITH TIME ZONE DEFAULT pg_catalog.TIMEZONE('UTC'::TEXT, CURRENT_TIMESTAMP) NOT NULL,
CONSTRAINT cartlineitems_cart_sale_insertedat_unique UNIQUE (cart, sale, inserted_at),
CONSTRAINT cartlineitems_carts_fk FOREIGN KEY (cart) REFERENCES MarketNexus.Carts (id) ON DELETE CASCADE,
CONSTRAINT cartlineitems_sale_fk FOREIGN KEY (sale) REFERENCES MarketNexus.Sales (id) ON DELETE CASCADE,
CONSTRAINT cartlineitems_id_min_value_check CHECK (MarketNexus.cart_line_items.id >= 1),
CONSTRAINT cartlineitems_cartlineitemprice_min_value_check CHECK (MarketNexus.cart_line_items.cartlineitem_price > 0),
CONSTRAINT cartlineitems_cartlineitemprice_max_value_check CHECK (MarketNexus.cart_line_items.cartlineitem_price <= 10000),
CONSTRAINT cartlineitems_cart_min_value_check CHECK (MarketNexus.cart_line_items.cart >= 1),
CONSTRAINT cartlineitems_sale_min_value_check CHECK (MarketNexus.cart_line_items.sale >= 1),
CONSTRAINT cartlineitems_quantity_min_value_check CHECK (MarketNexus.cart_line_items.quantity >= 1),
CONSTRAINT cartlineitems_insertedat_updatedat_value_check CHECK (MarketNexus.cart_line_items.inserted_at <=
MarketNexus.cart_line_items.updated_at)
--CONSTRAINT cartlineitems_insertedat_min_value_check CHECK (MarketNexus.cart_line_items.inserted_at <= CURRENT_TIMESTAMP),
);
CREATE
OR REPLACE TRIGGER CARTLINEITEMS_UPDATEDAT_TRIGGER
BEFORE
UPDATE
ON MarketNexus.cart_line_items
FOR EACH ROW
EXECUTE
FUNCTION MarketNexus.UPDATEDAT_SET_TIMESTAMP_FUNCTION();
CREATE
OR REPLACE FUNCTION CHECK_CART_USER_CREDENTIALS_ROLE_FUNCTION()
RETURNS TRIGGER AS
$$
BEGIN
IF ((SELECT CASE
WHEN (c.role = 'SELLER_AND_BUYER' OR c.role = 'BUYER')
THEN TRUE
ELSE FALSE END AS are_equals
FROM MarketNexus.cart_line_items cli
JOIN MarketNexus.Sales s ON cli.sale = s.id
JOIN MarketNexus.Users u ON s._user = u.id
JOIN MarketNexus.Credentials c ON u.credentials = c.id
WHERE cli.id = NEW.ID) = TRUE) THEN
RETURN NEW;
ELSE
RAISE EXCEPTION 'User Cart Credentials role error, with this Cart_Line_Item ID: % .' , NEW.ID;
END IF;
END;
$$ LANGUAGE PLPGSQL;
CREATE
OR REPLACE TRIGGER CART_USER_CREDENTIALS_ROLE_TRIGGER
AFTER
INSERT OR UPDATE
ON MarketNexus.cart_line_items
FOR EACH ROW
EXECUTE
FUNCTION MarketNexus.CHECK_CART_USER_CREDENTIALS_ROLE_FUNCTION();
CREATE
OR REPLACE FUNCTION CHECK_CARTLINEITEM_CARTLINEITEMPRICE_VALUE_FUNCTION()
RETURNS TRIGGER AS
$$
BEGIN
IF ((SELECT CASE
WHEN (ROUND(cli.cartlineitem_price::NUMERIC, 2) = ROUND((p.price * cli.quantity)::NUMERIC, 2))
THEN TRUE
ELSE FALSE END AS are_equals
FROM MarketNexus.Products p
JOIN MarketNexus.Sales s ON p.id = s.product
JOIN MarketNexus.cart_line_items cli ON s.id = cli.sale
WHERE cli.id = NEW.ID) = TRUE) THEN
RETURN NEW;
ELSE
RAISE EXCEPTION 'CartLineItem cartlineitem_price error with this CartLineItem ID: % and this cartlineitem_price: %.' , NEW.ID, NEW.cartlineitem_price;
END IF;
END;
$$ LANGUAGE PLPGSQL;
CREATE
OR REPLACE TRIGGER CARTLINEITEM_CARTLINEITEMPRICE_VALUE_TRIGGER
AFTER
INSERT OR UPDATE
ON MarketNexus.cart_line_items
FOR EACH ROW
EXECUTE
FUNCTION MarketNexus.CHECK_CARTLINEITEM_CARTLINEITEMPRICE_VALUE_FUNCTION();
CREATE
OR REPLACE FUNCTION CHECK_CART_USER_SALE_FUNCTION()
RETURNS TRIGGER AS
$$
BEGIN
IF ((SELECT CASE
WHEN (c._user <> s._user)
THEN TRUE
ELSE FALSE END AS are_equals
FROM cart_line_items cli
JOIN MarketNexus.Carts c ON cli.cart = c.id
JOIN MarketNexus.Sales s ON cli.sale = s.id
JOIN MarketNexus.Users u ON s._user = u.id
WHERE cli.id = NEW.ID) = TRUE) THEN
RETURN NEW;
ELSE
RAISE EXCEPTION 'User that adds to Cart his sale error, with this cart_line_items ID: % .' , NEW.ID;
END IF;
END;
$$ LANGUAGE PLPGSQL;
CREATE
OR REPLACE TRIGGER CART_USER_SALE_FUNCTION_TRIGGER
AFTER
INSERT OR UPDATE
ON MarketNexus.cart_line_items
FOR EACH ROW
EXECUTE
FUNCTION MarketNexus.CHECK_CART_USER_SALE_FUNCTION();
CREATE OR REPLACE FUNCTION GET_CARTLINEITEMS_PRICE_SUM_FROM_CARTID(cart_id BIGINT)
RETURNS NUMERIC(10, 2) AS
$$
DECLARE
cartLineItemsPriceSumFromCartId NUMERIC(10, 2) ;
BEGIN
SELECT COALESCE(SUM(cli.cartlineitem_price),
0) AS cart_line_items_price_sum_from_cart_id
FROM MarketNexus.Carts c
JOIN MarketNexus.cart_line_items cli ON cli.cart = c.id
WHERE c.id = cart_id
INTO cartLineItemsPriceSumFromCartId;
RETURN cartLineItemsPriceSumFromCartId;
END;
$$ LANGUAGE PLPGSQL;
SELECT *
FROM GET_CARTLINEITEMS_PRICE_SUM_FROM_CARTID(1);
CREATE
OR REPLACE FUNCTION CHECK_CART_CARTPRICE_VALUE_FUNCTION()
RETURNS TRIGGER AS
$$
BEGIN
IF (SELECT (c.cart_price) = GET_CARTLINEITEMS_PRICE_SUM_FROM_CARTID(NEW.cart)
AS are_equals
FROM MarketNexus.Carts c
WHERE c.id = NEW.cart) THEN
RETURN NEW;
ELSE
RAISE EXCEPTION 'Cart cart_price error with this Cart ID: % and this cart_line_item ID: %, %' , NEW.cart, NEW.id, GET_CARTLINEITEMS_PRICE_SUM_FROM_CARTID(NEW.cart);
END IF;
END;
$$ LANGUAGE PLPGSQL;
CREATE
OR REPLACE TRIGGER CART_CARTPRICE_VALUE_TRIGGER
BEFORE
INSERT
ON MarketNexus.cart_line_items
FOR EACH ROW
EXECUTE
FUNCTION MarketNexus.CHECK_CART_CARTPRICE_VALUE_FUNCTION();
COMMENT ON TABLE MarketNexus.cart_line_items IS 'MarketNexus User who puts a Sale Product in his Cart.';
ALTER TABLE MarketNexus.cart_line_items
OWNER TO postgres;
--INSERT INTO MarketNexus.cart_line_items(cart, sale, quantity, cartlineitem_price) VALUES (1, 6, 1, 89.99);
CREATE TABLE IF NOT EXISTS MarketNexus.Orders
(
id SERIAL NOT NULL PRIMARY KEY,
_user INTEGER NOT NULL,
cart INTEGER NOT NULL,
inserted_at TIMESTAMP WITH TIME ZONE DEFAULT pg_catalog.TIMEZONE('UTC'::TEXT, CURRENT_TIMESTAMP) NOT NULL,
CONSTRAINT orders_user_cart_insertedat_unique UNIQUE (_user, cart, inserted_at),
CONSTRAINT orders_users_fk FOREIGN KEY (_user) REFERENCES MarketNexus.Users (id) ON DELETE CASCADE,
CONSTRAINT orders_carts_fk FOREIGN KEY (cart) REFERENCES MarketNexus.Carts (id) ON DELETE CASCADE,
CONSTRAINT orders_id_min_value_check CHECK (MarketNexus.Orders.id >= 1),
CONSTRAINT orders_user_min_value_check CHECK (MarketNexus.Orders._user >= 1),
CONSTRAINT orders_cart_min_value_check CHECK (MarketNexus.Orders.cart >= 1)
--CONSTRAINT orders_insertedat_min_value_check CHECK (MarketNexus.Orders.inserted_at <= CURRENT_TIMESTAMP),
);
CREATE
OR REPLACE FUNCTION CHECK_ORDER_USER_SALE_FUNCTION()
RETURNS TRIGGER AS
$$
BEGIN
IF (SELECT (o._user = c._user) AS are_equals
FROM MarketNexus.Orders o
JOIN MarketNexus.Carts c ON o.cart = c.id
WHERE o.id = NEW.ID) THEN
RETURN NEW;
ELSE
RAISE EXCEPTION 'User that Ordered his Cart error, with this Order ID: %, this Cart ID: % and this User ID: %.' , NEW.ID, NEW.cart, NEW._user;
END IF;
END;
$$ LANGUAGE PLPGSQL;
CREATE
OR REPLACE TRIGGER ORDER_USER_SALE_FUNCTION_TRIGGER
AFTER
INSERT OR UPDATE
ON MarketNexus.Orders
FOR EACH ROW
EXECUTE
FUNCTION MarketNexus.CHECK_ORDER_USER_SALE_FUNCTION();
COMMENT ON TABLE MarketNexus.Orders IS 'MarketNexus User who buys all Sale Products that are in his Cart.';
ALTER TABLE MarketNexus.Orders
OWNER TO postgres;
/*
INSERT INTO MarketNexus.Orders(_user, cart)
VALUES (1, 1);
*/
DROP FUNCTION IF EXISTS GET_USER_SOLD_SALES_STATS();
CREATE OR REPLACE FUNCTION GET_USER_SOLD_SALES_STATS(user_id BIGINT)
RETURNS TABLE
(
day TEXT,
numberOfSoldSales BIGINT
)
AS
$$
BEGIN
RETURN QUERY
WITH RECURSIVE date_series AS (SELECT CURRENT_TIMESTAMP AS date
UNION ALL
SELECT (date - INTERVAL '1 day')
FROM date_series
WHERE date_series.date > (CURRENT_TIMESTAMP - INTERVAL '6 days'))
SELECT TO_CHAR(date_series.date, 'yyyy-MM-dd') AS day,
COALESCE(COUNT(DISTINCT s.id), 0) AS numberOfSoldSales
FROM date_series
LEFT JOIN MarketNexus.Orders o ON CAST(date_series.date AS DATE) = CAST(o.inserted_at AS DATE)
LEFT JOIN MarketNexus.Carts c ON o.cart = c.id
LEFT JOIN MarketNexus.cart_line_items cli ON cli.cart = c.id
LEFT JOIN MarketNexus.Sales s ON cli.sale = s.id AND s._user = user_id
GROUP BY date_series.date
ORDER BY date_series.date;
END
$$ LANGUAGE PLPGSQL;
SELECT *
FROM GET_USER_SOLD_SALES_STATS(1);
DROP FUNCTION IF EXISTS GET_USERS_SALES_STATS();
CREATE OR REPLACE FUNCTION GET_USERS_SALES_STATS()
RETURNS TABLE
(
user_username VARCHAR,
MIN BIGINT,
MAX BIGINT,
CNT BIGINT,
TOT NUMERIC,
AVG NUMERIC,
"%" TEXT,
STDDEV NUMERIC
)
AS
$$
BEGIN
RETURN QUERY
SELECT userAndDayToSalesPublished.user_username,
MIN(userAndDayToSalesPublished.salesPublishedPerDay) AS MIN,
MAX(userAndDayToSalesPublished.salesPublishedPerDay) AS MAX,
COUNT(DISTINCT CASE
WHEN userAndDayToSalesPublished.salesPublishedPerDay > 0
THEN (userAndDayToSalesPublished.salesPublishedPerDay,
userAndDayToSalesPublished.inserted_at) END) AS CNT,
SUM(userAndDayToSalesPublished.salesPublishedPerDay) AS TOT,
ROUND(AVG(userAndDayToSalesPublished.salesPublishedPerDay), 2) AS AVG,
CAST((ROUND(
CAST(
(
CAST(SUM(userAndDayToSalesPublished.salesPublishedPerDay) AS FLOAT) /
(SELECT COUNT(s2.id) FROM Sales s2)
) AS NUMERIC
),
2
) * 100) AS TEXT) || ' %' AS "%",
ROUND(COALESCE(STDDEV(userAndDayToSalesPublished.salesPublishedPerDay), 0.00), 2) AS STDDEV
FROM (SELECT c.username AS user_username,
s.inserted_at::DATE,
COUNT(DISTINCT s.id) AS salesPublishedPerDay
FROM Users u
JOIN Credentials c ON u.credentials = c.id
LEFT JOIN Sales s ON s._user = u.id
GROUP BY c.username, s.inserted_at::DATE
ORDER BY salesPublishedPerDay DESC) AS userAndDayToSalesPublished
GROUP BY userAndDayToSalesPublished.user_username
ORDER BY SUM(userAndDayToSalesPublished.salesPublishedPerDay) DESC -- TOT
LIMIT 5;
END
$$ LANGUAGE PLPGSQL;
SELECT *
FROM GET_USERS_SALES_STATS();