feat: Add comprehensive API usage examples for v3, ERD, data dictionary, and course cloning documentation.
This commit is contained in:
parent
6c4d10963e
commit
a1f7ee057d
9 changed files with 1661 additions and 10 deletions
BIN
docs/api-docs/ER/.DS_Store
vendored
Normal file
BIN
docs/api-docs/ER/.DS_Store
vendored
Normal file
Binary file not shown.
507
docs/api-docs/ER/ERD_v3_improved.txt
Normal file
507
docs/api-docs/ER/ERD_v3_improved.txt
Normal file
|
|
@ -0,0 +1,507 @@
|
|||
// E-Learning Platform - Enhanced ERD v3.0
|
||||
// Major improvements:
|
||||
// 1. Separated roles table with display values
|
||||
// 2. Separated user_profiles table
|
||||
// 3. Added created_by/updated_by audit trails
|
||||
// 4. Made updated_at/updated_by nullable
|
||||
// 5. Used ENUM for status fields
|
||||
// 6. Optimized audit trail placement
|
||||
// 7. Added announcement status and multi-instructor support
|
||||
|
||||
// ============================================
|
||||
// CORE TABLES
|
||||
// ============================================
|
||||
|
||||
Table roles {
|
||||
id int [pk, increment]
|
||||
code varchar [unique, not null, note: 'ADMIN | INSTRUCTOR | STUDENT']
|
||||
name jsonb [not null, note: '{"th": "ผู้ดูแลระบบ", "en": "Administrator"}']
|
||||
description jsonb [note: 'role description']
|
||||
created_at datetime [not null, default: `now()`]
|
||||
|
||||
indexes {
|
||||
code [unique]
|
||||
}
|
||||
}
|
||||
|
||||
Table users {
|
||||
id int [pk, increment]
|
||||
username varchar [unique, not null]
|
||||
email varchar [unique, not null]
|
||||
password varchar [not null]
|
||||
role_id int [not null, ref: > roles.id]
|
||||
email_verified_at datetime
|
||||
created_at datetime [not null, default: `now()`]
|
||||
updated_at datetime
|
||||
|
||||
indexes {
|
||||
username [unique]
|
||||
email [unique]
|
||||
role_id
|
||||
}
|
||||
}
|
||||
|
||||
Table user_profiles {
|
||||
id int [pk, increment]
|
||||
user_id int [unique, not null, ref: > users.id]
|
||||
prefix varchar [note: 'Mr. | Mrs. | Ms. | Dr. etc.']
|
||||
first_name varchar [not null]
|
||||
last_name varchar [not null]
|
||||
phone varchar
|
||||
avatar_url varchar
|
||||
created_at datetime [not null, default: `now()`]
|
||||
updated_at datetime
|
||||
updated_by int [ref: > users.id]
|
||||
|
||||
indexes {
|
||||
user_id [unique]
|
||||
}
|
||||
}
|
||||
|
||||
Table categories {
|
||||
id int [pk, increment]
|
||||
name jsonb [not null, note: 'multi-language category name']
|
||||
slug varchar [unique, not null]
|
||||
description jsonb
|
||||
icon varchar [note: 'icon identifier']
|
||||
sort_order int [not null, default: 0]
|
||||
is_active boolean [not null, default: true]
|
||||
created_at datetime [not null, default: `now()`]
|
||||
created_by int [not null, ref: > users.id]
|
||||
updated_at datetime
|
||||
updated_by int [ref: > users.id]
|
||||
|
||||
indexes {
|
||||
slug [unique]
|
||||
is_active
|
||||
sort_order
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// COURSE STRUCTURE
|
||||
// ============================================
|
||||
|
||||
Table courses {
|
||||
id int [pk, increment]
|
||||
category_id int [ref: > categories.id]
|
||||
title jsonb [not null, note: '{"th": "...", "en": "..."}']
|
||||
slug varchar [unique, not null]
|
||||
description jsonb
|
||||
thumbnail_url varchar
|
||||
price decimal [not null, default: 0, note: 'must be >= 0']
|
||||
is_free boolean [not null, default: false]
|
||||
have_certificate boolean [not null, default: false, note: 'issue certificate upon completion']
|
||||
status varchar [not null, default: 'DRAFT', note: 'ENUM: DRAFT | PENDING | APPROVED | REJECTED | ARCHIVED']
|
||||
approved_by int [ref: > users.id, note: 'admin user id']
|
||||
approved_at datetime
|
||||
rejection_reason varchar
|
||||
created_at datetime [not null, default: `now()`]
|
||||
created_by int [not null, ref: > users.id, note: 'primary instructor']
|
||||
updated_at datetime
|
||||
updated_by int [ref: > users.id]
|
||||
|
||||
indexes {
|
||||
category_id
|
||||
slug [unique]
|
||||
status
|
||||
created_by
|
||||
(status, is_free)
|
||||
(category_id, status)
|
||||
}
|
||||
}
|
||||
|
||||
Table course_instructors {
|
||||
id int [pk, increment]
|
||||
course_id int [not null, ref: > courses.id]
|
||||
user_id int [not null, ref: > users.id]
|
||||
is_primary boolean [not null, default: false, note: 'primary instructor']
|
||||
joined_at datetime [not null, default: `now()`]
|
||||
|
||||
indexes {
|
||||
(course_id, user_id) [unique]
|
||||
course_id
|
||||
user_id
|
||||
is_primary
|
||||
}
|
||||
}
|
||||
|
||||
Table chapters {
|
||||
id int [pk, increment]
|
||||
course_id int [not null, ref: > courses.id]
|
||||
title jsonb [not null, note: 'multi-language']
|
||||
description jsonb
|
||||
sort_order int [not null, default: 0, note: 'must be >= 0']
|
||||
is_published boolean [not null, default: false]
|
||||
created_at datetime [not null, default: `now()`]
|
||||
updated_at datetime
|
||||
|
||||
Note: 'No created_by/updated_by - use course audit trail'
|
||||
|
||||
indexes {
|
||||
course_id
|
||||
(course_id, sort_order)
|
||||
}
|
||||
}
|
||||
|
||||
Table lessons {
|
||||
id int [pk, increment]
|
||||
chapter_id int [not null, ref: > chapters.id]
|
||||
title jsonb [not null, note: 'multi-language']
|
||||
content jsonb [note: 'multi-language lesson content']
|
||||
type varchar [not null, note: 'ENUM: VIDEO QUIZ']
|
||||
duration_minutes int [note: 'estimated duration']
|
||||
sort_order int [not null, default: 0, note: 'must be >= 0']
|
||||
is_sequential boolean [not null, default: true]
|
||||
prerequisite_lesson_ids jsonb [note: 'array of lesson IDs [1, 2, 3]']
|
||||
require_pass_quiz boolean [default: false]
|
||||
is_published boolean [not null, default: false]
|
||||
created_at datetime [not null, default: `now()`]
|
||||
updated_at datetime
|
||||
|
||||
Note: 'No created_by/updated_by - use course audit trail'
|
||||
|
||||
indexes {
|
||||
chapter_id
|
||||
(chapter_id, sort_order)
|
||||
type
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// QUIZ SYSTEM
|
||||
// ============================================
|
||||
|
||||
Table quizzes {
|
||||
id int [pk, increment]
|
||||
lesson_id int [not null, ref: > lessons.id]
|
||||
title jsonb [not null, note: 'multi-language']
|
||||
description jsonb
|
||||
passing_score int [not null, default: 60, note: 'must be 0-100']
|
||||
time_limit int [note: 'in minutes, must be > 0 if set']
|
||||
shuffle_questions boolean [not null, default: false]
|
||||
shuffle_choices boolean [not null, default: false]
|
||||
show_answers_after_completion boolean [not null, default: true, note: 'show correct answers after quiz completion']
|
||||
created_at datetime [not null, default: `now()`]
|
||||
created_by int [not null, ref: > users.id]
|
||||
updated_at datetime
|
||||
updated_by int [ref: > users.id]
|
||||
|
||||
indexes {
|
||||
lesson_id
|
||||
}
|
||||
}
|
||||
|
||||
Table questions {
|
||||
id int [pk, increment]
|
||||
quiz_id int [not null, ref: > quizzes.id]
|
||||
question jsonb [not null, note: 'multi-language']
|
||||
explanation jsonb [note: 'answer explanation']
|
||||
question_type varchar [not null, default: 'MULTIPLE_CHOICE', note: 'ENUM: MULTIPLE_CHOICE | TRUE_FALSE | SHORT_ANSWER']
|
||||
score int [not null, default: 1, note: 'must be > 0']
|
||||
sort_order int [not null, default: 0]
|
||||
created_at datetime [not null, default: `now()`]
|
||||
updated_at datetime
|
||||
|
||||
Note: 'No created_by/updated_by - saved with quiz'
|
||||
|
||||
indexes {
|
||||
quiz_id
|
||||
(quiz_id, sort_order)
|
||||
}
|
||||
}
|
||||
|
||||
Table choices {
|
||||
id int [pk, increment]
|
||||
question_id int [not null, ref: > questions.id]
|
||||
text jsonb [not null, note: 'multi-language']
|
||||
is_correct boolean [not null, default: false]
|
||||
sort_order int [not null, default: 0]
|
||||
indexes {
|
||||
question_id
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// STUDENT PROGRESS
|
||||
// ============================================
|
||||
|
||||
Table enrollments {
|
||||
id int [pk, increment]
|
||||
user_id int [not null, ref: > users.id]
|
||||
course_id int [not null, ref: > courses.id]
|
||||
status varchar [not null, default: 'ENROLLED', note: 'ENUM: ENROLLED | IN_PROGRESS | COMPLETED | DROPPED']
|
||||
progress_percentage int [not null, default: 0, note: '0-100']
|
||||
enrolled_at datetime [not null, default: `now()`]
|
||||
started_at datetime [note: 'first lesson access']
|
||||
completed_at datetime
|
||||
last_accessed_at datetime
|
||||
|
||||
Note: 'No created_by/updated_by - system managed'
|
||||
|
||||
indexes {
|
||||
(user_id, course_id) [unique, name: 'unique_enrollment']
|
||||
user_id
|
||||
course_id
|
||||
status
|
||||
last_accessed_at
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Table certificates {
|
||||
id int [pk, increment]
|
||||
user_id int [not null, ref: > users.id]
|
||||
course_id int [not null, ref: > courses.id]
|
||||
enrollment_id int [unique, not null, ref: > enrollments.id]
|
||||
file_path varchar [not null, note: 'S3 path to certificate PDF']
|
||||
issued_at datetime [not null, default: `now()`]
|
||||
|
||||
indexes {
|
||||
user_id
|
||||
course_id
|
||||
enrollment_id [unique]
|
||||
(user_id, course_id)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Table lesson_progress {
|
||||
id int [pk, increment]
|
||||
user_id int [not null, ref: > users.id]
|
||||
lesson_id int [not null, ref: > lessons.id]
|
||||
is_completed boolean [not null, default: false]
|
||||
completed_at datetime
|
||||
video_progress_seconds int [default: 0]
|
||||
video_duration_seconds int
|
||||
video_progress_percentage decimal(5,2)
|
||||
last_watched_at datetime
|
||||
created_at datetime [not null, default: `now()`]
|
||||
updated_at datetime
|
||||
|
||||
Note: 'No created_by/updated_by - student action only'
|
||||
|
||||
indexes {
|
||||
(user_id, lesson_id) [unique]
|
||||
user_id
|
||||
lesson_id
|
||||
last_watched_at
|
||||
}
|
||||
}
|
||||
|
||||
Table quiz_attempts {
|
||||
id int [pk, increment]
|
||||
user_id int [not null, ref: > users.id]
|
||||
quiz_id int [not null, ref: > quizzes.id]
|
||||
score int [not null, default: 0, note: '0-100']
|
||||
total_questions int [not null]
|
||||
correct_answers int [not null, default: 0]
|
||||
is_passed boolean [not null, default: false]
|
||||
attempt_number int [not null, default: 1]
|
||||
answers jsonb [note: 'student answers for review']
|
||||
started_at datetime [not null, default: `now()`]
|
||||
completed_at datetime
|
||||
|
||||
Note: 'No updated_at - attempts are immutable after completion'
|
||||
|
||||
indexes {
|
||||
user_id
|
||||
quiz_id
|
||||
(user_id, quiz_id)
|
||||
(user_id, quiz_id, attempt_number)
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// COMMUNICATION
|
||||
// ============================================
|
||||
|
||||
Table announcements {
|
||||
id int [pk, increment]
|
||||
course_id int [not null, ref: > courses.id]
|
||||
title jsonb [not null, note: 'multi-language']
|
||||
content jsonb [not null, note: 'multi-language']
|
||||
status varchar [not null, default: 'DRAFT', note: 'ENUM: DRAFT | PUBLISHED | ARCHIVED']
|
||||
is_pinned boolean [not null, default: false]
|
||||
published_at datetime [note: 'scheduled publish date']
|
||||
created_at datetime [not null, default: `now()`]
|
||||
created_by int [not null, ref: > users.id]
|
||||
updated_at datetime
|
||||
updated_by int [ref: > users.id]
|
||||
|
||||
indexes {
|
||||
course_id
|
||||
created_by
|
||||
status
|
||||
(course_id, status, is_pinned, published_at)
|
||||
}
|
||||
}
|
||||
|
||||
Table announcement_attachments {
|
||||
id int [pk, increment]
|
||||
announcement_id int [not null, ref: > announcements.id]
|
||||
file_name varchar [not null]
|
||||
file_path varchar [not null, note: 'S3 key']
|
||||
file_size int [not null, note: 'bytes']
|
||||
mime_type varchar [not null]
|
||||
created_at datetime [not null, default: `now()`]
|
||||
|
||||
Note: 'No updated_at - attachments are immutable'
|
||||
|
||||
indexes {
|
||||
announcement_id
|
||||
}
|
||||
}
|
||||
|
||||
Table lesson_attachments {
|
||||
id int [pk, increment]
|
||||
lesson_id int [not null, ref: > lessons.id]
|
||||
file_name varchar [not null]
|
||||
file_path varchar [not null, note: 'S3 key']
|
||||
file_size int [not null, note: 'bytes']
|
||||
mime_type varchar [not null]
|
||||
description jsonb [note: 'multi-language']
|
||||
sort_order int [not null, default: 0]
|
||||
created_at datetime [not null, default: `now()`]
|
||||
|
||||
Note: 'No updated_at - use lesson audit trail'
|
||||
|
||||
indexes {
|
||||
lesson_id
|
||||
(lesson_id, sort_order)
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// PAYMENT SYSTEM (Future)
|
||||
// ============================================
|
||||
|
||||
Table orders {
|
||||
id int [pk, increment]
|
||||
user_id int [not null, ref: > users.id]
|
||||
total_amount decimal [not null, default: 0]
|
||||
status varchar [not null, default: 'PENDING', note: 'ENUM: PENDING | PAID | CANCELLED | REFUNDED']
|
||||
created_at datetime [not null, default: `now()`]
|
||||
updated_at datetime
|
||||
|
||||
indexes {
|
||||
user_id
|
||||
status
|
||||
(user_id, status)
|
||||
}
|
||||
}
|
||||
|
||||
Table order_items {
|
||||
id int [pk, increment]
|
||||
order_id int [not null, ref: > orders.id]
|
||||
course_id int [not null, ref: > courses.id]
|
||||
price decimal [not null]
|
||||
created_at datetime [not null, default: `now()`]
|
||||
|
||||
indexes {
|
||||
order_id
|
||||
course_id
|
||||
}
|
||||
}
|
||||
|
||||
Table payments {
|
||||
id int [pk, increment]
|
||||
order_id int [not null, ref: > orders.id]
|
||||
provider varchar [not null, note: 'stripe | paypal | promptpay']
|
||||
transaction_id varchar [unique]
|
||||
amount decimal [not null]
|
||||
status varchar [not null, default: 'PENDING', note: 'ENUM: PENDING | SUCCESS | FAILED']
|
||||
paid_at datetime
|
||||
created_at datetime [not null, default: `now()`]
|
||||
updated_at datetime
|
||||
|
||||
indexes {
|
||||
order_id
|
||||
transaction_id [unique]
|
||||
status
|
||||
}
|
||||
}
|
||||
|
||||
Table instructor_balances {
|
||||
id int [pk, increment]
|
||||
instructor_id int [not null, unique, ref: > users.id]
|
||||
available_amount decimal [not null, default: 0]
|
||||
withdrawn_amount decimal [not null, default: 0]
|
||||
created_at datetime [not null, default: `now()`]
|
||||
updated_at datetime
|
||||
|
||||
indexes {
|
||||
instructor_id [unique]
|
||||
}
|
||||
}
|
||||
|
||||
Table withdrawal_requests {
|
||||
id int [pk, increment]
|
||||
instructor_id int [not null, ref: > users.id]
|
||||
amount decimal [not null]
|
||||
status varchar [not null, default: 'PENDING', note: 'ENUM: PENDING | APPROVED | REJECTED | PAID']
|
||||
approved_by int [ref: > users.id]
|
||||
approved_at datetime
|
||||
rejected_reason varchar
|
||||
created_at datetime [not null, default: `now()`]
|
||||
updated_at datetime
|
||||
updated_by int [ref: > users.id]
|
||||
|
||||
indexes {
|
||||
instructor_id
|
||||
status
|
||||
(instructor_id, status)
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// NOTES & BEST PRACTICES
|
||||
// ============================================
|
||||
|
||||
// 1. ENUM Status Values:
|
||||
// - courses: DRAFT | PENDING | APPROVED | REJECTED | ARCHIVED
|
||||
// - enrollments: ENROLLED | IN_PROGRESS | COMPLETED | DROPPED
|
||||
// - announcements: DRAFT | PUBLISHED | ARCHIVED
|
||||
// - orders: PENDING | PAID | CANCELLED | REFUNDED
|
||||
// - payments: PENDING | SUCCESS | FAILED
|
||||
// - withdrawals: PENDING | APPROVED | REJECTED | PAID
|
||||
// - score_policy: HIGHEST | LATEST | FIRST | AVERAGE
|
||||
// - lesson_type: VIDEO | PDF | TEXT | QUIZ
|
||||
// - question_type: MULTIPLE_CHOICE | TRUE_FALSE | SHORT_ANSWER
|
||||
|
||||
// 2. Audit Trail Strategy:
|
||||
// - Full audit (created_by, updated_by): courses, quizzes, categories, announcements
|
||||
// - Partial audit (created_by only): user_profiles
|
||||
// - No audit: student actions (enrollments, progress, attempts)
|
||||
// - No audit: child records saved with parent (questions, choices, chapters, lessons)
|
||||
|
||||
// 3. Updated Fields:
|
||||
// - updated_at is NULL on creation, only set when actually updated
|
||||
// - updated_by is NULL on creation, only set when updated by someone
|
||||
|
||||
// 4. Multi-Instructor Support:
|
||||
// - course_instructors table allows multiple instructors per course
|
||||
// - is_primary flag identifies main instructor
|
||||
// - created_by in courses table is the original creator
|
||||
|
||||
// 5. Role System:
|
||||
// - roles table stores code (ADMIN) and display names ({"th": "ผู้ดูแลระบบ"})
|
||||
// - Allows easy translation and role management
|
||||
// - users.role_id references roles.id
|
||||
|
||||
// 6. User Profiles:
|
||||
// - Separated from users table for cleaner authentication
|
||||
// - Contains display information (name, bio, avatar)
|
||||
// - prefix field for Thai/international name prefixes
|
||||
|
||||
// 7. Announcement Status:
|
||||
// - DRAFT: not visible to students
|
||||
// - PUBLISHED: visible to enrolled students
|
||||
// - ARCHIVED: hidden but kept for history
|
||||
|
||||
// 8. Foreign Key Actions:
|
||||
// - users.role_id: RESTRICT (don't delete roles in use)
|
||||
// - courses.created_by: RESTRICT (don't delete instructors with courses)
|
||||
// - enrollments: CASCADE (delete with user/course)
|
||||
// - announcements: CASCADE (delete with course)
|
||||
// - quiz_attempts: CASCADE (delete with user)
|
||||
|
|
@ -0,0 +1,205 @@
|
|||
table_name,column_name,data_type,size,is_nullable,is_primary_key,is_foreign_key,description
|
||||
roles,id,INTEGER,10,NO,YES,NO,คีย์หลัก เพิ่มค่าอัตโนมัติ
|
||||
roles,code,VARCHAR,50,NO,NO,NO,รหัสบทบาท (ADMIN | INSTRUCTOR | STUDENT)
|
||||
roles,name,JSONB,,NO,NO,NO,ชื่อบทบาทหลายภาษา
|
||||
roles,description,JSONB,,YES,NO,NO,คำอธิบายบทบาท
|
||||
roles,created_at,TIMESTAMP,,NO,NO,NO,วันเวลาที่สร้าง
|
||||
users,id,INTEGER,10,NO,YES,NO,คีย์หลัก เพิ่มค่าอัตโนมัติ
|
||||
users,username,VARCHAR,100,NO,NO,NO,ชื่อผู้ใช้สำหรับเข้าสู่ระบบ (ไม่ซ้ำ)
|
||||
users,email,VARCHAR,255,NO,NO,NO,อีเมล (ไม่ซ้ำ)
|
||||
users,password,VARCHAR,255,NO,NO,NO,รหัสผ่านที่เข้ารหัสแล้ว
|
||||
users,role_id,INTEGER,10,NO,NO,YES,อ้างอิงบทบาทผู้ใช้
|
||||
users,email_verified_at,TIMESTAMP,,YES,NO,NO,วันเวลาที่ยืนยันอีเมล
|
||||
users,created_at,TIMESTAMP,,NO,NO,NO,วันเวลาที่สร้าง
|
||||
users,updated_at,TIMESTAMP,,YES,NO,NO,วันเวลาที่แก้ไขล่าสุด
|
||||
user_profiles,id,INTEGER,10,NO,YES,NO,คีย์หลัก เพิ่มค่าอัตโนมัติ
|
||||
user_profiles,user_id,INTEGER,10,NO,NO,YES,อ้างอิงผู้ใช้ (ไม่ซ้ำ)
|
||||
user_profiles,prefix,VARCHAR,20,YES,NO,NO,"คำนำหน้าชื่อ enum(นาย, นาง, นางสาว, ดร.)"
|
||||
user_profiles,first_name,VARCHAR,100,NO,NO,NO,ชื่อจริง
|
||||
user_profiles,last_name,VARCHAR,100,NO,NO,NO,นามสกุล
|
||||
user_profiles,phone,VARCHAR,20,YES,NO,NO,เบอร์โทรศัพท์
|
||||
user_profiles,avatar_url,VARCHAR,500,YES,NO,NO,URL รูปโปรไฟล์
|
||||
user_profiles,created_at,TIMESTAMP,,NO,NO,NO,วันเวลาที่สร้าง
|
||||
user_profiles,updated_at,TIMESTAMP,,YES,NO,NO,วันเวลาที่แก้ไขล่าสุด
|
||||
user_profiles,updated_by,INTEGER,10,YES,NO,YES,ผู้ใช้ที่แก้ไขล่าสุด
|
||||
categories,id,INTEGER,10,NO,YES,NO,คีย์หลัก เพิ่มค่าอัตโนมัติ
|
||||
categories,name,JSONB,,NO,NO,NO,ชื่อหมวดหมู่หลายภาษา
|
||||
categories,slug,VARCHAR,100,NO,NO,NO,ตัวระบุสำหรับ URL (ไม่ซ้ำ)
|
||||
categories,description,JSONB,,YES,NO,NO,คำอธิบายหลายภาษา
|
||||
categories,icon,VARCHAR,100,YES,NO,NO,ตัวระบุไอคอน
|
||||
categories,sort_order,INTEGER,10,NO,NO,NO,ลำดับการแสดงผล
|
||||
categories,is_active,BOOLEAN,,NO,NO,NO,สถานะเปิดใช้งาน
|
||||
categories,created_at,TIMESTAMP,,NO,NO,NO,วันเวลาที่สร้าง
|
||||
categories,created_by,INTEGER,10,NO,NO,YES,ผู้สร้าง
|
||||
categories,updated_at,TIMESTAMP,,YES,NO,NO,วันเวลาที่แก้ไขล่าสุด
|
||||
categories,updated_by,INTEGER,10,YES,NO,YES,ผู้แก้ไขล่าสุด
|
||||
courses,id,INTEGER,10,NO,YES,NO,คีย์หลัก เพิ่มค่าอัตโนมัติ
|
||||
courses,category_id,INTEGER,10,YES,NO,YES,อ้างอิงหมวดหมู่
|
||||
courses,title,JSONB,,NO,NO,NO,ชื่อคอร์สหลายภาษา
|
||||
courses,slug,VARCHAR,200,NO,NO,NO,ตัวระบุสำหรับ URL (ไม่ซ้ำ)
|
||||
courses,description,JSONB,,YES,NO,NO,คำอธิบายคอร์สหลายภาษา
|
||||
courses,thumbnail_url,VARCHAR,500,YES,NO,NO,URL รูปปกคอร์ส
|
||||
courses,price,"DECIMAL(10,2)",,NO,NO,NO,ราคาคอร์ส (ต้อง >= 0)
|
||||
courses,is_free,BOOLEAN,,NO,NO,NO,คอร์สฟรี
|
||||
courses,have_certificate,BOOLEAN,,NO,NO,NO,ออกใบประกาศนียบัตรเมื่อจบ
|
||||
courses,status,VARCHAR,20,NO,NO,NO,"สถานะ enum(DRAFT, PENDING, APPROVED, REJECTED, ARCHIVED)"
|
||||
courses,approved_by,INTEGER,10,YES,NO,YES,ผู้ดูแลที่อนุมัติ
|
||||
courses,approved_at,TIMESTAMP,,YES,NO,NO,วันเวลาที่อนุมัติ
|
||||
courses,rejection_reason,TEXT,,YES,NO,NO,เหตุผลที่ปฏิเสธ
|
||||
courses,created_at,TIMESTAMP,,NO,NO,NO,วันเวลาที่สร้าง
|
||||
courses,created_by,INTEGER,10,NO,NO,YES,ผู้สอนหลัก
|
||||
courses,updated_at,TIMESTAMP,,YES,NO,NO,วันเวลาที่แก้ไขล่าสุด
|
||||
courses,updated_by,INTEGER,10,YES,NO,YES,ผู้แก้ไขล่าสุด
|
||||
course_instructors,id,INTEGER,10,NO,YES,NO,คีย์หลัก เพิ่มค่าอัตโนมัติ
|
||||
course_instructors,course_id,INTEGER,10,NO,NO,YES,อ้างอิงคอร์ส
|
||||
course_instructors,user_id,INTEGER,10,NO,NO,YES,อ้างอิงผู้สอน
|
||||
course_instructors,is_primary,BOOLEAN,,NO,NO,NO,ผู้สอนหลัก
|
||||
course_instructors,joined_at,TIMESTAMP,,NO,NO,NO,วันเวลาที่เข้าร่วม
|
||||
chapters,id,INTEGER,10,NO,YES,NO,คีย์หลัก เพิ่มค่าอัตโนมัติ
|
||||
chapters,course_id,INTEGER,10,NO,NO,YES,อ้างอิงคอร์ส
|
||||
chapters,title,JSONB,,NO,NO,NO,ชื่อบทหลายภาษา
|
||||
chapters,description,JSONB,,YES,NO,NO,คำอธิบายบทหลายภาษา
|
||||
chapters,sort_order,INTEGER,10,NO,NO,NO,ลำดับการแสดงผล (ต้อง >= 0)
|
||||
chapters,is_published,BOOLEAN,,NO,NO,NO,สถานะเผยแพร่
|
||||
chapters,created_at,TIMESTAMP,,NO,NO,NO,วันเวลาที่สร้าง
|
||||
chapters,updated_at,TIMESTAMP,,YES,NO,NO,วันเวลาที่แก้ไขล่าสุด
|
||||
lessons,id,INTEGER,10,NO,YES,NO,คีย์หลัก เพิ่มค่าอัตโนมัติ
|
||||
lessons,chapter_id,INTEGER,10,NO,NO,YES,อ้างอิงบท
|
||||
lessons,title,JSONB,,NO,NO,NO,ชื่อบทเรียนหลายภาษา
|
||||
lessons,content,JSONB,,YES,NO,NO,เนื้อหาบทเรียนหลายภาษา
|
||||
lessons,type,VARCHAR,20,NO,NO,NO,"ประเภทบทเรียน (VIDEO, QUIZ)"
|
||||
lessons,duration_minutes,INTEGER,10,YES,NO,NO,ระยะเวลาโดยประมาณ (นาที)
|
||||
lessons,sort_order,INTEGER,10,NO,NO,NO,ลำดับการแสดงผล (ต้อง >= 0)
|
||||
lessons,is_sequential,BOOLEAN,,NO,NO,NO,ต้องเรียนตามลำดับ
|
||||
lessons,prerequisite_lesson_ids,JSONB,,YES,NO,NO,รายการ ID บทเรียนที่ต้องเรียนก่อน
|
||||
lessons,require_pass_quiz,BOOLEAN,,YES,NO,NO,ต้องผ่านแบบทดสอบก่อนดำเนินการต่อ
|
||||
lessons,is_published,BOOLEAN,,NO,NO,NO,สถานะเผยแพร่
|
||||
lessons,created_at,TIMESTAMP,,NO,NO,NO,วันเวลาที่สร้าง
|
||||
lessons,updated_at,TIMESTAMP,,YES,NO,NO,วันเวลาที่แก้ไขล่าสุด
|
||||
quizzes,id,INTEGER,10,NO,YES,NO,คีย์หลัก เพิ่มค่าอัตโนมัติ
|
||||
quizzes,lesson_id,INTEGER,10,NO,NO,YES,อ้างอิงบทเรียน
|
||||
quizzes,title,JSONB,,NO,NO,NO,ชื่อแบบทดสอบหลายภาษา
|
||||
quizzes,description,JSONB,,YES,NO,NO,คำอธิบายแบบทดสอบหลายภาษา
|
||||
quizzes,passing_score,INTEGER,10,NO,NO,NO,คะแนนผ่าน (0-100)
|
||||
quizzes,time_limit,INTEGER,10,YES,NO,NO,เวลาจำกัด (นาที ต้อง > 0 ถ้ากำหนด)
|
||||
quizzes,shuffle_questions,BOOLEAN,,NO,NO,NO,สุ่มลำดับคำถาม
|
||||
quizzes,shuffle_choices,BOOLEAN,,NO,NO,NO,สุ่มลำดับตัวเลือก
|
||||
quizzes,show_answers_after_completion,BOOLEAN,,NO,NO,NO,แสดงเฉลยหลังทำเสร็จ
|
||||
quizzes,created_at,TIMESTAMP,,NO,NO,NO,วันเวลาที่สร้าง
|
||||
quizzes,created_by,INTEGER,10,NO,NO,YES,ผู้สร้าง
|
||||
quizzes,updated_at,TIMESTAMP,,YES,NO,NO,วันเวลาที่แก้ไขล่าสุด
|
||||
quizzes,updated_by,INTEGER,10,YES,NO,YES,ผู้แก้ไขล่าสุด
|
||||
questions,id,INTEGER,10,NO,YES,NO,คีย์หลัก เพิ่มค่าอัตโนมัติ
|
||||
questions,quiz_id,INTEGER,10,NO,NO,YES,อ้างอิงแบบทดสอบ
|
||||
questions,question,JSONB,,NO,NO,NO,ข้อความคำถามหลายภาษา
|
||||
questions,explanation,JSONB,,YES,NO,NO,คำอธิบายเฉลยหลายภาษา
|
||||
questions,question_type,VARCHAR,20,NO,NO,NO,"ประเภทคำถาม enum(MULTIPLE_CHOICE, TRUE_FALSE, SHORT_ANSWER)"
|
||||
questions,score,INTEGER,10,NO,NO,NO,คะแนนสำหรับคำตอบที่ถูก (ต้อง > 0)
|
||||
questions,sort_order,INTEGER,10,NO,NO,NO,ลำดับการแสดงผล
|
||||
questions,created_at,TIMESTAMP,,NO,NO,NO,วันเวลาที่สร้าง
|
||||
questions,updated_at,TIMESTAMP,,YES,NO,NO,วันเวลาที่แก้ไขล่าสุด
|
||||
choices,id,INTEGER,10,NO,YES,NO,คีย์หลัก เพิ่มค่าอัตโนมัติ
|
||||
choices,question_id,INTEGER,10,NO,NO,YES,อ้างอิงคำถาม
|
||||
choices,text,JSONB,,NO,NO,NO,ข้อความตัวเลือกหลายภาษา
|
||||
choices,is_correct,BOOLEAN,,NO,NO,NO,คำตอบที่ถูกต้อง
|
||||
choices,sort_order,INTEGER,10,NO,NO,NO,ลำดับการแสดงผล
|
||||
enrollments,id,INTEGER,10,NO,YES,NO,คีย์หลัก เพิ่มค่าอัตโนมัติ
|
||||
enrollments,user_id,INTEGER,10,NO,NO,YES,อ้างอิงนักเรียน
|
||||
enrollments,course_id,INTEGER,10,NO,NO,YES,อ้างอิงคอร์ส
|
||||
enrollments,status,VARCHAR,20,NO,NO,NO,"สถานะ enum(ENROLLED, IN_PROGRESS, COMPLETED, DROPPED)"
|
||||
enrollments,progress_percentage,INTEGER,10,NO,NO,NO,เปอร์เซ็นต์ความคืบหน้า (0-100)
|
||||
enrollments,enrolled_at,TIMESTAMP,,NO,NO,NO,วันเวลาที่ลงทะเบียน
|
||||
enrollments,started_at,TIMESTAMP,,YES,NO,NO,วันเวลาที่เข้าเรียนครั้งแรก
|
||||
enrollments,completed_at,TIMESTAMP,,YES,NO,NO,วันเวลาที่เรียนจบ
|
||||
enrollments,last_accessed_at,TIMESTAMP,,YES,NO,NO,วันเวลาที่เข้าใช้ล่าสุด
|
||||
certificates,id,INTEGER,10,NO,YES,NO,คีย์หลัก เพิ่มค่าอัตโนมัติ
|
||||
certificates,user_id,INTEGER,10,NO,NO,YES,อ้างอิงนักเรียน
|
||||
certificates,course_id,INTEGER,10,NO,NO,YES,อ้างอิงคอร์ส
|
||||
certificates,enrollment_id,INTEGER,10,NO,NO,YES,อ้างอิงการลงทะเบียน (ไม่ซ้ำ)
|
||||
certificates,file_path,VARCHAR,500,NO,NO,NO,เส้นทาง S3 ไฟล์ PDF ใบประกาศนียบัตร
|
||||
certificates,issued_at,TIMESTAMP,,NO,NO,NO,วันเวลาที่ออกใบประกาศนียบัตร
|
||||
lesson_progress,id,INTEGER,10,NO,YES,NO,คีย์หลัก เพิ่มค่าอัตโนมัติ
|
||||
lesson_progress,user_id,INTEGER,10,NO,NO,YES,อ้างอิงนักเรียน
|
||||
lesson_progress,lesson_id,INTEGER,10,NO,NO,YES,อ้างอิงบทเรียน
|
||||
lesson_progress,is_completed,BOOLEAN,,NO,NO,NO,สถานะเรียนจบ
|
||||
lesson_progress,completed_at,TIMESTAMP,,YES,NO,NO,วันเวลาที่เรียนจบ
|
||||
lesson_progress,video_progress_seconds,INTEGER,10,YES,NO,NO,ความคืบหน้าวีดีโอ (วินาที)
|
||||
lesson_progress,video_duration_seconds,INTEGER,10,YES,NO,NO,ความยาววีดีโอทั้งหมด (วินาที)
|
||||
lesson_progress,video_progress_percentage,"DECIMAL(5,2)",,YES,NO,NO,เปอร์เซ็นต์ความคืบหน้าวีดีโอ
|
||||
lesson_progress,last_watched_at,TIMESTAMP,,YES,NO,NO,วันเวลาที่ดูล่าสุด
|
||||
lesson_progress,created_at,TIMESTAMP,,NO,NO,NO,วันเวลาที่สร้าง
|
||||
lesson_progress,updated_at,TIMESTAMP,,YES,NO,NO,วันเวลาที่แก้ไขล่าสุด
|
||||
quiz_attempts,id,INTEGER,10,NO,YES,NO,คีย์หลัก เพิ่มค่าอัตโนมัติ
|
||||
quiz_attempts,user_id,INTEGER,10,NO,NO,YES,อ้างอิงนักเรียน
|
||||
quiz_attempts,quiz_id,INTEGER,10,NO,NO,YES,อ้างอิงแบบทดสอบ
|
||||
quiz_attempts,score,INTEGER,10,NO,NO,NO,คะแนนที่ได้ (0-100)
|
||||
quiz_attempts,total_questions,INTEGER,10,NO,NO,NO,จำนวนคำถามทั้งหมด
|
||||
quiz_attempts,correct_answers,INTEGER,10,NO,NO,NO,จำนวนคำตอบที่ถูก
|
||||
quiz_attempts,is_passed,BOOLEAN,,NO,NO,NO,สถานะผ่าน
|
||||
quiz_attempts,attempt_number,INTEGER,10,NO,NO,NO,ครั้งที่ทำ
|
||||
quiz_attempts,answers,JSONB,,YES,NO,NO,คำตอบของนักเรียนสำหรับตรวจสอบ
|
||||
quiz_attempts,started_at,TIMESTAMP,,NO,NO,NO,วันเวลาที่เริ่มทำ
|
||||
quiz_attempts,completed_at,TIMESTAMP,,YES,NO,NO,วันเวลาที่ทำเสร็จ
|
||||
announcements,id,INTEGER,10,NO,YES,NO,คีย์หลัก เพิ่มค่าอัตโนมัติ
|
||||
announcements,course_id,INTEGER,10,NO,NO,YES,อ้างอิงคอร์ส
|
||||
announcements,title,JSONB,,NO,NO,NO,ชื่อประกาศหลายภาษา
|
||||
announcements,content,JSONB,,NO,NO,NO,เนื้อหาประกาศหลายภาษา
|
||||
announcements,status,VARCHAR,20,NO,NO,NO,"สถานะ enum(DRAFT, PUBLISHED, ARCHIVED)"
|
||||
announcements,is_pinned,BOOLEAN,,NO,NO,NO,ปักหมุด
|
||||
announcements,published_at,TIMESTAMP,,YES,NO,NO,วันเวลาที่กำหนดเผยแพร่
|
||||
announcements,created_at,TIMESTAMP,,NO,NO,NO,วันเวลาที่สร้าง
|
||||
announcements,created_by,INTEGER,10,NO,NO,YES,ผู้สร้าง
|
||||
announcements,updated_at,TIMESTAMP,,YES,NO,NO,วันเวลาที่แก้ไขล่าสุด
|
||||
announcements,updated_by,INTEGER,10,YES,NO,YES,ผู้แก้ไขล่าสุด
|
||||
announcement_attachments,id,INTEGER,10,NO,YES,NO,คีย์หลัก เพิ่มค่าอัตโนมัติ
|
||||
announcement_attachments,announcement_id,INTEGER,10,NO,NO,YES,อ้างอิงประกาศ
|
||||
announcement_attachments,file_name,VARCHAR,255,NO,NO,NO,ชื่อไฟล์
|
||||
announcement_attachments,file_path,VARCHAR,500,NO,NO,NO,เส้นทาง/คีย์ S3
|
||||
announcement_attachments,file_size,INTEGER,10,NO,NO,NO,ขนาดไฟล์ (ไบต์)
|
||||
announcement_attachments,mime_type,VARCHAR,100,NO,NO,NO,ประเภท MIME
|
||||
announcement_attachments,created_at,TIMESTAMP,,NO,NO,NO,วันเวลาที่สร้าง
|
||||
lesson_attachments,id,INTEGER,10,NO,YES,NO,คีย์หลัก เพิ่มค่าอัตโนมัติ
|
||||
lesson_attachments,lesson_id,INTEGER,10,NO,NO,YES,อ้างอิงบทเรียน
|
||||
lesson_attachments,file_name,VARCHAR,255,NO,NO,NO,ชื่อไฟล์
|
||||
lesson_attachments,file_path,VARCHAR,500,NO,NO,NO,เส้นทาง/คีย์ S3
|
||||
lesson_attachments,file_size,INTEGER,10,NO,NO,NO,ขนาดไฟล์ (ไบต์)
|
||||
lesson_attachments,mime_type,VARCHAR,100,NO,NO,NO,ประเภท MIME
|
||||
lesson_attachments,description,JSONB,,YES,NO,NO,คำอธิบายไฟล์หลายภาษา
|
||||
lesson_attachments,sort_order,INTEGER,10,NO,NO,NO,ลำดับการแสดงผล
|
||||
lesson_attachments,created_at,TIMESTAMP,,NO,NO,NO,วันเวลาที่สร้าง
|
||||
orders,id,INTEGER,10,NO,YES,NO,คีย์หลัก เพิ่มค่าอัตโนมัติ
|
||||
orders,user_id,INTEGER,10,NO,NO,YES,อ้างอิงลูกค้า
|
||||
orders,total_amount,"DECIMAL(10,2)",,NO,NO,NO,ยอดรวมคำสั่งซื้อ
|
||||
orders,status,VARCHAR,20,NO,NO,NO,"สถานะ enum(PENDING, PAID, CANCELLED, REFUNDED)"
|
||||
orders,created_at,TIMESTAMP,,NO,NO,NO,วันเวลาที่สร้าง
|
||||
orders,updated_at,TIMESTAMP,,YES,NO,NO,วันเวลาที่แก้ไขล่าสุด
|
||||
order_items,id,INTEGER,10,NO,YES,NO,คีย์หลัก เพิ่มค่าอัตโนมัติ
|
||||
order_items,order_id,INTEGER,10,NO,NO,YES,อ้างอิงคำสั่งซื้อ
|
||||
order_items,course_id,INTEGER,10,NO,NO,YES,อ้างอิงคอร์ส
|
||||
order_items,price,"DECIMAL(10,2)",,NO,NO,NO,ราคาคอร์ส ณ เวลาที่ซื้อ
|
||||
order_items,created_at,TIMESTAMP,,NO,NO,NO,วันเวลาที่สร้าง
|
||||
payments,id,INTEGER,10,NO,YES,NO,คีย์หลัก เพิ่มค่าอัตโนมัติ
|
||||
payments,order_id,INTEGER,10,NO,NO,YES,อ้างอิงคำสั่งซื้อ
|
||||
payments,provider,VARCHAR,50,NO,NO,NO,"ผู้ให้บริการชำระเงิน enum(stripe, paypal, promptpay)"
|
||||
payments,transaction_id,VARCHAR,100,YES,NO,NO,รหัสธุรกรรมจากผู้ให้บริการ (ไม่ซ้ำ)
|
||||
payments,amount,"DECIMAL(10,2)",,NO,NO,NO,จำนวนเงินที่ชำระ
|
||||
payments,status,VARCHAR,20,NO,NO,NO,"สถานะ enum(PENDING, SUCCESS, FAILED)"
|
||||
payments,paid_at,TIMESTAMP,,YES,NO,NO,วันเวลาที่ชำระเงิน
|
||||
payments,created_at,TIMESTAMP,,NO,NO,NO,วันเวลาที่สร้าง
|
||||
payments,updated_at,TIMESTAMP,,YES,NO,NO,วันเวลาที่แก้ไขล่าสุด
|
||||
instructor_balances,id,INTEGER,10,NO,YES,NO,คีย์หลัก เพิ่มค่าอัตโนมัติ
|
||||
instructor_balances,instructor_id,INTEGER,10,NO,NO,YES,อ้างอิงผู้สอน (ไม่ซ้ำ)
|
||||
instructor_balances,available_amount,"DECIMAL(10,2)",,NO,NO,NO,ยอดเงินคงเหลือ
|
||||
instructor_balances,withdrawn_amount,"DECIMAL(10,2)",,NO,NO,NO,ยอดเงินที่ถอนแล้วทั้งหมด
|
||||
instructor_balances,created_at,TIMESTAMP,,NO,NO,NO,วันเวลาที่สร้าง
|
||||
instructor_balances,updated_at,TIMESTAMP,,YES,NO,NO,วันเวลาที่แก้ไขล่าสุด
|
||||
withdrawal_requests,id,INTEGER,10,NO,YES,NO,คีย์หลัก เพิ่มค่าอัตโนมัติ
|
||||
withdrawal_requests,instructor_id,INTEGER,10,NO,NO,YES,อ้างอิงผู้สอน
|
||||
withdrawal_requests,amount,"DECIMAL(10,2)",,NO,NO,NO,จำนวนเงินที่ขอถอน
|
||||
withdrawal_requests,status,VARCHAR,20,NO,NO,NO,"สถานะ enum(PENDING, APPROVED, REJECTED, PAID)"
|
||||
withdrawal_requests,approved_by,INTEGER,10,YES,NO,YES,ผู้ดูแลที่อนุมัติ
|
||||
withdrawal_requests,approved_at,TIMESTAMP,,YES,NO,NO,วันเวลาที่อนุมัติ
|
||||
withdrawal_requests,rejected_reason,TEXT,,YES,NO,NO,เหตุผลที่ปฏิเสธ
|
||||
withdrawal_requests,created_at,TIMESTAMP,,NO,NO,NO,วันเวลาที่สร้าง
|
||||
withdrawal_requests,updated_at,TIMESTAMP,,YES,NO,NO,วันเวลาที่แก้ไขล่าสุด
|
||||
withdrawal_requests,updated_by,INTEGER,10,YES,NO,YES,ผู้แก้ไขล่าสุด
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue