Skip to content

Data Dictionary · Whale ​

⚙️ Trang này sinh tự động từ source code bằng scripts/gen-reference.mjs — đừng sửa tay, sửa code rồi chạy npm run gen:reference.

Thuộc Data Dictionary. 7 bảng, opportunities tới whale_universities.

opportunities ​

Migration 0009 — Whale: hub cơ hội học tập (toàn cầu + VN) để truyền cảm hứng. REQ-SCH-09, SDD-011. Public read (learner + parent). Content-as-data.

migration: 0009_whale_opportunities.sql

CộtKiểuRàng buộc / ghi chú
idTEXTPRIMARY KEY
titleTEXTNOT NULL
regionTEXTNOT NULL CHECK (region IN ('vietnam','asia','europe','america','oceania','global'))
categoryTEXTNOT NULL CHECK (category IN ('scholarship','program','competition','university','summer','pathway','career'))
summaryTEXTNOT NULL
detailTEXT—
tags_jsonTEXT—
audienceTEXTNOT NULL DEFAULT 'both' CHECK (audience IN ('learner','parent','both'))
featuredINTEGERNOT NULL DEFAULT 0
created_atTEXTNOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now'))

Index: idx_opportunities_region(region, category)

success_stories ​

migration: 0010_target_kinds_whale_stories.sql

CộtKiểuRàng buộc / ghi chú
idTEXTPRIMARY KEY
titleTEXTNOT NULL
personaTEXTNOT NULL, -- xuất phát: "Bạn M. — lớp 9, Hà Nội, mạnh Toán" (ẩn danh/tổng hợp)
journeyTEXTNOT NULL, -- hành trình: IELTS/SAT/hoạt động
outcomeTEXTNOT NULL, -- kết quả: trường + học bổng
scholarshipTEXT, -- tên/mức học bổng (nếu có)
regionTEXTNOT NULL DEFAULT 'global'
tags_jsonTEXT—
school_codes_jsonTEXT, -- schools liên quan (squid/ray/shark…) để recommend theo enrollment
featuredINTEGERNOT NULL DEFAULT 0
created_atTEXTNOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now'))

Index: idx_success_stories_region(region, featured)

whale_countries ​

migration: 0013_whale_preferences.sql

CộtKiểuRàng buộc / ghi chú
codeTEXTPRIMARY KEY, name_vi TEXT NOT NULL, name_en TEXT NOT NULL, flag TEXT NOT NULL
regionTEXTNOT NULL, why_vi TEXT NOT NULL, education_vi TEXT NOT NULL
scholarship_viTEXTNOT NULL, cost_vi TEXT NOT NULL

whale_preferences ​

Migration 0013 — Whale destination preferences (learner/parent riêng) + country info. SRC-043, REQ-SCH-14.

migration: 0013_whale_preferences.sql

CộtKiểuRàng buộc / ghi chú
user_idTEXTNOT NULL REFERENCES users(id)
learner_idTEXTNOT NULL REFERENCES learners(id)
roleTEXTNOT NULL CHECK (role IN ('learner','parent'))
countries_jsonTEXTNOT NULL DEFAULT '[]'
majors_jsonTEXTNOT NULL DEFAULT '[]'
updated_atTEXTNOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now'))
—table constraintPRIMARY KEY (user_id, learner_id)

Khóa ngoại: user_id → users · learner_id → learners

whale_rankings ​

Migration 0024 — Bảng xếp hạng đại học theo quốc gia (SRC-084). Nguồn công khai (QS / THE / ARWU…), lưu kèm source + year để người đọc biết số này của ai, năm nào.

migration: 0024_whale_rankings.sql

