Database Schema – EZD AI Booth
| Mã tài liệu |
EZD-TEC-DB |
Phiên bản |
1.0 |
| Ngày hiệu lực |
20/09/2025 |
Người soạn |
John |
| Người phê duyệt |
Stephen |
Trang |
1/X |
Tài liệu đặc tả lược đồ dữ liệu logic cho hệ thống EZD AI Booth, phục vụ các dịch vụ: AI Core Service, Backend Service (CMS/Dashboard), API Gateway; bao gồm Knowledge Base (KB), Logging DB, Auth & RBAC, và các bảng Metadata/Operations hỗ trợ vận hành (multi-tenant, cache, heartbeat).
1. Tổng quan & Phạm vi
- Mục tiêu: Chuẩn hoá mô hình dữ liệu để các team (BE/FE/AI/DevOps/Vendor) cùng triển khai nhất quán.
- Phạm vi: Schema logic PostgreSQL ≥ 14 (gợi ý), dùng UUID làm khoá chính, JSONB cho trường linh hoạt, TIMESTAMPTZ cho thời gian.
- Nguyên tắc: Multi-tenant isolation (mọi bảng dữ liệu nghiệp vụ & log đều gắn
tenant_id), Traceability (mọi request có request_id/trace_id), Auditable (log ghi đầy đủ).
2. Quy ước & Tiêu chuẩn
- Đặt tên:
snake_case, bảng số nhiều (vd: users, faqs); khoá chính id (UUID); FK theo {ref}_id.
- Thời gian:
created_at, updated_at (TIMESTAMPTZ, default now()).
- Xoá dữ liệu: LogDB không xoá (retention policy), các bảng KB xoá mềm qua trường
is_deleted (BOOLEAN, default FALSE) nếu cần.
- Index:
- Bắt buộc:
(tenant_id), (tenant_id, updated_at), GIN cho trường JSONB tra cứu nhãn/tags.
- Full-text search (
tsvector) cho faqs(question_text, answer_text), promotions(title, description).
- Khoá ngoại:
ON DELETE RESTRICT (KB/Auth); ON DELETE CASCADE (bảng nối many-to-many, log theo session).
3. Knowledge Base (KB)
Nguồn dữ liệu hiển thị cho Booth và làm đầu vào Retrieval của AI Core.
3.1 faqs
| Cột |
Kiểu |
Ràng buộc |
Mô tả |
| id |
UUID |
PK |
Khoá chính |
| tenant_id |
UUID |
FK → tenants.id |
Thuộc tenant nào |
| question_text |
TEXT |
NOT NULL |
Câu hỏi chuẩn hoá |
| answer_text |
TEXT |
NOT NULL |
Câu trả lời |
| tags |
JSONB |
|
Nhãn phân loại (topic, floor, brand, ...) |
| is_deleted |
BOOLEAN |
DEFAULT FALSE |
Xoá mềm |
| version |
INTEGER |
DEFAULT 1 |
Số phiên bản (optimistic locking) |
| updated_at |
TIMESTAMPTZ |
NOT NULL |
Thời điểm cập nhật |
| created_at |
TIMESTAMPTZ |
NOT NULL |
Thời điểm tạo |
Chỉ mục: GIN (tags), FTS tsvector(question_text, answer_text), (tenant_id, updated_at desc).
| Cột |
Kiểu |
Ràng buộc |
Mô tả |
| id |
UUID |
PK |
|
| tenant_id |
UUID |
FK → tenants.id |
|
| title |
TEXT |
NOT NULL |
Tiêu đề |
| description |
TEXT |
|
Mô tả |
| image_url |
TEXT |
|
Hình đại diện |
| start_date |
DATE |
NOT NULL |
Ngày bắt đầu |
| end_date |
DATE |
NOT NULL |
Ngày kết thúc |
| tags |
JSONB |
|
Nhãn: thương hiệu, chủ đề |
| status |
TEXT |
DEFAULT 'draft' |
Trạng thái: draft/scheduled/active/expired |
| is_deleted |
BOOLEAN |
DEFAULT FALSE |
|
| version |
INTEGER |
DEFAULT 1 |
Số phiên bản (optimistic locking) |
| updated_at |
TIMESTAMPTZ |
NOT NULL |
|
| created_at |
TIMESTAMPTZ |
NOT NULL |
|
Chỉ mục: (tenant_id, start_date, end_date), FTS tsvector(title, description), GIN(tags).
3.3 branding
| Cột |
Kiểu |
Ràng buộc |
Mô tả |
| id |
UUID |
PK |
|
| tenant_id |
UUID |
FK → tenants.id |
|
| logo_url |
TEXT |
|
|
| primary_color |
TEXT |
|
HEX / token |
| theme |
JSONB |
|
Tuỳ chọn mở rộng (typography, palette) |
| is_deleted |
BOOLEAN |
DEFAULT FALSE |
|
| version |
INTEGER |
DEFAULT 1 |
Số phiên bản (optimistic locking) |
| updated_at |
TIMESTAMPTZ |
NOT NULL |
|
| created_at |
TIMESTAMPTZ |
NOT NULL |
|
3.4 avatars
| Cột |
Kiểu |
Ràng buộc |
Mô tả |
| id |
UUID |
PK |
|
| tenant_id |
UUID |
FK → tenants.id |
|
| model_ref |
TEXT |
NOT NULL |
Đường dẫn/ID asset 3D |
| config |
JSONB |
|
Biểu cảm, cử chỉ được bật |
| is_deleted |
BOOLEAN |
DEFAULT FALSE |
|
| updated_at |
TIMESTAMPTZ |
NOT NULL |
|
| created_at |
TIMESTAMPTZ |
NOT NULL |
|
3.5 map_locations
| Cột |
Kiểu |
Ràng buộc |
Mô tả |
| id |
UUID |
PK |
|
| tenant_id |
UUID |
FK → tenants.id |
|
| store_name |
TEXT |
NOT NULL |
Tên cửa hàng/điểm đến |
| floor |
TEXT |
NOT NULL |
Ví dụ: "T1" |
| coords |
JSONB |
NOT NULL |
Toạ độ hiển thị (x, y, zone, …) |
| metadata |
JSONB |
|
Điện thoại, giờ mở cửa |
| is_deleted |
BOOLEAN |
DEFAULT FALSE |
|
| updated_at |
TIMESTAMPTZ |
NOT NULL |
|
| created_at |
TIMESTAMPTZ |
NOT NULL |
|
4. Logging Database (LogDB)
Phục vụ Dashboard & quan trắc hệ thống. Không xoá dữ liệu; áp dụng retention policy theo môi trường (MVP: 90 ngày).
4.1 interaction_logs
| Cột |
Kiểu |
Ràng buộc |
Mô tả |
| id |
UUID |
PK |
|
| tenant_id |
UUID |
FK → tenants.id |
|
| booth_id |
UUID |
FK → booths.id |
|
| session_id |
UUID |
NOT NULL |
Phiên tương tác |
| request_id |
UUID |
|
Tương ứng header |
| trace_id |
UUID |
|
Truy vết end-to-end |
| user_utterance |
TEXT |
|
Văn bản hoá câu hỏi |
| ai_response |
TEXT |
|
Câu trả lời |
| scope_tag |
TEXT |
|
faq/promo/map/general |
| success |
BOOLEAN |
|
Pipeline thành công |
| feedback |
SMALLINT |
|
1=👍, -1=👎, 0/NULL=không có |
| latency_ms |
INTEGER |
|
Thời gian xử lý |
| created_at |
TIMESTAMPTZ |
NOT NULL |
|
Chỉ mục: (tenant_id, created_at desc), (tenant_id, booth_id, created_at desc), BTREE(session_id), BTREE(trace_id).
4.2 event_logs
| Cột |
Kiểu |
Ràng buộc |
Mô tả |
| id |
UUID |
PK |
|
| tenant_id |
UUID |
FK → tenants.id |
|
| session_id |
UUID |
|
|
| event_type |
TEXT |
NOT NULL |
Ví dụ: fail_out_of_scope, retry_in_scope, heartbeat_offline |
| payload |
JSONB |
|
Tuỳ biến theo event |
| created_at |
TIMESTAMPTZ |
NOT NULL |
|
Chỉ mục: (tenant_id, event_type, created_at desc), BTREE(session_id).
5. Auth & RBAC (Admin Webapp)
Quản lý người dùng, vai trò, quyền hạn. Mặc định 2 vai trò: SUPER_ADMIN, TENANT_ADMIN (có thể mở rộng).
5.1 users
| Cột |
Kiểu |
Ràng buộc |
Mô tả |
| id |
UUID |
PK |
|
| tenant_id |
UUID |
FK → tenants.id, NULLABLE |
NULL cho SUPER_ADMIN toàn hệ |
| email |
TEXT |
UNIQUE NOT NULL |
|
| password_hash |
TEXT |
NOT NULL |
|
| status |
TEXT |
DEFAULT 'active' |
active/inactive |
| last_login_at |
TIMESTAMPTZ |
|
|
| created_at |
TIMESTAMPTZ |
NOT NULL |
|
| updated_at |
TIMESTAMPTZ |
NOT NULL |
|
5.2 roles
| Cột |
Kiểu |
Ràng buộc |
Mô tả |
| id |
UUID |
PK |
|
| tenant_id |
UUID |
FK → tenants.id, NULLABLE |
NULL = scope toàn hệ |
| role_name |
TEXT |
NOT NULL |
|
| created_at |
TIMESTAMPTZ |
NOT NULL |
|
Ràng buộc: (tenant_id, role_name) UNIQUE.
5.3 permissions
| Cột |
Kiểu |
Ràng buộc |
Mô tả |
| id |
UUID |
PK |
|
| permission_name |
TEXT |
UNIQUE NOT NULL |
|
| description |
TEXT |
|
|
5.4 role_permissions (N-N)
| Cột |
Kiểu |
Ràng buộc |
Mô tả |
| role_id |
UUID |
FK → roles.id |
PK part |
| permission_id |
UUID |
FK → permissions.id |
PK part |
PK: (role_id, permission_id).
5.5 user_roles (N-N)
| Cột |
Kiểu |
Ràng buộc |
Mô tả |
| user_id |
UUID |
FK → users.id |
PK part |
| role_id |
UUID |
FK → roles.id |
PK part |
PK: (user_id, role_id).
Bảng nền tảng để quản trị multi-tenant, thiết bị, đồng bộ cache.
6.1 tenants
| Cột |
Kiểu |
Ràng buộc |
Mô tả |
| id |
UUID |
PK |
|
| name |
TEXT |
UNIQUE NOT NULL |
|
| contact_email |
TEXT |
|
|
| created_at |
TIMESTAMPTZ |
NOT NULL |
|
| updated_at |
TIMESTAMPTZ |
NOT NULL |
|
6.2 booths
| Cột |
Kiểu |
Ràng buộc |
Mô tả |
| id |
UUID |
PK |
|
| tenant_id |
UUID |
FK → tenants.id |
|
| location_desc |
TEXT |
|
Ví dụ: Sảnh chính |
| status |
TEXT |
DEFAULT 'online' |
online/offline/maintenance |
| last_heartbeat_at |
TIMESTAMPTZ |
|
Phục vụ cảnh báo |
| created_at |
TIMESTAMPTZ |
NOT NULL |
|
| updated_at |
TIMESTAMPTZ |
NOT NULL |
|
6.3 cache_invalidations
| Cột |
Kiểu |
Ràng buộc |
Mô tả |
| id |
UUID |
PK |
|
| tenant_id |
UUID |
FK → tenants.id |
|
| entity_type |
TEXT |
NOT NULL |
faq/promotion/branding/avatar/map_location |
| entity_id |
UUID |
|
Ghi nhận mục cụ thể (tuỳ chọn) |
| invalidated_at |
TIMESTAMPTZ |
NOT NULL |
|
Chỉ mục: (tenant_id, entity_type, invalidated_at desc).
7. Khoá ngoại & Quan hệ (Tổng hợp)
- tenants 1—N users, booths, faqs, promotions, branding, avatars, map_locations, interaction_logs, event_logs, cache_invalidations.
- users N—N roles qua user_roles.
- roles N—N permissions qua role_permissions.
8. ERD (Mermaid)
erDiagram
TENANTS ||--o{ USERS : "has"
TENANTS ||--o{ BOOTHS : "has"
TENANTS ||--o{ FAQS : "owns"
TENANTS ||--o{ PROMOTIONS : "owns"
TENANTS ||--o{ BRANDING : "owns"
TENANTS ||--o{ AVATARS : "owns"
TENANTS ||--o{ MAP_LOCATIONS : "owns"
TENANTS ||--o{ INTERACTION_LOGS : "owns"
TENANTS ||--o{ EVENT_LOGS : "owns"
TENANTS ||--o{ CACHE_INVALIDATIONS : "owns"
USERS ||--o{ USER_ROLES : "maps"
ROLES ||--o{ USER_ROLES : "maps"
ROLES ||--o{ ROLE_PERMISSIONS : "grants"
PERMISSIONS ||--o{ ROLE_PERMISSIONS : "bound"
BOOTHS ||--o{ INTERACTION_LOGS : "collects"
TENANTS {
uuid id PK
text name
text contact_email
timestamptz created_at
timestamptz updated_at
}
USERS {
uuid id PK
uuid tenant_id FK
text email
text password_hash
text status
timestamptz last_login_at
timestamptz created_at
timestamptz updated_at
}
ROLES {
uuid id PK
uuid tenant_id FK
text role_name
timestamptz created_at
}
PERMISSIONS {
uuid id PK
text permission_name
text description
}
USER_ROLES {
uuid user_id FK
uuid role_id FK
}
ROLE_PERMISSIONS {
uuid role_id FK
uuid permission_id FK
}
BOOTHS {
uuid id PK
uuid tenant_id FK
text location_desc
text status
timestamptz last_heartbeat_at
timestamptz created_at
timestamptz updated_at
}
FAQS {
jsonb tags
boolean is_deleted
int version
timestamptz updated_at
timestamptz created_at
}
PROMOTIONS {
uuid id PK
uuid tenant_id FK
text title
text description
text image_url
date start_date
date end_date
jsonb tags
text status
boolean is_deleted
int version
timestamptz updated_at
timestamptz created_at
}
BRANDING {
uuid id PK
uuid tenant_id FK
text logo_url
text primary_color
jsonb theme
boolean is_deleted
int version
timestamptz updated_at
timestamptz created_at
}
AVATARS {
uuid id PK
uuid tenant_id FK
text model_ref
jsonb config
boolean is_deleted
timestamptz updated_at
timestamptz created_at
}
MAP_LOCATIONS {
uuid id PK
uuid tenant_id FK
text store_name
text floor
jsonb coords
jsonb metadata
boolean is_deleted
timestamptz updated_at
timestamptz created_at
}
INTERACTION_LOGS {
uuid id PK
uuid tenant_id FK
uuid booth_id FK
uuid session_id
uuid request_id
uuid trace_id
text user_utterance
text ai_response
text scope_tag
boolean success
smallint feedback
int latency_ms
timestamptz created_at
}
EVENT_LOGS {
uuid id PK
uuid tenant_id FK
uuid session_id
text event_type
jsonb payload
timestamptz created_at
}
CACHE_INVALIDATIONS {
uuid id PK
uuid tenant_id FK
text entity_type
uuid entity_id
timestamptz invalidated_at
}
9. Gợi ý Triển khai & Tối ưu
- Partitioning:
interaction_logs, event_logs theo created_at (by month) để tối ưu retention/scan.
- Materialized Views: tổng hợp KPI (lượt tương tác/ngày, top câu hỏi) cho Dashboard (refresh mỗi 5–15 phút).
- FTS: tạo
tsvector + GIN index cho FAQ/Promotion để tăng tốc gợi ý trong AI Core.
- Row Level Security (RLS): nếu chạy single DB multi-tenant, kích hoạt RLS theo
tenant_id trên KB & LogDB.
- CDC/Eventing: phát sự kiện từ Backend khi KB thay đổi → invalidate cache tức thời, giảm độ trễ sync.
10. Phụ lục – Enum khuyến nghị
event_logs.event_type: fail_out_of_scope, retry_in_scope, heartbeat_offline, content_updated, auth_login_success, auth_password_reset…
interaction_logs.feedback: 1 (👍), -1 (👎), NULL (không phản hồi).
Trạng thái sẵn sàng: Tài liệu này đủ để BE viết DDL, AI Core định nghĩa retrieval index, Dashboard xây dựng truy vấn KPI, và Ops cấu hình retention/alerting.