diff --git a/shop_db.sql b/shop_db.sql new file mode 100644 index 0000000..6c2b15e --- /dev/null +++ b/shop_db.sql @@ -0,0 +1,129 @@ +CREATE TYPE SEX AS ENUM ('m', 'f'); + +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 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(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_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 table_phone ( + id INT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + phone TEXT NOT NULL CHECK ( phone <> '' ) +); + +CREATE TABLE table_email ( + id INT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + email TEXT NOT NULL CHECK ( email <> '' ) +); + +CREATE TABLE 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 INT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + person_id INTEGER NOT NULL, + position TEXT 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 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, + FOREIGN KEY (person_id) REFERENCES persons(person_id) +); + +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, + 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 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(10,2) NOT NULL, + applied_discount_rate NUMERIC(5,2) DEFAULT 0, + 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 'Недостаточно товара на складе. ', 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 +BEFORE INSERT ON transaction_items +FOR EACH ROW +EXECUTE FUNCTION update_product_stock(); + +INSERT INTO manufacturers (manufacturer_name) VALUES +('Производитель 1'), +('Производитель 2'), +('Производитель 3') + + +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) + + +INSERT INTO product_descriptions (product_id, description) +VALUES +(1, 'Смартфон'), +(2, 'футболка')