CộtKiểuRàng buộc / ghi chú
idTEXTPRIMARY KEY
country_codeTEXTNOT NULL
sourceTEXTNOT NULL, -- "QS World University Rankings"
editionTEXTNOT NULL, -- "2026"
rank_localINTEGERNOT NULL, -- thứ hạng trong nước
rank_globalTEXT, -- thứ hạng thế giới (chuỗi vì có dạng "=54", "301-350")
university_nameTEXTNOT NULL
university_idTEXT, -- link tới whale_universities nếu trùng
note_viTEXT—
source_urlTEXT—

Index: idx_whale_rankings_country(country_code, rank_local)

whale_scholarships ​

migration: 0031_whale_country_detail.sql

CộtKiểuRàng buộc / ghi chú
idTEXTPRIMARY KEY
country_codeTEXTNOT NULL
nameTEXTNOT NULL
provider_viTEXT, -- ai cấp
level_viTEXT, -- bậc học áp dụng (đại học / sau đại học)
coverage_viTEXTNOT NULL, -- cấp những gì
who_viTEXT, -- dành cho ai
note_viTEXT, -- mốc thời gian, lưu ý
websiteTEXT—
sort_orderINTEGERNOT NULL DEFAULT 0
value_viTEXT, -- con số cụ thể: tiền, % học phí, số suất
requirements_viTEXT, -- điều kiện và giấy tờ cần có
how_viTEXT, -- nộp ở đâu, theo mấy bước
deadline_viTEXT, -- mốc thời gian lặp lại hằng năm
sources_jsonTEXT-- [{"label":"...","url":"..."}] — trang gốc để tự kiểm chứng

Index: idx_whale_scholarships_country(country_code, sort_order)

whale_universities ​

Migration 0031 — Nội dung chi tiết theo quốc gia cho Whale (SRC-076, REQ-SCH-14). ⚠️ ĐỔI TÊN, KHÔNG PHẢI MIGRATION MỚI (AS-04.1.1). File này trước đây tên 0022_whale_country_detail.sql và ĐÃ ÁP trên D1 production dưới tên cũ (bảng d1_migrations có dòng '0022_whale_country_detail.sql'). Nó bị đổi số vì trùng số với 0022_user_avatar.sql — một sequence chỉ được có một số 0022. Vì tên đổi, wrangler coi đây là migration CHƯA áp và sẽ chạy lại. Toàn bộ lệnh dưới đây đã là idempotent (CREATE TABLE/INDEX IF NOT EXISTS) nên chạy lại KHÔNG lỗi và KHÔNG mất dữ liệu. Dù vậy, cách sạch nhất là đăng ký tên mới một lần trên production — xem migrations/README.md §3. Trang chi tiết một quốc gia cần: học bổng của nước đó, vài trường đại học tiêu biểu, và câu chuyện người đi trước (stories dùng lại bảng success_stories, lọc theo tag). HỆ QUẢ CỦA VIỆC ĐỔI SỐ — đọc kỹ: file này giờ chạy SAU 0026, mà 0026 lại ALTER bảng whale_scholarships do chính file này tạo. Trên môi trường mới (local/DR) 0026 sẽ không có bảng để ALTER. Cách gỡ: 5 cột của 0026 (value_vi, requirements_vi, how_vi, deadline_vi, sources_json) được gộp thẳng vào CREATE TABLE dưới đây — một định nghĩa duy nhất — và 0026 trở thành no-op có ghi chú. Kết quả schema cuối cùng giống hệt production (đã đối chiếu sqlite_master ngày 2026-08-15).

migration: 0031_whale_country_detail.sql

CộtKiểuRàng buộc / ghi chú
idTEXTPRIMARY KEY
country_codeTEXTNOT NULL
nameTEXTNOT NULL
name_viTEXT—
cityTEXT—
why_viTEXTNOT NULL, -- vì sao đáng chú ý, 1-2 câu
strength_viTEXT, -- ngành mạnh
note_viTEXT, -- lưu ý khi apply (học phí, yêu cầu tiếng)
websiteTEXT—
sort_orderINTEGERNOT NULL DEFAULT 0

Index: idx_whale_universities_country(country_code, sort_order)