Files
warehouse-management-BE/db/init/init.sql
Tran Anh Tuan 6a4a96e0ca Base Project
2026-05-08 14:32:24 +07:00

485 lines
21 KiB
PL/PgSQL

-- ============================================================
-- Warehouse Management Database - Init Script (PostgreSQL)
-- Based on WareHouseDB.md specification
-- ============================================================
-- ============================================================
-- ENUM Types
-- ============================================================
CREATE TYPE container_type_enum AS ENUM ('empty_box', 'tray', 'paper_box', 'plastic_box', 'bag', 'other');
CREATE TYPE component_item_status_enum AS ENUM ('normal', 'damaged', 'long_unused', 'expired', 'pending_inspection');
CREATE TYPE invoice_type_enum AS ENUM ('import', 'export');
CREATE TYPE invoice_status_enum AS ENUM ('draft', 'pending', 'approved', 'completed', 'cancelled');
CREATE TYPE transaction_type_enum AS ENUM ('import', 'export', 'adjustment', 'transfer');
-- ============================================================
-- Trigger function: auto-update updated_at
-- ============================================================
CREATE OR REPLACE FUNCTION update_updated_at_column()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = CURRENT_TIMESTAMP;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- ============================================================
-- 1. warehouses (Kho)
-- ============================================================
CREATE TABLE warehouses (
id BIGSERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
description TEXT,
address VARCHAR(500),
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TRIGGER trg_warehouses_updated_at
BEFORE UPDATE ON warehouses
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
-- ============================================================
-- 2. rooms (Phòng)
-- ============================================================
CREATE TABLE rooms (
id BIGSERIAL PRIMARY KEY,
warehouse_id BIGINT NOT NULL REFERENCES warehouses(id),
name VARCHAR(255) NOT NULL,
description TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TRIGGER trg_rooms_updated_at
BEFORE UPDATE ON rooms
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
-- ============================================================
-- 3. cabinets (Tủ)
-- ============================================================
CREATE TABLE cabinets (
id BIGSERIAL PRIMARY KEY,
room_id BIGINT NOT NULL REFERENCES rooms(id),
name VARCHAR(255) NOT NULL,
description TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TRIGGER trg_cabinets_updated_at
BEFORE UPDATE ON cabinets
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
-- ============================================================
-- 4. shelves (Tầng / Kệ)
-- ============================================================
CREATE TABLE shelves (
id BIGSERIAL PRIMARY KEY,
cabinet_id BIGINT NOT NULL REFERENCES cabinets(id),
name VARCHAR(255) NOT NULL,
level_index INT NOT NULL,
description TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TRIGGER trg_shelves_updated_at
BEFORE UPDATE ON shelves
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
-- ============================================================
-- 5. containers (Vật chứa)
-- ============================================================
CREATE TABLE containers (
id BIGSERIAL PRIMARY KEY,
shelf_id BIGINT NOT NULL REFERENCES shelves(id),
name VARCHAR(255) NOT NULL,
container_type container_type_enum NOT NULL,
description TEXT,
max_capacity INT,
metadata JSONB,
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TRIGGER trg_containers_updated_at
BEFORE UPDATE ON containers
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
-- ============================================================
-- 6. component_types (Loại linh kiện)
-- ============================================================
CREATE TABLE component_types (
id BIGSERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
description TEXT,
metadata JSONB,
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT uk_component_types_name UNIQUE (name)
);
CREATE TRIGGER trg_component_types_updated_at
BEFORE UPDATE ON component_types
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
-- ============================================================
-- 7. components (Linh kiện)
-- ============================================================
CREATE TABLE components (
id BIGSERIAL PRIMARY KEY,
component_type_id BIGINT NOT NULL REFERENCES component_types(id),
name VARCHAR(255) NOT NULL,
description TEXT,
unit VARCHAR(50) NOT NULL DEFAULT 'cái',
total_quantity INT NOT NULL DEFAULT 0,
min_quantity INT NOT NULL DEFAULT 0,
metadata JSONB,
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TRIGGER trg_components_updated_at
BEFORE UPDATE ON components
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
-- ============================================================
-- 8. component_codes (Mã linh kiện)
-- ============================================================
CREATE TABLE component_codes (
id BIGSERIAL PRIMARY KEY,
component_id BIGINT NOT NULL REFERENCES components(id),
code VARCHAR(255) NOT NULL,
code_type VARCHAR(100),
is_primary BOOLEAN NOT NULL DEFAULT FALSE,
metadata JSONB,
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT uk_component_codes_code_type UNIQUE (code, code_type)
);
-- ============================================================
-- 9. component_items (Linh kiện tại từng vị trí)
-- ============================================================
CREATE TABLE component_items (
id BIGSERIAL PRIMARY KEY,
component_id BIGINT NOT NULL REFERENCES components(id),
container_id BIGINT NOT NULL REFERENCES containers(id),
quantity INT NOT NULL DEFAULT 0,
status component_item_status_enum NOT NULL DEFAULT 'normal',
metadata JSONB,
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT uk_component_items_comp_cont_status UNIQUE (component_id, container_id, status)
);
CREATE TRIGGER trg_component_items_updated_at
BEFORE UPDATE ON component_items
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
-- ============================================================
-- 10. component_status_history (Lịch sử thay đổi tình trạng)
-- ============================================================
CREATE TABLE component_status_history (
id BIGSERIAL PRIMARY KEY,
component_item_id BIGINT NOT NULL REFERENCES component_items(id),
old_status component_item_status_enum,
new_status component_item_status_enum NOT NULL,
changed_quantity INT,
note TEXT,
changed_by VARCHAR(255),
changed_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
);
-- ============================================================
-- 11. invoice_configs (Cấu hình hóa đơn mẫu)
-- ============================================================
CREATE TABLE invoice_configs (
id BIGSERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
type invoice_type_enum NOT NULL,
description TEXT,
is_active BOOLEAN NOT NULL DEFAULT TRUE,
metadata JSONB,
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TRIGGER trg_invoice_configs_updated_at
BEFORE UPDATE ON invoice_configs
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
-- ============================================================
-- 12. invoice_config_items (Chi tiết cấu hình hóa đơn)
-- ============================================================
CREATE TABLE invoice_config_items (
id BIGSERIAL PRIMARY KEY,
invoice_config_id BIGINT NOT NULL REFERENCES invoice_configs(id),
component_id BIGINT NOT NULL REFERENCES components(id),
required_quantity INT NOT NULL,
allow_alternative BOOLEAN NOT NULL DEFAULT FALSE,
priority_order INT NOT NULL DEFAULT 0,
note TEXT,
metadata JSONB,
CONSTRAINT uk_invoice_config_items_config_comp UNIQUE (invoice_config_id, component_id)
);
-- ============================================================
-- 13. alternative_components (Linh kiện thay thế)
-- ============================================================
CREATE TABLE alternative_components (
id BIGSERIAL PRIMARY KEY,
invoice_config_item_id BIGINT NOT NULL REFERENCES invoice_config_items(id),
alternative_component_id BIGINT NOT NULL REFERENCES components(id),
conversion_ratio DECIMAL(10,2) NOT NULL DEFAULT 1.00,
priority INT NOT NULL DEFAULT 0,
note TEXT,
metadata JSONB,
CONSTRAINT uk_alternative_components_item_alt UNIQUE (invoice_config_item_id, alternative_component_id)
);
-- ============================================================
-- 14. invoices (Hóa đơn nhập/xuất)
-- ============================================================
CREATE TABLE invoices (
id BIGSERIAL PRIMARY KEY,
invoice_code VARCHAR(100) NOT NULL,
type invoice_type_enum NOT NULL,
status invoice_status_enum NOT NULL DEFAULT 'draft',
invoice_config_id BIGINT REFERENCES invoice_configs(id),
total_items INT NOT NULL DEFAULT 0,
note TEXT,
created_by VARCHAR(255),
approved_by VARCHAR(255),
completed_at TIMESTAMPTZ,
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
metadata JSONB,
CONSTRAINT uk_invoices_invoice_code UNIQUE (invoice_code)
);
CREATE TRIGGER trg_invoices_updated_at
BEFORE UPDATE ON invoices
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
-- ============================================================
-- 15. invoice_items (Chi tiết hóa đơn)
-- ============================================================
CREATE TABLE invoice_items (
id BIGSERIAL PRIMARY KEY,
invoice_id BIGINT NOT NULL REFERENCES invoices(id),
component_id BIGINT NOT NULL REFERENCES components(id),
original_component_id BIGINT REFERENCES components(id),
required_quantity INT NOT NULL,
actual_quantity INT NOT NULL DEFAULT 0,
is_substituted BOOLEAN NOT NULL DEFAULT FALSE,
is_short BOOLEAN NOT NULL DEFAULT FALSE,
shortage_quantity INT NOT NULL DEFAULT 0,
note TEXT,
metadata JSONB,
CONSTRAINT uk_invoice_items_invoice_comp UNIQUE (invoice_id, component_id)
);
-- ============================================================
-- 16. invoice_item_locations (Vị trí xuất/nhập cho từng item)
-- ============================================================
CREATE TABLE invoice_item_locations (
id BIGSERIAL PRIMARY KEY,
invoice_item_id BIGINT NOT NULL REFERENCES invoice_items(id),
container_id BIGINT NOT NULL REFERENCES containers(id),
quantity INT NOT NULL
);
-- ============================================================
-- 17. invoice_status_history (Lịch sử trạng thái hóa đơn)
-- ============================================================
CREATE TABLE invoice_status_history (
id BIGSERIAL PRIMARY KEY,
invoice_id BIGINT NOT NULL REFERENCES invoices(id),
old_status VARCHAR(50),
new_status VARCHAR(50) NOT NULL,
changed_by VARCHAR(255),
note TEXT,
changed_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
);
-- ============================================================
-- 18. stock_transactions (Lịch sử nhập xuất kho)
-- ============================================================
CREATE TABLE stock_transactions (
id BIGSERIAL PRIMARY KEY,
invoice_id BIGINT NOT NULL REFERENCES invoices(id),
component_id BIGINT NOT NULL REFERENCES components(id),
container_id BIGINT NOT NULL REFERENCES containers(id),
transaction_type transaction_type_enum NOT NULL,
quantity INT NOT NULL,
balance_after INT,
note TEXT,
created_by VARCHAR(255),
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
username VARCHAR(50) UNIQUE NOT NULL,
email VARCHAR(255) UNIQUE NOT NULL,
password_hash VARCHAR(255) NOT NULL,
full_name VARCHAR(100),
is_active BOOLEAN DEFAULT TRUE,
created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
created_by VARCHAR(50)
);
-- Bảng Roles: Lưu các vai trò (admin, editor, viewer...)
CREATE TABLE roles (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name VARCHAR(50) UNIQUE NOT NULL,
description VARCHAR(255),
created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
created_by VARCHAR(50)
);
-- Bảng Permissions: Lưu các quyền hạn (read, write, delete...)
CREATE TABLE permissions (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name VARCHAR(100) UNIQUE NOT NULL,
description VARCHAR(255),
created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
created_by VARCHAR(50)
);
-- Bảng user_roles: Liên kết user với role (N-N)
CREATE TABLE user_roles (
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
role_id UUID NOT NULL REFERENCES roles(id) ON DELETE CASCADE,
assigned_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (user_id, role_id)
);
-- Bảng role_permissions: Liên kết role với permission (N-N)
CREATE TABLE role_permissions (
role_id UUID NOT NULL REFERENCES roles(id) ON DELETE CASCADE,
permission_id UUID NOT NULL REFERENCES permissions(id) ON DELETE CASCADE,
assigned_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (role_id, permission_id)
);
-- ============================================================
-- Indexes
-- ============================================================
-- Comment: Tạo index cho việc tìm kiếm nhanh (tùy chọn)
CREATE INDEX idx_users_username ON users(username);
CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_roles_name ON roles(name);
-- Index cho truy vấn nhanh
CREATE INDEX idx_user_roles_user_id ON user_roles(user_id);
CREATE INDEX idx_user_roles_role_id ON user_roles(role_id);
CREATE INDEX idx_role_permissions_role_id ON role_permissions(role_id);
CREATE INDEX idx_role_permissions_permission_id ON role_permissions(permission_id);
-- Tìm linh kiện theo vị trí
CREATE INDEX idx_component_items_component ON component_items(component_id);
CREATE INDEX idx_component_items_container ON component_items(container_id);
CREATE INDEX idx_component_items_status ON component_items(status);
-- Tìm mã linh kiện
CREATE INDEX idx_component_codes_code ON component_codes(code);
CREATE INDEX idx_component_codes_component ON component_codes(component_id);
-- Thống kê hóa đơn theo thời gian
CREATE INDEX idx_invoices_type_status ON invoices(type, status);
CREATE INDEX idx_invoices_created_at ON invoices(created_at);
CREATE INDEX idx_invoices_type_created ON invoices(type, created_at);
-- Thống kê giao dịch kho
CREATE INDEX idx_stock_transactions_component_date ON stock_transactions(component_id, created_at);
CREATE INDEX idx_stock_transactions_type_date ON stock_transactions(transaction_type, created_at);
CREATE INDEX idx_stock_transactions_invoice ON stock_transactions(invoice_id);
-- Tìm vị trí container (theo cấu trúc phân cấp)
CREATE INDEX idx_containers_shelf ON containers(shelf_id);
CREATE INDEX idx_shelves_cabinet ON shelves(cabinet_id);
CREATE INDEX idx_cabinets_room ON cabinets(room_id);
CREATE INDEX idx_rooms_warehouse ON rooms(warehouse_id);
-- ============================================================
-- Seed: Default permissions (theo module)
-- ============================================================
-- Warehouse module
INSERT INTO permissions (name, description) VALUES
('warehouse:create', 'Tạo kho mới'),
('warehouse:read', 'Xem thông tin kho'),
('warehouse:update', 'Cập nhật kho'),
('warehouse:delete', 'Xóa kho');
-- Room module
INSERT INTO permissions (name, description) VALUES
('room:create', 'Tạo phòng mới'),
('room:read', 'Xem thông tin phòng'),
('room:update', 'Cập nhật phòng'),
('room:delete', 'Xóa phòng');
-- Cabinet module
INSERT INTO permissions (name, description) VALUES
('cabinet:create', 'Tạo tủ mới'),
('cabinet:read', 'Xem thông tin tủ'),
('cabinet:update', 'Cập nhật tủ'),
('cabinet:delete', 'Xóa tủ');
-- Shelf module
INSERT INTO permissions (name, description) VALUES
('shelf:create', 'Tạo kệ mới'),
('shelf:read', 'Xem thông tin kệ'),
('shelf:update', 'Cập nhật kệ'),
('shelf:delete', 'Xóa kệ');
-- Container module
INSERT INTO permissions (name, description) VALUES
('container:create', 'Tạo vật chứa mới'),
('container:read', 'Xem thông tin vật chứa'),
('container:update', 'Cập nhật vật chứa'),
('container:delete', 'Xóa vật chứa');
-- Component Type module
INSERT INTO permissions (name, description) VALUES
('component_type:create', 'Tạo loại linh kiện mới'),
('component_type:read', 'Xem loại linh kiện'),
('component_type:update', 'Cập nhật loại linh kiện'),
('component_type:delete', 'Xóa loại linh kiện');
-- Component module
INSERT INTO permissions (name, description) VALUES
('component:create', 'Tạo linh kiện mới'),
('component:read', 'Xem thông tin linh kiện'),
('component:update', 'Cập nhật linh kiện'),
('component:delete', 'Xóa linh kiện');
-- Invoice module
INSERT INTO permissions (name, description) VALUES
('invoice:create', 'Tạo hóa đơn mới'),
('invoice:read', 'Xem thông tin hóa đơn'),
('invoice:update', 'Cập nhật hóa đơn'),
('invoice:delete', 'Xóa hóa đơn'),
('invoice:approve', 'Duyệt hóa đơn');
-- Stock module
INSERT INTO permissions (name, description) VALUES
('stock:import', 'Nhập kho'),
('stock:export', 'Xuất kho'),
('stock:adjust', 'Điều chỉnh tồn kho'),
('stock:transfer', 'Chuyển kho'),
('stock:read', 'Xem báo cáo tồn kho');
-- User & RBAC module
INSERT INTO permissions (name, description) VALUES
('user:create', 'Tạo người dùng mới'),
('user:read', 'Xem thông tin người dùng'),
('user:update', 'Cập nhật người dùng'),
('user:delete', 'Xóa người dùng'),
('role:manage', 'Quản lý vai trò và quyền hạn');
-- Seed: SYS_ADMIN role
INSERT INTO roles (name, description, created_by) VALUES
('SYS_ADMIN', 'Quản trị viên hệ thống - toàn quyền', 'system');
-- Gán TẤT CẢ permissions cho SYS_ADMIN
INSERT INTO role_permissions (role_id, permission_id)
SELECT r.id, p.id
FROM roles r
CROSS JOIN permissions p
WHERE r.name = 'SYS_ADMIN';