441 lines
13 KiB
SQL
441 lines
13 KiB
SQL
-- E-Commerce Database Schema
|
|
-- Run this file to create database, user, tables and populate initial data
|
|
-- Usage: psql -U postgres -h localhost -f schema.sql
|
|
|
|
-- ============================================
|
|
-- CREATE DATABASE AND USER
|
|
-- ============================================
|
|
|
|
-- Drop existing database and user if they exist (for clean setup)
|
|
DROP DATABASE IF EXISTS ecommerce_db;
|
|
DROP USER IF EXISTS ecommerce_user;
|
|
|
|
-- Create database (Windows compatible - uses system defaults)
|
|
CREATE DATABASE ecommerce_db
|
|
WITH
|
|
OWNER = postgres
|
|
ENCODING = 'UTF8'
|
|
TABLESPACE = pg_default
|
|
CONNECTION LIMIT = -1;
|
|
|
|
-- Create user with password
|
|
CREATE USER ecommerce_user WITH PASSWORD 'password';
|
|
|
|
-- Grant all privileges on database to user
|
|
GRANT ALL PRIVILEGES ON DATABASE ecommerce_db TO ecommerce_user;
|
|
|
|
-- Connect to the ecommerce_db database
|
|
\c ecommerce_db
|
|
|
|
-- Grant schema privileges including CREATE permission
|
|
GRANT ALL ON SCHEMA public TO ecommerce_user;
|
|
GRANT CREATE ON SCHEMA public TO ecommerce_user;
|
|
|
|
-- Make ecommerce_user owner of public schema to avoid permission issues
|
|
ALTER SCHEMA public OWNER TO ecommerce_user;
|
|
|
|
-- Grant privileges on all current and future tables
|
|
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO ecommerce_user;
|
|
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO ecommerce_user;
|
|
GRANT ALL PRIVILEGES ON ALL FUNCTIONS IN SCHEMA public TO ecommerce_user;
|
|
|
|
-- Grant privileges on future objects
|
|
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES TO ecommerce_user;
|
|
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON SEQUENCES TO ecommerce_user;
|
|
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON FUNCTIONS TO ecommerce_user;
|
|
|
|
-- ============================================
|
|
-- CREATE TABLES
|
|
-- ============================================
|
|
|
|
-- Category Table
|
|
CREATE TABLE category (
|
|
id SERIAL PRIMARY KEY,
|
|
name VARCHAR(100) UNIQUE NOT NULL,
|
|
slug VARCHAR(100) UNIQUE NOT NULL,
|
|
description TEXT,
|
|
image VARCHAR(500)
|
|
);
|
|
|
|
-- Model Table (e.g., New Balance 9060)
|
|
CREATE TABLE model (
|
|
id SERIAL PRIMARY KEY,
|
|
name VARCHAR(255) NOT NULL,
|
|
category_id INTEGER NOT NULL,
|
|
brand VARCHAR(100) NOT NULL,
|
|
base_price DECIMAL(10, 2),
|
|
sizes JSONB,
|
|
description TEXT,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
FOREIGN KEY (category_id) REFERENCES category(id) ON DELETE CASCADE,
|
|
UNIQUE (name, category_id, brand)
|
|
);
|
|
|
|
CREATE INDEX idx_model_category ON model(category_id);
|
|
CREATE INDEX idx_model_brand ON model(brand);
|
|
|
|
-- User Table
|
|
CREATE TABLE "user" (
|
|
id SERIAL PRIMARY KEY,
|
|
email VARCHAR(255) UNIQUE NOT NULL,
|
|
hashed_password VARCHAR(255) NOT NULL,
|
|
full_name VARCHAR(255),
|
|
phone VARCHAR(20),
|
|
address TEXT,
|
|
city VARCHAR(100),
|
|
postal_code VARCHAR(20),
|
|
country VARCHAR(100),
|
|
is_active BOOLEAN DEFAULT TRUE,
|
|
is_admin BOOLEAN DEFAULT FALSE,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
-- Product Table
|
|
CREATE TABLE product (
|
|
id SERIAL PRIMARY KEY,
|
|
name VARCHAR(255) NOT NULL,
|
|
slug VARCHAR(255) UNIQUE,
|
|
description TEXT,
|
|
price DECIMAL(10, 2) NOT NULL,
|
|
discount_price DECIMAL(10, 2),
|
|
category_id INTEGER NOT NULL,
|
|
model_id INTEGER,
|
|
gender VARCHAR(50),
|
|
brand VARCHAR(100),
|
|
sizes JSONB,
|
|
colors JSONB,
|
|
stock INTEGER DEFAULT 0,
|
|
images JSONB,
|
|
is_featured BOOLEAN DEFAULT FALSE,
|
|
is_on_sale BOOLEAN DEFAULT FALSE,
|
|
override_price DECIMAL(10, 2),
|
|
override_sizes JSONB,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
FOREIGN KEY (category_id) REFERENCES category(id) ON DELETE CASCADE,
|
|
FOREIGN KEY (model_id) REFERENCES model(id) ON DELETE SET NULL
|
|
);
|
|
|
|
CREATE INDEX idx_product_slug ON product(slug);
|
|
CREATE INDEX idx_product_model ON product(model_id);
|
|
|
|
-- Cart Table
|
|
CREATE TABLE cart (
|
|
id SERIAL PRIMARY KEY,
|
|
user_id INTEGER UNIQUE NOT NULL,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
FOREIGN KEY (user_id) REFERENCES "user"(id) ON DELETE CASCADE
|
|
);
|
|
|
|
-- Cart Item Table
|
|
CREATE TABLE cart_item (
|
|
id SERIAL PRIMARY KEY,
|
|
cart_id INTEGER NOT NULL,
|
|
product_id INTEGER NOT NULL,
|
|
quantity INTEGER DEFAULT 1,
|
|
size VARCHAR(50),
|
|
color VARCHAR(50),
|
|
FOREIGN KEY (cart_id) REFERENCES cart(id) ON DELETE CASCADE,
|
|
FOREIGN KEY (product_id) REFERENCES product(id) ON DELETE CASCADE
|
|
);
|
|
|
|
-- Order Table
|
|
CREATE TABLE "order" (
|
|
id SERIAL PRIMARY KEY,
|
|
user_id INTEGER NOT NULL,
|
|
order_number VARCHAR(100) UNIQUE NOT NULL,
|
|
status VARCHAR(50) DEFAULT 'pending',
|
|
total_amount DECIMAL(10, 2) NOT NULL,
|
|
shipping_address TEXT,
|
|
shipping_city VARCHAR(100),
|
|
shipping_postal_code VARCHAR(20),
|
|
shipping_country VARCHAR(100),
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
FOREIGN KEY (user_id) REFERENCES "user"(id) ON DELETE CASCADE
|
|
);
|
|
|
|
-- Order Item Table
|
|
CREATE TABLE order_item (
|
|
id SERIAL PRIMARY KEY,
|
|
order_id INTEGER NOT NULL,
|
|
product_id INTEGER NOT NULL,
|
|
quantity INTEGER NOT NULL,
|
|
price DECIMAL(10, 2) NOT NULL,
|
|
size VARCHAR(50),
|
|
color VARCHAR(50),
|
|
FOREIGN KEY (order_id) REFERENCES "order"(id) ON DELETE CASCADE,
|
|
FOREIGN KEY (product_id) REFERENCES product(id) ON DELETE CASCADE
|
|
);
|
|
|
|
-- Wishlist (User-Product Association)
|
|
CREATE TABLE user_wishlist (
|
|
user_id INTEGER NOT NULL,
|
|
product_id INTEGER NOT NULL,
|
|
PRIMARY KEY (user_id, product_id),
|
|
FOREIGN KEY (user_id) REFERENCES "user"(id) ON DELETE CASCADE,
|
|
FOREIGN KEY (product_id) REFERENCES product(id) ON DELETE CASCADE
|
|
);
|
|
|
|
-- Contact Message Table
|
|
CREATE TABLE contact_message (
|
|
id SERIAL PRIMARY KEY,
|
|
name VARCHAR(255),
|
|
email VARCHAR(255),
|
|
subject VARCHAR(255),
|
|
message TEXT,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
-- ============================================
|
|
-- CREATE INDEXES
|
|
-- ============================================
|
|
CREATE INDEX idx_user_email ON "user"(email);
|
|
CREATE INDEX idx_product_name ON product(name);
|
|
CREATE INDEX idx_product_category ON product(category_id);
|
|
CREATE INDEX idx_product_is_featured ON product(is_featured);
|
|
CREATE INDEX idx_product_is_on_sale ON product(is_on_sale);
|
|
CREATE INDEX idx_order_user ON "order"(user_id);
|
|
CREATE INDEX idx_order_created_at ON "order"(created_at);
|
|
CREATE INDEX idx_cart_item_cart ON cart_item(cart_id);
|
|
CREATE INDEX idx_order_item_order ON order_item(order_id);
|
|
|
|
-- ============================================
|
|
-- POPULATE INITIAL DATA
|
|
-- ============================================
|
|
|
|
-- Insert Categories
|
|
INSERT INTO category (name, slug, description) VALUES
|
|
('Shoes', 'shoes', 'Footwear for all occasions'),
|
|
('Shirts', 'shirts', 'T-shirts and casual tops'),
|
|
('Pants', 'pants', 'Jeans and trousers'),
|
|
('Hats', 'hats', 'Caps and beanies'),
|
|
('Accessories', 'accessories', 'Bags, belts, and more');
|
|
|
|
-- Insert Sample Products (Shoes - Featured)
|
|
INSERT INTO product (name, description, price, discount_price, category_id, gender, brand, sizes, colors, stock, images, is_featured, is_on_sale) VALUES
|
|
(
|
|
'Premium Running Shoes',
|
|
'High-performance running shoes with advanced cushioning technology',
|
|
129.99,
|
|
99.99,
|
|
1,
|
|
'men',
|
|
'Nike',
|
|
'["7", "8", "9", "10", "11", "12", "13"]',
|
|
'["Black", "White", "Blue"]',
|
|
50,
|
|
'["https://via.placeholder.com/300x300?text=Nike+Running"]',
|
|
TRUE,
|
|
TRUE
|
|
),
|
|
(
|
|
'Women Athletic Sneakers',
|
|
'Comfortable athletic sneakers for everyday wear',
|
|
99.99,
|
|
NULL,
|
|
1,
|
|
'women',
|
|
'Adidas',
|
|
'["5", "6", "7", "8", "9", "10"]',
|
|
'["Pink", "White", "Purple"]',
|
|
45,
|
|
'["https://via.placeholder.com/300x300?text=Adidas+Sneakers"]',
|
|
TRUE,
|
|
FALSE
|
|
),
|
|
(
|
|
'Basketball High Tops',
|
|
'Professional basketball shoes with ankle support',
|
|
149.99,
|
|
NULL,
|
|
1,
|
|
'men',
|
|
'Jordan',
|
|
'["8", "9", "10", "11", "12", "13"]',
|
|
'["Red", "Black", "Gold"]',
|
|
30,
|
|
'["https://via.placeholder.com/300x300?text=Jordan+High"]',
|
|
TRUE,
|
|
FALSE
|
|
),
|
|
(
|
|
'Casual Leather Loafers',
|
|
'Classic leather loafers for formal occasions',
|
|
139.99,
|
|
109.99,
|
|
1,
|
|
'men',
|
|
'Cole Haan',
|
|
'["7", "8", "9", "10", "11", "12"]',
|
|
'["Brown", "Black"]',
|
|
25,
|
|
'["https://via.placeholder.com/300x300?text=Cole+Haan+Loafers"]',
|
|
TRUE,
|
|
TRUE
|
|
),
|
|
(
|
|
'Hiking Boot Pro',
|
|
'Durable hiking boots with waterproof technology',
|
|
179.99,
|
|
149.99,
|
|
1,
|
|
'men',
|
|
'Salomon',
|
|
'["8", "9", "10", "11", "12", "13"]',
|
|
'["Brown", "Gray", "Black"]',
|
|
35,
|
|
'["https://via.placeholder.com/300x300?text=Salomon+Hiking"]',
|
|
TRUE,
|
|
TRUE
|
|
);
|
|
|
|
-- Insert Sample Products (Clothing)
|
|
INSERT INTO product (name, description, price, discount_price, category_id, gender, brand, sizes, colors, stock, images, is_featured, is_on_sale) VALUES
|
|
(
|
|
'Classic Cotton T-Shirt',
|
|
'Comfortable everyday cotton t-shirt',
|
|
29.99,
|
|
NULL,
|
|
2,
|
|
'men',
|
|
'Gap',
|
|
'["S", "M", "L", "XL", "XXL"]',
|
|
'["Red", "Blue", "White", "Black"]',
|
|
100,
|
|
'["https://via.placeholder.com/300x300?text=Cotton+Tee"]',
|
|
FALSE,
|
|
FALSE
|
|
),
|
|
(
|
|
'Silk Blouse',
|
|
'Elegant silk blouse for professional settings',
|
|
89.99,
|
|
69.99,
|
|
2,
|
|
'women',
|
|
'Hugo Boss',
|
|
'["XS", "S", "M", "L", "XL"]',
|
|
'["White", "Black", "Navy"]',
|
|
40,
|
|
'["https://via.placeholder.com/300x300?text=Silk+Blouse"]',
|
|
FALSE,
|
|
TRUE
|
|
),
|
|
(
|
|
'Slim Fit Jeans',
|
|
'Modern slim fit jeans with stretch fabric',
|
|
79.99,
|
|
59.99,
|
|
3,
|
|
'men',
|
|
'Levi''s',
|
|
'["28", "30", "32", "34", "36", "38"]',
|
|
'["Dark Blue", "Light Blue", "Black"]',
|
|
60,
|
|
'["https://via.placeholder.com/300x300?text=Slim+Jeans"]',
|
|
FALSE,
|
|
TRUE
|
|
),
|
|
(
|
|
'Yoga Leggings',
|
|
'High-waist yoga leggings with moisture-wicking',
|
|
89.99,
|
|
NULL,
|
|
3,
|
|
'women',
|
|
'Lululemon',
|
|
'["XS", "S", "M", "L", "XL"]',
|
|
'["Black", "Navy", "Purple", "Gray"]',
|
|
55,
|
|
'["https://via.placeholder.com/300x300?text=Yoga+Leggings"]',
|
|
TRUE,
|
|
FALSE
|
|
);
|
|
|
|
-- Insert Sample Users (for testing)
|
|
INSERT INTO "user" (email, hashed_password, full_name, phone, address, city, postal_code, country, is_active, is_admin) VALUES
|
|
(
|
|
'admin@example.com',
|
|
'$2b$12$jNWZdZNMbKEkOjA8Gq3ZUOTml23zfqhFDPJ8AlZQ51WhUyi04AH7C', -- password: password123
|
|
'Admin User',
|
|
'1234567890',
|
|
'123 Admin Street',
|
|
'New York',
|
|
'10001',
|
|
'USA',
|
|
TRUE,
|
|
TRUE
|
|
),
|
|
(
|
|
'user@example.com',
|
|
'$2b$12$jNWZdZNMbKEkOjA8Gq3ZUOTml23zfqhFDPJ8AlZQ51WhUyi04AH7C', -- password: password123
|
|
'John Doe',
|
|
'1234567890',
|
|
'123 Main Street',
|
|
'New York',
|
|
'10001',
|
|
'USA',
|
|
TRUE,
|
|
FALSE
|
|
),
|
|
(
|
|
'jane@example.com',
|
|
'$2b$12$jNWZdZNMbKEkOjA8Gq3ZUOTml23zfqhFDPJ8AlZQ51WhUyi04AH7C', -- password: password123
|
|
'Jane Smith',
|
|
'9876543210',
|
|
'456 Oak Avenue',
|
|
'Los Angeles',
|
|
'90001',
|
|
'USA',
|
|
TRUE,
|
|
FALSE
|
|
);
|
|
|
|
-- Create carts for users
|
|
INSERT INTO cart (user_id) VALUES
|
|
(1),
|
|
(2),
|
|
(3);
|
|
|
|
-- ============================================
|
|
-- SET PERMISSIONS (After all tables are created)
|
|
-- ============================================
|
|
-- Grant all privileges on all tables, sequences, and functions to the user
|
|
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO ecommerce_user;
|
|
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO ecommerce_user;
|
|
GRANT ALL PRIVILEGES ON ALL FUNCTIONS IN SCHEMA public TO ecommerce_user;
|
|
|
|
-- Ensure future objects also get permissions
|
|
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES TO ecommerce_user;
|
|
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON SEQUENCES TO ecommerce_user;
|
|
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON FUNCTIONS TO ecommerce_user;
|
|
|
|
-- ============================================
|
|
-- COMPLETE
|
|
-- ============================================
|
|
-- Schema created successfully!
|
|
--
|
|
-- Database: ecommerce_db
|
|
-- User: ecommerce_user
|
|
-- Password: password
|
|
-- Host: localhost:5432
|
|
--
|
|
-- Connection string for .env file:
|
|
-- DATABASE_URL=postgresql://ecommerce_user:password@localhost:5432/ecommerce_db
|
|
--
|
|
-- Tables created: 9
|
|
-- - category, user, product, cart, cart_item
|
|
-- - order, order_item, user_wishlist, contact_message
|
|
--
|
|
-- Demo accounts:
|
|
-- - ADMIN: admin@example.com / password123 (is_admin: true)
|
|
-- - USER: user@example.com / password123
|
|
-- - USER: jane@example.com / password123
|
|
--
|
|
-- Sample data: 5 categories, 9 products, 3 users
|
|
--
|
|
-- Next steps:
|
|
-- 1. Update backend/.env with: DATABASE_URL=postgresql://ecommerce_user:password@localhost:5432/ecommerce_db
|
|
-- 2. Run: python backend/app/main.py
|
|
-- 3. Login as admin to create/edit/delete products
|