101 lines
3.8 KiB
SQL
101 lines
3.8 KiB
SQL
-- Cargo ERP Database Schema
|
|
|
|
-- Provinces table
|
|
CREATE TABLE IF NOT EXISTS provinces (
|
|
id SERIAL PRIMARY KEY,
|
|
code VARCHAR(10) NOT NULL UNIQUE,
|
|
name VARCHAR(100) NOT NULL
|
|
);
|
|
|
|
-- Cities table
|
|
CREATE TABLE IF NOT EXISTS cities (
|
|
id SERIAL PRIMARY KEY,
|
|
code VARCHAR(10) NOT NULL,
|
|
name VARCHAR(100) NOT NULL,
|
|
province_id INTEGER REFERENCES provinces(id) ON DELETE CASCADE
|
|
);
|
|
|
|
-- Districts table
|
|
CREATE TABLE IF NOT EXISTS districts (
|
|
id SERIAL PRIMARY KEY,
|
|
code VARCHAR(10) NOT NULL,
|
|
name VARCHAR(100) NOT NULL,
|
|
city_id INTEGER REFERENCES cities(id) ON DELETE CASCADE
|
|
);
|
|
|
|
-- Subdistricts table
|
|
CREATE TABLE IF NOT EXISTS subdistricts (
|
|
id SERIAL PRIMARY KEY,
|
|
code VARCHAR(10) NOT NULL,
|
|
name VARCHAR(100) NOT NULL,
|
|
district_id INTEGER REFERENCES districts(id) ON DELETE CASCADE
|
|
);
|
|
|
|
-- Merchants table
|
|
CREATE TABLE IF NOT EXISTS merchants (
|
|
id SERIAL PRIMARY KEY,
|
|
name VARCHAR(255) NOT NULL,
|
|
code VARCHAR(50) NOT NULL UNIQUE,
|
|
address TEXT NOT NULL,
|
|
phone VARCHAR(20) NOT NULL,
|
|
email VARCHAR(255) NOT NULL,
|
|
province_id INTEGER REFERENCES provinces(id),
|
|
city_id INTEGER REFERENCES cities(id),
|
|
district_id INTEGER REFERENCES districts(id),
|
|
subdistrict_id INTEGER REFERENCES subdistricts(id),
|
|
postcode VARCHAR(10),
|
|
status VARCHAR(20) NOT NULL DEFAULT 'active',
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
|
);
|
|
|
|
-- Users table
|
|
CREATE TABLE IF NOT EXISTS users (
|
|
id SERIAL PRIMARY KEY,
|
|
merchant_id INTEGER REFERENCES merchants(id) ON DELETE SET NULL,
|
|
username VARCHAR(100) NOT NULL UNIQUE,
|
|
email VARCHAR(255) NOT NULL UNIQUE,
|
|
password VARCHAR(255) NOT NULL,
|
|
role VARCHAR(20) NOT NULL CHECK (role IN ('admin', 'administrasi', 'warehouse', 'cashier')),
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
|
);
|
|
|
|
-- Orders table
|
|
CREATE TABLE IF NOT EXISTS orders (
|
|
id SERIAL PRIMARY KEY,
|
|
merchant_id INTEGER NOT NULL REFERENCES merchants(id) ON DELETE CASCADE,
|
|
order_number VARCHAR(50) NOT NULL UNIQUE,
|
|
customer_name VARCHAR(255) NOT NULL,
|
|
customer_phone VARCHAR(20) NOT NULL,
|
|
pickup_address TEXT NOT NULL,
|
|
delivery_address TEXT NOT NULL,
|
|
pickup_subdistrict_id INTEGER REFERENCES subdistricts(id),
|
|
delivery_subdistrict_id INTEGER REFERENCES subdistricts(id),
|
|
status VARCHAR(20) NOT NULL DEFAULT 'pending' CHECK (status IN ('pending', 'picked_up', 'in_transit', 'delivered', 'cancelled')),
|
|
weight DECIMAL(10,2) NOT NULL,
|
|
price DECIMAL(15,2) NOT NULL,
|
|
notes TEXT,
|
|
created_by INTEGER REFERENCES users(id),
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
|
);
|
|
|
|
-- Indexes
|
|
CREATE INDEX IF NOT EXISTS idx_cities_province_id ON cities(province_id);
|
|
CREATE INDEX IF NOT EXISTS idx_districts_city_id ON districts(city_id);
|
|
CREATE INDEX IF NOT EXISTS idx_subdistricts_district_id ON subdistricts(district_id);
|
|
CREATE INDEX IF NOT EXISTS idx_merchants_status ON merchants(status);
|
|
CREATE INDEX IF NOT EXISTS idx_users_username ON users(username);
|
|
CREATE INDEX IF NOT EXISTS idx_users_email ON users(email);
|
|
CREATE INDEX IF NOT EXISTS idx_orders_merchant_id ON orders(merchant_id);
|
|
CREATE INDEX IF NOT EXISTS idx_orders_order_number ON orders(order_number);
|
|
CREATE INDEX IF NOT EXISTS idx_orders_status ON orders(status);
|
|
CREATE INDEX IF NOT EXISTS idx_orders_created_at ON orders(created_at);
|
|
|
|
-- Insert sample admin user (password: admin123)
|
|
-- The password hash below is for "admin123" with bcrypt cost 10
|
|
INSERT INTO users (username, email, password, role) VALUES
|
|
('admin', 'admin@cargo-erp.com', '$2a$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy', 'admin')
|
|
ON CONFLICT (username) DO NOTHING;
|