Bỏ qua

Thuộc Thiết Kế CSDL — Nhóm Anchored Data

Chi Tiết Entity — Anchored Data

Bảng: domain, sub_domain, data_element, extension_proposal, data_lineage


domain

CREATE TABLE domain (
    id              BIGSERIAL PRIMARY KEY,
    public_id       UUID NOT NULL DEFAULT uuidv7(), -- ID public cho API/external integration
    code            TEXT UNIQUE NOT NULL,        -- DM{N} (VD: DM1, DM2). Bất biến sau khi tạo
    name            TEXT NOT NULL,               -- Tên lĩnh vực (VD: Con người, Tổ chức)
    description     TEXT,                        -- Mô tả chi tiết
    created_at      TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at      TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE UNIQUE INDEX idx_dm_public_id ON domain (public_id);

Business Rules: - code tự sinh theo format DM{N} — không cho sửa sau khi tạo - Không xóa Domain nếu còn Sub Domain con - Chỉ Manager được tạo Domain


sub_domain

CREATE TABLE sub_domain (
    id              BIGSERIAL PRIMARY KEY,
    public_id       UUID NOT NULL DEFAULT uuidv7(), -- ID public cho API/external integration
    code            TEXT UNIQUE NOT NULL,        -- DM{N}.{M} (VD: DM1.1). Bất biến
    domain_id       BIGINT NOT NULL REFERENCES domain(id),
    name            TEXT NOT NULL,               -- Tên phân nhóm
    description     TEXT,
    created_at      TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at      TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE UNIQUE INDEX idx_sd_public_id ON sub_domain (public_id);
CREATE INDEX idx_sd_domain ON sub_domain (domain_id);

Business Rules: - code tự sinh format DM{N}.{M} — prefix phải khớp Domain cha - Không xóa Sub Domain nếu còn Data Element con - Data Owner đề xuất qua extension_proposal


data_element

Lưu trữ các từ ngữ chuyên ngành và dữ liệu cốt lõi đã được chuẩn hóa. Bảng này đã được thiết kế gộp với khái niệm Dictonary Term (Từ điển) phục vụ AI Suggestion Worker, và sử dụng cơ chế SCD Type 2 để lưu vết version.

CREATE TABLE data_element (
    id                  BIGSERIAL PRIMARY KEY,
    public_id           UUID NOT NULL DEFAULT uuidv7(),          -- ID public cho API/external integration
    code                TEXT NOT NULL,                             -- Mã định danh tự sinh (DE{NNN}-DM{N}.{M})
    name                TEXT NOT NULL,                             -- Tên nghiệp vụ chuẩn (Term)
    sub_domain_id       BIGINT NOT NULL REFERENCES sub_domain(id),
    status              TEXT NOT NULL DEFAULT 'DRAFT'
                            CHECK (status IN ('DRAFT', 'IN_REVIEW', 'APPROVED', 'PUBLISHED', 'ARCHIVED')),
    data_type           TEXT NOT NULL,                             -- Kiểu dữ liệu gốc (VARCHAR, DATE...)

    -- Danh mục & Pháp lý
    reference_catalog_id BIGINT REFERENCES reference_catalog(id),  -- Tham chiếu nếu field là danh mục định sẵn
    legal_document_id    BIGINT REFERENCES legal_document(id),     -- Cơ sở pháp lý chuẩn hóa (ưu tiên dùng nếu có trong catalog)
    national_mapped_id   TEXT,                                     -- ID trên Nền tảng chia sẻ dữ liệu quốc gia NDXP
    is_personal_data     BOOLEAN DEFAULT FALSE,                    -- Đánh dấu Dữ liệu cá nhân (theo NĐ13/2023)

    -- SCD Type 2
    version_number      INTEGER DEFAULT 1,
    effective_from      TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    effective_to        TIMESTAMPTZ,                               -- NULL = Phiên bản đang active
    is_current          BOOLEAN DEFAULT TRUE,                      -- Cờ tối ưu query lấy phiên bản hiện hành

    -- Quản trị dữ liệu (Bảng D & Metadata)
    sensitivity_level   TEXT NOT NULL DEFAULT 'INTERNAL'
                            CHECK (sensitivity_level IN ('PUBLIC', 'INTERNAL', 'CONFIDENTIAL', 'SECRET')),
    owner_unit_id       BIGINT REFERENCES organization_unit(id),  -- Chủ quản cấp Phòng/Ban (1:1)
    is_future           BOOLEAN NOT NULL DEFAULT FALSE,           -- Dữ liệu tương lai
    future_objective    TEXT,                                      -- Mục tiêu phát triển (bắt buộc khi is_future=true)
    legal_basis         TEXT,                                      -- Cơ sở pháp lý dạng tự do (fallback khi chưa có trong catalog)
    attributes          JSONB DEFAULT '{}',                        -- 14 thuộc tính nghiệp vụ mở rộng
    tech_attributes     JSONB DEFAULT '{}',                        -- 11 thuộc tính kỹ thuật mở rộng
    created_at          TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at          TIMESTAMPTZ NOT NULL DEFAULT NOW(),

    CONSTRAINT chk_de_tu_dong_nghia_size CHECK (
        jsonb_array_length(attributes->'tu_dong_nghia') <= 10
        AND length(attributes->>'tu_dong_nghia') < 1000
    ),
    CONSTRAINT chk_de_legal_reference_rule CHECK (
        status != 'APPROVED'
        OR (
            (legal_document_id IS NOT NULL AND legal_basis IS NULL)
            OR (legal_document_id IS NULL AND legal_basis IS NOT NULL)
        )
    ),
    CONSTRAINT chk_de_owner_required_by_status CHECK (
        status NOT IN ('APPROVED', 'PUBLISHED')
        OR owner_unit_id IS NOT NULL
    ),
    CONSTRAINT chk_de_future_objective_required CHECK (
        is_future = FALSE
        OR (future_objective IS NOT NULL AND length(btrim(future_objective)) > 0)
    )
);

-- Core Index
CREATE UNIQUE INDEX idx_de_public_id ON data_element (public_id);
CREATE INDEX idx_de_subdomain ON data_element (sub_domain_id);
CREATE INDEX idx_de_status ON data_element (status);
CREATE INDEX idx_de_owner ON data_element (owner_unit_id);

-- SCD Type 2 Indexes
CREATE UNIQUE INDEX idx_de_current ON data_element (code) WHERE is_current = TRUE;
CREATE INDEX idx_de_effective ON data_element (effective_from, effective_to);

-- =========================================================================
-- AI Worker Support Indexes (PG_TRGM & GIN)
-- Bắt buộc tạo bằng migration scripts của module AI: 02_Init_AI_Matching_Engine.sql
-- =========================================================================

-- Text fuzzy search (Trigram) cho Tên nghiệp vụ
CREATE INDEX idx_de_name_trgm ON data_element USING GIN (name gin_trgm_ops);

-- Trigram Index cho Tên trường kỹ thuật phục vụ hàm levenshtein() & word_similarity()
CREATE INDEX idx_de_tech_ten_truong_trgm ON data_element USING GIN ((tech_attributes->>'ten_truong_ky_thuat') gin_trgm_ops);

-- GIN B-Tree/Jsonb Index cho `tu_dong_nghia` để Operator @> (Exact match) đạt O(log N)
CREATE INDEX idx_de_tu_dong_nghia_path ON data_element USING GIN ((attributes->'tu_dong_nghia') jsonb_path_ops);

Cấu trúc attributes JSONB (14 thuộc tính nghiệp vụ):

{
  "ten_nghiep_vu": "Số CCCD",
  "dinh_nghia": "Số căn cước công dân 12 số do Bộ Công an cấp",
  "don_vi_tao_lap": "Bộ Công an",
  "can_cu_phap_ly": "Luật Căn cước công dân 2014 (giá trị hiển thị, đồng bộ từ legal_document_id hoặc legal_basis)",
  "nhom_du_lieu": "Định danh cá nhân",
  "tu_dong_nghia": ["so_cccd", "cccd_number", "citizen_id", "cmnd"],
  "vi_du": "001234567890",
  "ghi_chu": "",
  "pham_vi_ap_dung": "Toàn TP",
  "tan_suat_cap_nhat": "Khi có thay đổi",
  "nguon_du_lieu": "CSDL Quốc gia về dân cư",
  "lien_ket_tham_chieu": ""
}

Cấu trúc tech_attributes JSONB (11 thuộc tính kỹ thuật):

{
  "ten_truong_ky_thuat": "cccd_so",
  "kieu_du_lieu_ky_thuat": "VARCHAR(12)",
  "do_dai_toi_da": 12,
  "bat_buoc": true,
  "gia_tri_mac_dinh": null,
  "validation_rules": { "regex": "^[0-9]{12}$" },
  "dinh_dang": "############",
  "don_vi_do": null,
  "he_thong_nguon": "CSDL Công an",
  "bang_nguon": "cong_dan",
  "lineage_info": {}
}

Business Rules: - code tự sinh, bất biến - Mỗi code có thể có nhiều bản ghi lịch sử, nhưng chỉ 1 bản ghi is_current = true - Cơ sở pháp lý khi status = APPROVED: dùng legal_document_id nếu có trong catalog; nếu chưa có thì dùng legal_basis; không điền đồng thời cả hai - attributes.can_cu_phap_ly chỉ phục vụ hiển thị/export, không phải source-of-truth pháp lý - Quy tắc 1:1: mỗi DE chỉ có tối đa 1 owner_unit_id - owner_unit_id phải tham chiếu đơn vị cấp PHONG trở xuống - owner_unit_id bắt buộc khi status = APPROVED hoặc PUBLISHED - is_future = truefuture_objective bắt buộc, owner_unit_id có thể NULL - Không xóa DE khi status = PUBLISHED


extension_proposal

CREATE TABLE extension_proposal (
    id                  BIGSERIAL PRIMARY KEY,
    public_id           UUID NOT NULL DEFAULT uuidv7(), -- ID public cho API/external integration
    proposal_type       TEXT NOT NULL
                            CHECK (proposal_type IN ('SUB_DOMAIN', 'DATA_ELEMENT')),
    domain_id           BIGINT NOT NULL REFERENCES domain(id),
    sub_domain_id       BIGINT REFERENCES sub_domain(id),     -- Chỉ khi type = DATA_ELEMENT
    proposed_name       TEXT NOT NULL,
    proposed_description TEXT,
    proposed_data_type  TEXT,                                   -- Chỉ khi type = DATA_ELEMENT
    justification       TEXT NOT NULL,                          -- Lý do đề xuất
    status              TEXT NOT NULL DEFAULT 'PENDING'
                            CHECK (status IN ('PENDING', 'APPROVED', 'REJECTED')),
    proposed_by         BIGINT NOT NULL REFERENCES app_user(id),
    reviewed_by         BIGINT REFERENCES app_user(id),
    review_note         TEXT,                                   -- Lý do chấp nhận/từ chối
    created_entity_id   BIGINT,                                 -- ID entity đã tạo (nếu APPROVED)
    created_at          TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at          TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE UNIQUE INDEX idx_ep_public_id ON extension_proposal (public_id);
CREATE INDEX idx_ep_status ON extension_proposal (status);
CREATE INDEX idx_ep_proposed_by ON extension_proposal (proposed_by);
CREATE INDEX idx_ep_domain ON extension_proposal (domain_id);

Business Rules: - Data Owner chỉ đề xuất trong Domain đã tồn tại — không tạo Domain mới - Khi APPROVED → hệ thống tự sinh mã và tạo Sub Domain/DE mới → lưu created_entity_id - review_note bắt buộc khi REJECTED


data_lineage

Bảng mô tả tác động dây chuyền khi một Data Element thay đổi phiên bản hoặc bị thay thế. Hỗ trợ đồ thị Impact Analysis.

CREATE TABLE data_lineage (
    id                  BIGSERIAL PRIMARY KEY,
    public_id           UUID NOT NULL DEFAULT uuidv7(), -- ID public cho API/external integration
    source_element_id   BIGINT NOT NULL REFERENCES data_element(id), -- DE bị tác động / phiên bản cũ
    target_element_id   BIGINT NOT NULL REFERENCES data_element(id), -- DE thay thế / phiên bản mới
    transformation_rule TEXT,                                        -- Quy tắc chuyển đổi (VD: Cắt 9 số thành 12 số)
    created_by          BIGINT NOT NULL REFERENCES app_user(id),
    created_at          TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE UNIQUE INDEX idx_dl_public_id ON data_lineage (public_id);
-- Index phục vụ Graph Query hai chiều
CREATE INDEX idx_dl_source ON data_lineage (source_element_id);
CREATE INDEX idx_dl_target ON data_lineage (target_element_id);

Business Rules: - Khi Data Element nâng phiên bản (SCD Type 2), hệ thống GHI NHẬN 1 bản ghi Lineage từ old_version_id sang new_version_id. - Tách biệt với SCD Type 2 để hệ thống bên ngoài / API không bị phá vỡ contract gốc, giúp việc phân tích Impact linh hoạt.


Cập nhật lần cuối: 2026-04-11