Skip to content

THIẾT KẾ CƠ SỞ DỮ LIỆU

1. Tổng Quan Database

1.1 Hệ Quản Trị Cơ Sở Dữ Liệu Đề Xuất

  • Primary: MySQL 8.0+ hoặc PostgreSQL 14+
  • Lý do: Miễn phí, ổn định, phù hợp doanh nghiệp vừa và nhỏ

1.2 Kiến Trúc Database

production_db (Cơ sở dữ liệu chính)
├── Quản lý khách hàng
├── Quản lý đơn hàng
├── Quản lý sản xuất
├── Quản lý kho
├── Quản lý tài chính
└── Hệ thống (Users, Logs, Settings)

2. Sơ Đồ Quan Hệ (ERD)

Sơ Đồ ERD

Sơ đồ dưới đây mô tả mối quan hệ giữa các bảng chính trong hệ thống. Hover vào các entity để xem chi tiết.

mermaid
erDiagram
    CUSTOMERS ||--o{ ORDERS : places
    ORDERS ||--o{ ORDER_ITEMS : contains
    ORDER_ITEMS ||--|| PRODUCTS : references
    ORDERS ||--o{ PRODUCTION_ORDERS : generates
    PRODUCTION_ORDERS ||--o{ PRODUCTION_STEPS : has
    PRODUCTION_STEPS ||--o{ MATERIAL_USAGE : uses
    MATERIALS ||--o{ MATERIAL_USAGE : used_in
    MATERIALS ||--o{ INVENTORY_TRANSACTIONS : tracked_by
    WAREHOUSES ||--o{ INVENTORY_TRANSACTIONS : stores
    ORDERS ||--o{ DELIVERIES : scheduled
    DELIVERIES ||--o{ PAYMENTS : triggers
    CUSTOMERS ||--o{ PAYMENTS : makes

3. Chi Tiết Các Bảng

3.1 Quản Lý Khách Hàng

Bảng: customers

sql
CREATE TABLE customers (
    id INT PRIMARY KEY AUTO_INCREMENT,
    code VARCHAR(20) UNIQUE NOT NULL,           -- Mã KH: KH001
    name VARCHAR(200) NOT NULL,                 -- Tên công ty/cá nhân
    tax_code VARCHAR(20),                       -- Mã số thuế
    phone VARCHAR(20) NOT NULL,
    email VARCHAR(100),
    address TEXT,                               -- Địa chỉ xuất HĐ
    contact_person VARCHAR(100),                -- Người liên hệ
    customer_type ENUM('NEW','REGULAR','VIP') DEFAULT 'NEW',
    credit_limit DECIMAL(15,2) DEFAULT 0,       -- Hạn mức công nợ
    status ENUM('ACTIVE','INACTIVE') DEFAULT 'ACTIVE',
    notes TEXT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    INDEX idx_code (code),
    INDEX idx_phone (phone),
    INDEX idx_customer_type (customer_type)
);

3.2 Quản Lý Đơn Hàng

Bảng: orders

sql
CREATE TABLE orders (
    id INT PRIMARY KEY AUTO_INCREMENT,
    order_code VARCHAR(30) UNIQUE NOT NULL,     -- DH-20260129-001
    customer_id INT NOT NULL,
    order_date DATE NOT NULL,
    required_date DATE,                         -- Ngày cần nhận
    status ENUM(
        'DRAFT',           -- Nháp
        'QUOTED',          -- Đã báo giá
        'CONFIRMED',       -- Đã xác nhận
        'IN_PRODUCTION',   -- Đang sản xuất
        'COMPLETED',       -- Hoàn thành SX
        'DELIVERED',       -- Đã giao hàng
        'ACCEPTED',        -- Đã nghiệm thu
        'CANCELLED'        -- Đã hủy
    ) DEFAULT 'DRAFT',
    subtotal DECIMAL(15,2) DEFAULT 0,           -- Tổng tiền chưa VAT
    vat_rate DECIMAL(5,2) DEFAULT 10.00,        -- % VAT
    vat_amount DECIMAL(15,2) DEFAULT 0,         -- Tiền VAT
    total_amount DECIMAL(15,2) DEFAULT 0,       -- Tổng cộng
    delivery_address TEXT,                      -- Địa chỉ giao hàng
    payment_method ENUM('CASH','TRANSFER','CARD','MIXED'),
    payment_terms TEXT,                         -- Điều khoản thanh toán
    notes TEXT,
    created_by INT,                             -- User ID
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    FOREIGN KEY (customer_id) REFERENCES customers(id),
    INDEX idx_order_code (order_code),
    INDEX idx_customer (customer_id),
    INDEX idx_status (status),
    INDEX idx_order_date (order_date)
);

Bảng: order_items

sql
CREATE TABLE order_items (
    id INT PRIMARY KEY AUTO_INCREMENT,
    order_id INT NOT NULL,
    line_number INT NOT NULL,                   -- Số thứ tự dòng
    product_type ENUM('PRINT','SIGNBOARD'),     -- In ấn / Biển QC
    product_name VARCHAR(200) NOT NULL,
    description TEXT,                           -- Mô tả chi tiết
    quantity INT NOT NULL,
    unit VARCHAR(20),                           -- Tờ, cuốn, cái, m²
    unit_price DECIMAL(15,2) NOT NULL,
    total_price DECIMAL(15,2) NOT NULL,
    design_file_url VARCHAR(500),               -- Link file thiết kế
    specifications JSON,                        -- Thông số kỹ thuật
    notes TEXT,
    FOREIGN KEY (order_id) REFERENCES orders(id) ON DELETE CASCADE,
    INDEX idx_order (order_id)
);

Ví dụ specifications (JSON):

json
{
  "size": "A4",
  "paper_type": "C250",
  "color": "4/4",
  "finishing": ["lamination", "die-cut"],
  "binding": "thermal"
}

3.3 Quản Lý Sản Xuất

Bảng: production_orders

sql
CREATE TABLE production_orders (
    id INT PRIMARY KEY AUTO_INCREMENT,
    po_code VARCHAR(30) UNIQUE NOT NULL,        -- LSX-20260129-001
    order_id INT NOT NULL,
    order_item_id INT NOT NULL,
    start_date DATE,
    planned_end_date DATE,
    actual_end_date DATE,
    status ENUM(
        'PENDING',         -- Chờ sản xuất
        'DESIGN',          -- Đang thiết kế
        'MATERIAL_PREP',   -- Chuẩn bị NVL
        'PRINTING',        -- Đang in
        'FINISHING',       -- Gia công
        'QC',              -- Kiểm tra chất lượng
        'COMPLETED',       -- Hoàn thành
        'FAILED'           -- Lỗi
    ) DEFAULT 'PENDING',
    assigned_to INT,                            -- User ID thợ chính
    priority INT DEFAULT 3,                     -- 1=Cao, 3=Thường, 5=Thấp
    notes TEXT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    FOREIGN KEY (order_id) REFERENCES orders(id),
    FOREIGN KEY (order_item_id) REFERENCES order_items(id),
    INDEX idx_po_code (po_code),
    INDEX idx_status (status),
    INDEX idx_assigned (assigned_to)
);

Bảng: production_steps

sql
CREATE TABLE production_steps (
    id INT PRIMARY KEY AUTO_INCREMENT,
    po_id INT NOT NULL,
    step_name ENUM(
        'DESIGN',          -- Thiết kế
        'PLATE_MAKING',    -- Xuất kẽm
        'MATERIAL_OUT',    -- Xuất NVL
        'PRINTING',        -- In
        'LAMINATION',      -- Cán màng
        'DIE_CUT',         -- Bế
        'BINDING',         -- Đóng gáy
        'QC',              -- Kiểm tra
        'PACKING'          -- Đóng gói
    ) NOT NULL,
    sequence_no INT NOT NULL,                   -- Thứ tự công đoạn
    status ENUM('PENDING','IN_PROGRESS','COMPLETED','FAILED') DEFAULT 'PENDING',
    assigned_to INT,                            -- User ID
    start_time TIMESTAMP NULL,
    end_time TIMESTAMP NULL,
    duration_minutes INT,                       -- Thời gian thực tế (phút)
    quantity_input INT,                         -- Số lượng đầu vào
    quantity_output INT,                        -- Số lượng đầu ra
    quantity_defect INT DEFAULT 0,              -- Số lượng lỗi
    notes TEXT,
    FOREIGN KEY (po_id) REFERENCES production_orders(id) ON DELETE CASCADE,
    INDEX idx_po (po_id),
    INDEX idx_status (status)
);

3.4 Quản Lý Kho

Bảng: warehouses

sql
CREATE TABLE warehouses (
    id INT PRIMARY KEY AUTO_INCREMENT,
    code VARCHAR(20) UNIQUE NOT NULL,           -- K1, K2
    name VARCHAR(100) NOT NULL,                 -- Kho NVL, Kho TP
    type ENUM('MATERIAL','FINISHED_PRODUCT'),
    location VARCHAR(200),
    manager_id INT,                             -- User ID
    status ENUM('ACTIVE','INACTIVE') DEFAULT 'ACTIVE',
    notes TEXT
);

Bảng: materials

sql
CREATE TABLE materials (
    id INT PRIMARY KEY AUTO_INCREMENT,
    code VARCHAR(30) UNIQUE NOT NULL,           -- NVL-GIAY-C250
    name VARCHAR(200) NOT NULL,
    category ENUM(
        'PAPER',           -- Giấy
        'INK',             -- Mực
        'PLATE',           -- Kẽm/CTP
        'FILM',            -- Màng cán
        'GLUE',            -- Keo
        'OTHER'            -- Khác
    ) NOT NULL,
    unit VARCHAR(20),                           -- Tờ, kg, lít, cái
    unit_price DECIMAL(15,2),
    min_stock INT DEFAULT 0,                    -- Tồn kho tối thiểu
    max_stock INT,
    reorder_point INT,                          -- Điểm đặt hàng lại
    supplier VARCHAR(200),
    specifications JSON,
    status ENUM('ACTIVE','INACTIVE') DEFAULT 'ACTIVE',
    notes TEXT,
    INDEX idx_code (code),
    INDEX idx_category (category)
);

Bảng: inventory_transactions

sql
CREATE TABLE inventory_transactions (
    id INT PRIMARY KEY AUTO_INCREMENT,
    transaction_code VARCHAR(30) UNIQUE NOT NULL, -- NK-001, XK-001
    transaction_type ENUM('IN','OUT','TRANSFER','ADJUST'),
    warehouse_id INT NOT NULL,
    material_id INT NOT NULL,
    quantity DECIMAL(10,2) NOT NULL,
    unit_price DECIMAL(15,2),
    total_amount DECIMAL(15,2),
    reference_type VARCHAR(50),                 -- 'PO', 'PURCHASE', 'SALE'
    reference_id INT,                           -- ID của đơn liên quan
    transaction_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    created_by INT,
    notes TEXT,
    FOREIGN KEY (warehouse_id) REFERENCES warehouses(id),
    FOREIGN KEY (material_id) REFERENCES materials(id),
    INDEX idx_warehouse (warehouse_id),
    INDEX idx_material (material_id),
    INDEX idx_date (transaction_date)
);

Bảng: inventory_balances (View hoặc bảng tổng hợp)

sql
CREATE TABLE inventory_balances (
    warehouse_id INT NOT NULL,
    material_id INT NOT NULL,
    quantity DECIMAL(10,2) DEFAULT 0,
    last_updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    PRIMARY KEY (warehouse_id, material_id),
    FOREIGN KEY (warehouse_id) REFERENCES warehouses(id),
    FOREIGN KEY (material_id) REFERENCES materials(id)
);

3.5 Quản Lý Giao Hàng

Bảng: deliveries

sql
CREATE TABLE deliveries (
    id INT PRIMARY KEY AUTO_INCREMENT,
    delivery_code VARCHAR(30) UNIQUE NOT NULL,  -- GH-20260129-001
    order_id INT NOT NULL,
    delivery_date DATE NOT NULL,
    delivery_address TEXT,
    delivery_method ENUM('SELF_PICKUP','COMPANY_DELIVERY','COURIER'),
    vehicle_number VARCHAR(20),                 -- Biển số xe
    driver_name VARCHAR(100),
    driver_phone VARCHAR(20),
    status ENUM('SCHEDULED','IN_TRANSIT','DELIVERED','FAILED') DEFAULT 'SCHEDULED',
    delivered_at TIMESTAMP NULL,
    receiver_name VARCHAR(100),
    receiver_signature_url VARCHAR(500),        -- Link chữ ký
    notes TEXT,
    FOREIGN KEY (order_id) REFERENCES orders(id),
    INDEX idx_delivery_code (delivery_code),
    INDEX idx_order (order_id),
    INDEX idx_status (status)
);

3.6 Quản Lý Thanh Toán

Bảng: payments

sql
CREATE TABLE payments (
    id INT PRIMARY KEY AUTO_INCREMENT,
    payment_code VARCHAR(30) UNIQUE NOT NULL,   -- TT-20260129-001
    order_id INT NOT NULL,
    customer_id INT NOT NULL,
    payment_date DATE NOT NULL,
    amount DECIMAL(15,2) NOT NULL,
    payment_method ENUM('CASH','TRANSFER','CARD','E_WALLET'),
    payment_type ENUM('DEPOSIT','PARTIAL','FULL'),
    transaction_ref VARCHAR(100),               -- Mã giao dịch ngân hàng
    notes TEXT,
    created_by INT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (order_id) REFERENCES orders(id),
    FOREIGN KEY (customer_id) REFERENCES customers(id),
    INDEX idx_payment_code (payment_code),
    INDEX idx_order (order_id),
    INDEX idx_customer (customer_id)
);

3.7 Quản Lý Người Dùng

Bảng: users

sql
CREATE TABLE users (
    id INT PRIMARY KEY AUTO_INCREMENT,
    username VARCHAR(50) UNIQUE NOT NULL,
    password_hash VARCHAR(255) NOT NULL,
    full_name VARCHAR(100) NOT NULL,
    email VARCHAR(100),
    phone VARCHAR(20),
    role ENUM(
        'ADMIN',           -- Quản trị viên
        'MANAGER',         -- Quản lý
        'SALES',           -- Kinh doanh
        'PRODUCTION',      -- Sản xuất
        'WAREHOUSE',       -- Kho
        'ACCOUNTANT'       -- Kế toán
    ) NOT NULL,
    department VARCHAR(50),
    status ENUM('ACTIVE','INACTIVE') DEFAULT 'ACTIVE',
    last_login TIMESTAMP NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    INDEX idx_username (username),
    INDEX idx_role (role)
);

Bảng: activity_logs

sql
CREATE TABLE activity_logs (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    user_id INT,
    action VARCHAR(100),                        -- CREATE_ORDER, UPDATE_STATUS
    table_name VARCHAR(50),
    record_id INT,
    old_value JSON,
    new_value JSON,
    ip_address VARCHAR(45),
    user_agent TEXT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    INDEX idx_user (user_id),
    INDEX idx_action (action),
    INDEX idx_created (created_at)
);

4. Indexes và Optimization

4.1 Indexes Quan Trọng

sql
-- Tìm kiếm đơn hàng nhanh
CREATE INDEX idx_orders_composite ON orders(customer_id, order_date, status);

-- Tìm công nợ
CREATE INDEX idx_payments_composite ON payments(customer_id, payment_date);

-- Theo dõi tồn kho
CREATE INDEX idx_inventory_composite ON inventory_transactions(material_id, warehouse_id, transaction_date);

4.2 Partitioning (Cho dữ liệu lớn)

sql
-- Phân vùng bảng orders theo năm
ALTER TABLE orders 
PARTITION BY RANGE (YEAR(order_date)) (
    PARTITION p2024 VALUES LESS THAN (2025),
    PARTITION p2025 VALUES LESS THAN (2026),
    PARTITION p2026 VALUES LESS THAN (2027),
    PARTITION p_future VALUES LESS THAN MAXVALUE
);

5. Views Hữu Ích

5.1 View Công Nợ Khách Hàng

sql
CREATE VIEW customer_debts AS
SELECT 
    c.id AS customer_id,
    c.code AS customer_code,
    c.name AS customer_name,
    COALESCE(SUM(o.total_amount), 0) AS total_ordered,
    COALESCE(SUM(p.amount), 0) AS total_paid,
    COALESCE(SUM(o.total_amount), 0) - COALESCE(SUM(p.amount), 0) AS debt_amount
FROM customers c
LEFT JOIN orders o ON c.id = o.customer_id AND o.status NOT IN ('DRAFT', 'CANCELLED')
LEFT JOIN payments p ON c.id = p.customer_id
GROUP BY c.id, c.code, c.name;

5.2 View Tồn Kho Theo NVL

sql
CREATE VIEW current_inventory AS
SELECT 
    w.code AS warehouse_code,
    w.name AS warehouse_name,
    m.code AS material_code,
    m.name AS material_name,
    m.unit,
    ib.quantity AS current_stock,
    m.min_stock,
    CASE 
        WHEN ib.quantity < m.min_stock THEN 'LOW'
        WHEN ib.quantity > m.max_stock THEN 'EXCESS'
        ELSE 'NORMAL'
    END AS stock_status
FROM inventory_balances ib
JOIN warehouses w ON ib.warehouse_id = w.id
JOIN materials m ON ib.material_id = m.id;

Tài liệu hệ thống quản lý sản xuất giấy