From 54941f9d84eafdb8581c4449898a108e56e23d9f Mon Sep 17 00:00:00 2001 From: emokid Date: Mon, 1 Dec 2025 01:40:32 +0300 Subject: [PATCH 1/7] db --- shop_db.sql | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 shop_db.sql diff --git a/shop_db.sql b/shop_db.sql new file mode 100644 index 0000000..f0db7a6 --- /dev/null +++ b/shop_db.sql @@ -0,0 +1,49 @@ +CREATE TABLE products ( + product_id SERIAL PRIMARY KEY, + manufacturer_name TEXT NOT NULL, + product_category TEXT NOT NULL, + product_name TEXT NOT NULL, + selling_price NUMERIC NOT NULL, + stock_quantity INTEGER NOT NULL, + category_description TEXT, + purchase_cost NUMERIC NOT NULL +); + +CREATE TABLE employees ( + employee_id SERIAL PRIMARY KEY, + position TEXT NOT NULL, + first_name TEXT NOT NULL, + second_name TEXT NOT NULL, + middle_name TEXT NOT NULL, + salary NUMERIC, + employment_date DATE NOT NULL, + sex TEXT NOT NULL +); + +CREATE TABLE customers ( + customer_id SERIAL PRIMARY KEY, + phone_number TEXT NOT NULL, + discount_rate NUMERIC(3,2) NOT NULL DEFAULT 0.00, + first_name TEXT NOT NULL, + second_name TEXT NOT NULL, + middle_name TEXT NOT NULL, + subscription BOOLEAN NOT NULL DEFAULT FALSE, + email_address TEXT NOT NULL, + sex TEXT +); + +CREATE TABLE sales_transactions ( + transaction_id SERIAL PRIMARY KEY, + transaction_date DATE NOT NULL, + customer_id INTEGER NOT NULL REFERENCES customers(customer_id), + sold INTEGER NOT NULL, + product_id INTEGER NOT NULL REFERENCES products(product_id), + employee_id INTEGER NOT NULL REFERENCES employees(employee_id), + transaction_total NUMERIC NOT NULL +); + +CREATE TABLE purchase_history ( + history_id SERIAL PRIMARY KEY, + transaction_id INTEGER NOT NULL REFERENCES sales_transactions(transaction_id), + customer_id INTEGER NOT NULL REFERENCES customers(customer_id) +); \ No newline at end of file From 1ba1d960346a797bb28409561498d50d32f49bbb Mon Sep 17 00:00:00 2001 From: emokid Date: Mon, 1 Dec 2025 22:25:40 +0300 Subject: [PATCH 2/7] Add files via upload Signed-off-by: emokid --- shop_db.sql | 76 ++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 58 insertions(+), 18 deletions(-) diff --git a/shop_db.sql b/shop_db.sql index f0db7a6..e1e55ac 100644 --- a/shop_db.sql +++ b/shop_db.sql @@ -1,49 +1,89 @@ +CREATE TYPE SEX AS ENUM ('m', 'f'); + +CREATE TABLE persons ( + person_id SERIAL PRIMARY KEY, + first_name TEXT NOT NULL, + second_name TEXT NOT NULL, + middle_name TEXT NOT NULL, + phone_number TEXT, + email_address TEXT, + sex SEX, + person_type TEXT NOT NULL CHECK (person_type IN ('employee', 'customer')) +); + + CREATE TABLE products ( product_id SERIAL PRIMARY KEY, manufacturer_name TEXT NOT NULL, product_category TEXT NOT NULL, product_name TEXT NOT NULL, selling_price NUMERIC NOT NULL, + purchase_cost NUMERIC NOT NULL, stock_quantity INTEGER NOT NULL, category_description TEXT, - purchase_cost NUMERIC NOT NULL + product_description TEXT +); + + +CREATE TABLE product_discounts ( + discount_id SERIAL PRIMARY KEY, + product_id INTEGER NOT NULL REFERENCES products(product_id), + discount_rate NUMERIC(5,2) NOT NULL CHECK (discount_rate >= 0 AND discount_rate <= 100), + start_date DATE NOT NULL, + end_date DATE NOT NULL, + is_active BOOLEAN DEFAULT TRUE, + CONSTRAINT valid_dates CHECK (end_date >= start_date) +); + + +CREATE TABLE personal_discounts ( + personal_discount_id SERIAL PRIMARY KEY, + person_id INTEGER NOT NULL REFERENCES persons(person_id), + discount_rate NUMERIC(5,2) NOT NULL CHECK (discount_rate >= 0 AND discount_rate <= 100), + start_date DATE NOT NULL, + end_date DATE NOT NULL, + is_active BOOLEAN DEFAULT TRUE, + discount_reason TEXT, + CONSTRAINT valid_dates CHECK (end_date >= start_date) ); + CREATE TABLE employees ( employee_id SERIAL PRIMARY KEY, + person_id INTEGER NOT NULL UNIQUE REFERENCES persons(person_id), position TEXT NOT NULL, - first_name TEXT NOT NULL, - second_name TEXT NOT NULL, - middle_name TEXT NOT NULL, salary NUMERIC, - employment_date DATE NOT NULL, - sex TEXT NOT NULL + employment_date DATE NOT NULL ); + CREATE TABLE customers ( customer_id SERIAL PRIMARY KEY, - phone_number TEXT NOT NULL, + person_id INTEGER NOT NULL UNIQUE REFERENCES persons(person_id), discount_rate NUMERIC(3,2) NOT NULL DEFAULT 0.00, - first_name TEXT NOT NULL, - second_name TEXT NOT NULL, - middle_name TEXT NOT NULL, subscription BOOLEAN NOT NULL DEFAULT FALSE, - email_address TEXT NOT NULL, - sex TEXT + registration_date DATE DEFAULT CURRENT_DATE ); + CREATE TABLE sales_transactions ( transaction_id SERIAL PRIMARY KEY, - transaction_date DATE NOT NULL, + transaction_date DATE NOT NULL DEFAULT CURRENT_DATE, customer_id INTEGER NOT NULL REFERENCES customers(customer_id), - sold INTEGER NOT NULL, - product_id INTEGER NOT NULL REFERENCES products(product_id), employee_id INTEGER NOT NULL REFERENCES employees(employee_id), + total_before_discount NUMERIC NOT NULL, + product_discount_applied NUMERIC DEFAULT 0, + personal_discount_applied NUMERIC DEFAULT 0, transaction_total NUMERIC NOT NULL ); -CREATE TABLE purchase_history ( - history_id SERIAL PRIMARY KEY, + +CREATE TABLE transaction_items ( + item_id SERIAL PRIMARY KEY, transaction_id INTEGER NOT NULL REFERENCES sales_transactions(transaction_id), - customer_id INTEGER NOT NULL REFERENCES customers(customer_id) + product_id INTEGER NOT NULL REFERENCES products(product_id), + quantity INTEGER NOT NULL CHECK (quantity > 0), + unit_price NUMERIC NOT NULL, + applied_discount_rate NUMERIC(5,2) DEFAULT 0, + item_total NUMERIC NOT NULL ); \ No newline at end of file From 9c2c19eaa49b36c7841b1bebf17bad2513df1619 Mon Sep 17 00:00:00 2001 From: emokid Date: Mon, 1 Dec 2025 22:28:14 +0300 Subject: [PATCH 3/7] Add files via upload Signed-off-by: emokid From b7175dcd6c13372e092cba586cc5179763a48fcb Mon Sep 17 00:00:00 2001 From: emokid Date: Mon, 8 Dec 2025 21:29:33 +0300 Subject: [PATCH 4/7] Add files via upload Signed-off-by: emokid --- shop_db.sql | 167 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 104 insertions(+), 63 deletions(-) diff --git a/shop_db.sql b/shop_db.sql index e1e55ac..cf154d3 100644 --- a/shop_db.sql +++ b/shop_db.sql @@ -1,89 +1,130 @@ CREATE TYPE SEX AS ENUM ('m', 'f'); -CREATE TABLE persons ( - person_id SERIAL PRIMARY KEY, - first_name TEXT NOT NULL, - second_name TEXT NOT NULL, - middle_name TEXT NOT NULL, - phone_number TEXT, - email_address TEXT, - sex SEX, - person_type TEXT NOT NULL CHECK (person_type IN ('employee', 'customer')) +CREATE TABLE IF NOT EXISTS manufacturers ( + manufacturer_id INT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + manufacturer_name TEXT NOT NULL UNIQUE, + contact_info TEXT, + address TEXT ); - -CREATE TABLE products ( - product_id SERIAL PRIMARY KEY, - manufacturer_name TEXT NOT NULL, +CREATE TABLE IF NOT EXISTS products ( + product_id INT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + manufacturer_id INTEGER NOT NULL, product_category TEXT NOT NULL, product_name TEXT NOT NULL, - selling_price NUMERIC NOT NULL, - purchase_cost NUMERIC NOT NULL, - stock_quantity INTEGER NOT NULL, - category_description TEXT, - product_description TEXT + selling_price NUMERIC(10,2) NOT NULL CHECK (selling_price > 0), + purchase_cost NUMERIC(10,2) NOT NULL CHECK (purchase_cost >= 0), + stock_quantity INTEGER NOT NULL CHECK (stock_quantity >= 0), + description TEXT, + FOREIGN KEY (manufacturer_id) REFERENCES manufacturers(manufacturer_id) ); - -CREATE TABLE product_discounts ( - discount_id SERIAL PRIMARY KEY, - product_id INTEGER NOT NULL REFERENCES products(product_id), - discount_rate NUMERIC(5,2) NOT NULL CHECK (discount_rate >= 0 AND discount_rate <= 100), - start_date DATE NOT NULL, - end_date DATE NOT NULL, - is_active BOOLEAN DEFAULT TRUE, - CONSTRAINT valid_dates CHECK (end_date >= start_date) +CREATE TABLE IF NOT EXISTS product_descriptions ( + description_id INT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + product_id INTEGER NOT NULL UNIQUE, + description TEXT, + FOREIGN KEY (product_id) REFERENCES products(product_id) ON DELETE CASCADE ); +CREATE TABLE IF NOT EXISTS table_phone ( + id INT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + phone TEXT NOT NULL CHECK ( phone <> '' ) +); -CREATE TABLE personal_discounts ( - personal_discount_id SERIAL PRIMARY KEY, - person_id INTEGER NOT NULL REFERENCES persons(person_id), - discount_rate NUMERIC(5,2) NOT NULL CHECK (discount_rate >= 0 AND discount_rate <= 100), - start_date DATE NOT NULL, - end_date DATE NOT NULL, - is_active BOOLEAN DEFAULT TRUE, - discount_reason TEXT, - CONSTRAINT valid_dates CHECK (end_date >= start_date) +CREATE TABLE IF NOT EXISTS table_email ( + id INT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + email TEXT NOT NULL CHECK ( email <> '' ) ); +CREATE TABLE IF NOT EXISTS persons ( + person_id INT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + first_name TEXT NOT NULL, + second_name TEXT NOT NULL, + middle_name TEXT NOT NULL, + phone_id INTEGER NOT NULL, + email_id INTEGER NOT NULL, + sex SEX NOT NULL, + FOREIGN KEY (email_id) REFERENCES table_email(id), + FOREIGN KEY (phone_id) REFERENCES table_phone(id) +); -CREATE TABLE employees ( - employee_id SERIAL PRIMARY KEY, - person_id INTEGER NOT NULL UNIQUE REFERENCES persons(person_id), +CREATE TABLE IF NOT EXISTS employees ( + employee_id INT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + person_id INTEGER NOT NULL, position TEXT NOT NULL, - salary NUMERIC, - employment_date DATE NOT NULL + salary NUMERIC(10,2) NOT NULL, + employment_date DATE NOT NULL, + FOREIGN KEY (person_id) REFERENCES persons(person_id) ); - -CREATE TABLE customers ( - customer_id SERIAL PRIMARY KEY, - person_id INTEGER NOT NULL UNIQUE REFERENCES persons(person_id), +CREATE TABLE IF NOT EXISTS customers ( + customer_id INT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + person_id INTEGER NOT NULL, discount_rate NUMERIC(3,2) NOT NULL DEFAULT 0.00, subscription BOOLEAN NOT NULL DEFAULT FALSE, - registration_date DATE DEFAULT CURRENT_DATE + registration_date DATE DEFAULT CURRENT_DATE, + FOREIGN KEY (person_id) REFERENCES persons(person_id) ); - -CREATE TABLE sales_transactions ( - transaction_id SERIAL PRIMARY KEY, +CREATE TABLE IF NOT EXISTS sales_transactions ( + transaction_id INT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, transaction_date DATE NOT NULL DEFAULT CURRENT_DATE, - customer_id INTEGER NOT NULL REFERENCES customers(customer_id), - employee_id INTEGER NOT NULL REFERENCES employees(employee_id), - total_before_discount NUMERIC NOT NULL, - product_discount_applied NUMERIC DEFAULT 0, - personal_discount_applied NUMERIC DEFAULT 0, - transaction_total NUMERIC NOT NULL + customer_id INTEGER NOT NULL, + employee_id INTEGER NOT NULL, + total_before_discount NUMERIC(10,2) NOT NULL, + transaction_total NUMERIC(10,2) NOT NULL, + FOREIGN KEY (customer_id) REFERENCES customers(customer_id), + FOREIGN KEY (employee_id) REFERENCES employees(employee_id) ); - -CREATE TABLE transaction_items ( - item_id SERIAL PRIMARY KEY, - transaction_id INTEGER NOT NULL REFERENCES sales_transactions(transaction_id), - product_id INTEGER NOT NULL REFERENCES products(product_id), +CREATE TABLE IF NOT EXISTS transaction_items ( + item_id INT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + transaction_id INTEGER NOT NULL, + product_id INTEGER NOT NULL, quantity INTEGER NOT NULL CHECK (quantity > 0), - unit_price NUMERIC NOT NULL, + unit_price NUMERIC(10,2) NOT NULL, applied_discount_rate NUMERIC(5,2) DEFAULT 0, - item_total NUMERIC NOT NULL -); \ No newline at end of file + item_total NUMERIC(10,2) NOT NULL, + FOREIGN KEY (transaction_id) REFERENCES sales_transactions(transaction_id) ON DELETE CASCADE, + FOREIGN KEY (product_id) REFERENCES products(product_id) +); + +CREATE OR REPLACE FUNCTION update_product_stock() +RETURNS TRIGGER AS $$ +BEGIN + + IF (SELECT stock_quantity FROM products WHERE product_id = NEW.product_id) < NEW.quantity THEN + RAISE EXCEPTION 'Недостаточно товара на складе. ID товара: %', NEW.product_id; + END IF; + + UPDATE products + SET stock_quantity = stock_quantity - NEW.quantity + WHERE product_id = NEW.product_id; + + RETURN NEW; +END; +$$ LANGUAGE plpgsql; + +DROP TRIGGER IF EXISTS trg_update_stock_on_sale ON transaction_items; +CREATE TRIGGER trg_update_stock_on_sale +AFTER INSERT ON transaction_items +FOR EACH ROW +EXECUTE FUNCTION update_product_stock(); + +INSERT INTO manufacturers (manufacturer_name) VALUES +('Производитель 1'), +('Производитель 2'), +('Производитель 3') +ON CONFLICT (manufacturer_name) DO NOTHING; + +INSERT INTO products (manufacturer_id, product_category, product_name, selling_price, purchase_cost, stock_quantity) +VALUES +(1, 'Электроника', 'Телефон', 50000.00, 40000.00, 100), +(2, 'Одежда', 'Футболка', 1500.00, 800.00, 200) +ON CONFLICT DO NOTHING; + +INSERT INTO product_descriptions (product_id, description) +VALUES +(1, 'Смартфон'), +(2, 'футболка') +ON CONFLICT (product_id) DO NOTHING; \ No newline at end of file From 615a83533144e89b6a40c5547d4bfb8821d36530 Mon Sep 17 00:00:00 2001 From: emokid Date: Mon, 8 Dec 2025 21:32:22 +0300 Subject: [PATCH 5/7] Add files via upload Signed-off-by: emokid --- shop_db.sql | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/shop_db.sql b/shop_db.sql index cf154d3..519dc71 100644 --- a/shop_db.sql +++ b/shop_db.sql @@ -1,13 +1,13 @@ CREATE TYPE SEX AS ENUM ('m', 'f'); -CREATE TABLE IF NOT EXISTS manufacturers ( +CREATE TABLE manufacturers ( manufacturer_id INT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, manufacturer_name TEXT NOT NULL UNIQUE, contact_info TEXT, address TEXT ); -CREATE TABLE IF NOT EXISTS products ( +CREATE TABLE products ( product_id INT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, manufacturer_id INTEGER NOT NULL, product_category TEXT NOT NULL, @@ -19,24 +19,24 @@ CREATE TABLE IF NOT EXISTS products ( FOREIGN KEY (manufacturer_id) REFERENCES manufacturers(manufacturer_id) ); -CREATE TABLE IF NOT EXISTS product_descriptions ( +CREATE TABLE product_descriptions ( description_id INT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, product_id INTEGER NOT NULL UNIQUE, description TEXT, FOREIGN KEY (product_id) REFERENCES products(product_id) ON DELETE CASCADE ); -CREATE TABLE IF NOT EXISTS table_phone ( +CREATE TABLE table_phone ( id INT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, phone TEXT NOT NULL CHECK ( phone <> '' ) ); -CREATE TABLE IF NOT EXISTS table_email ( +CREATE TABLE table_email ( id INT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, email TEXT NOT NULL CHECK ( email <> '' ) ); -CREATE TABLE IF NOT EXISTS persons ( +CREATE TABLE persons ( person_id INT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, first_name TEXT NOT NULL, second_name TEXT NOT NULL, @@ -48,7 +48,7 @@ CREATE TABLE IF NOT EXISTS persons ( FOREIGN KEY (phone_id) REFERENCES table_phone(id) ); -CREATE TABLE IF NOT EXISTS employees ( +CREATE TABLE employees ( employee_id INT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, person_id INTEGER NOT NULL, position TEXT NOT NULL, @@ -57,7 +57,7 @@ CREATE TABLE IF NOT EXISTS employees ( FOREIGN KEY (person_id) REFERENCES persons(person_id) ); -CREATE TABLE IF NOT EXISTS customers ( +CREATE TABLE customers ( customer_id INT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, person_id INTEGER NOT NULL, discount_rate NUMERIC(3,2) NOT NULL DEFAULT 0.00, @@ -66,7 +66,7 @@ CREATE TABLE IF NOT EXISTS customers ( FOREIGN KEY (person_id) REFERENCES persons(person_id) ); -CREATE TABLE IF NOT EXISTS sales_transactions ( +CREATE TABLE sales_transactions ( transaction_id INT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, transaction_date DATE NOT NULL DEFAULT CURRENT_DATE, customer_id INTEGER NOT NULL, @@ -77,7 +77,7 @@ CREATE TABLE IF NOT EXISTS sales_transactions ( FOREIGN KEY (employee_id) REFERENCES employees(employee_id) ); -CREATE TABLE IF NOT EXISTS transaction_items ( +CREATE TABLE transaction_items ( item_id INT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, transaction_id INTEGER NOT NULL, product_id INTEGER NOT NULL, From f2f620c3272b78b33353fcf3d26794573307b32d Mon Sep 17 00:00:00 2001 From: emokid Date: Mon, 8 Dec 2025 22:11:52 +0300 Subject: [PATCH 6/7] Add files via upload Signed-off-by: emokid --- shop_db.sql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shop_db.sql b/shop_db.sql index 519dc71..cc2869b 100644 --- a/shop_db.sql +++ b/shop_db.sql @@ -94,7 +94,7 @@ RETURNS TRIGGER AS $$ BEGIN IF (SELECT stock_quantity FROM products WHERE product_id = NEW.product_id) < NEW.quantity THEN - RAISE EXCEPTION 'Недостаточно товара на складе. ID товара: %', NEW.product_id; + RAISE EXCEPTION 'Недостаточно товара на складе. ', NEW.product_id; END IF; UPDATE products @@ -107,7 +107,7 @@ $$ LANGUAGE plpgsql; DROP TRIGGER IF EXISTS trg_update_stock_on_sale ON transaction_items; CREATE TRIGGER trg_update_stock_on_sale -AFTER INSERT ON transaction_items +BEFORE INSERT ON transaction_items FOR EACH ROW EXECUTE FUNCTION update_product_stock(); From 536ee3569d6b4236c6e4bc5591f42670a3d39861 Mon Sep 17 00:00:00 2001 From: emokid Date: Mon, 8 Dec 2025 22:13:45 +0300 Subject: [PATCH 7/7] Add files via upload Signed-off-by: emokid --- shop_db.sql | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/shop_db.sql b/shop_db.sql index cc2869b..6c2b15e 100644 --- a/shop_db.sql +++ b/shop_db.sql @@ -115,16 +115,15 @@ INSERT INTO manufacturers (manufacturer_name) VALUES ('Производитель 1'), ('Производитель 2'), ('Производитель 3') -ON CONFLICT (manufacturer_name) DO NOTHING; + INSERT INTO products (manufacturer_id, product_category, product_name, selling_price, purchase_cost, stock_quantity) VALUES (1, 'Электроника', 'Телефон', 50000.00, 40000.00, 100), (2, 'Одежда', 'Футболка', 1500.00, 800.00, 200) -ON CONFLICT DO NOTHING; + INSERT INTO product_descriptions (product_id, description) VALUES (1, 'Смартфон'), (2, 'футболка') -ON CONFLICT (product_id) DO NOTHING; \ No newline at end of file