Data Model Diagram

This document presents the EduNest LMS data model at the field level: the key domain tables drawn directly from the CREATE TABLE / ALTER TABLE statements in src/lib/lms-schema.ts and src/lib/vendor-schema.ts. EduNest stores "soft enums" as plain VARCHAR columns with documented allowed values (so they can be extended without a migration), money as integer cents, and arrays/objects as JSONB.

Course

coursessrc/lib/lms-schema.ts.

Column Type Default Meaning
id SERIAL Primary key
slug VARCHAR(255) Unique URL slug
title VARCHAR(255) Course title
subtitle VARCHAR(500) '' Short tagline
description TEXT '' Full description
instructor_id INT null FK → instructors (ON DELETE SET NULL)
category_id INT null FK → course_categories (ON DELETE SET NULL)
thumbnail / cover_image / promo_video VARCHAR(500) '' Media assets
level VARCHAR(20) 'all' Difficulty (e.g. all, beginner, …)
language VARCHAR(50) '' Course language
price_cents INT 0 Base price (cents)
sale_price_cents INT null Discounted price (cents)
currency VARCHAR(5) 'INR' ISO currency code
status VARCHAR(20) 'draft' draft · pending · published · rejected · archived
rejection_reason TEXT '' Set when rejected by admin
is_featured BOOLEAN false Featured flag
drip_enabled BOOLEAN false Whether lessons drip-release
requirements / outcomes / tags / target_audience JSONB [] List fields
certificate_enabled BOOLEAN false Issue a certificate on completion
duration_minutes INT 0 Total runtime
rating_avg NUMERIC 0 Average review rating
rating_count INT 0 Number of reviews
enrollment_count INT 0 Number of enrollments
meta_title / meta_description VARCHAR '' SEO
published_at TIMESTAMPTZ null Publish timestamp
created_at / updated_at TIMESTAMPTZ NOW() Timestamps

Lesson

lessonssrc/lib/lms-schema.ts.

Column Type Default Meaning
id SERIAL Primary key
section_id INT FK → sections (ON DELETE CASCADE)
course_id INT FK → courses (ON DELETE CASCADE)
title VARCHAR(255) Lesson title
type VARCHAR(30) 'video' Content type (video, audio, text, embed, quiz, …)
content_url VARCHAR(500) '' Media/source URL
content TEXT '' Inline text content
description TEXT '' Short description
data JSONB {} Type-specific fields (provider, embed html, attachments, linked quiz/survey/task ids…)
duration_seconds INT 0 Length in seconds
is_preview BOOLEAN false Free preview before purchase
drip_type VARCHAR(20) 'immediate' immediate · days_after_enroll · date · after_prev
drip_days INT 0 Days offset when drip_type='days_after_enroll'
drip_date DATE null Fixed release date when drip_type='date'
sort_order INT 0 Ordering within the section

Enrollment

enrollmentssrc/lib/lms-schema.ts. Unique on (customer_id, course_id).

Column Type Default Meaning
id SERIAL Primary key
customer_id INT FK → customers (ON DELETE CASCADE)
course_id INT FK → courses (ON DELETE CASCADE)
source VARCHAR(20) 'purchase' purchase · bundle · manual · free
transaction_id INT null The originating purchase, if any
status VARCHAR(20) 'active' Enrollment state
progress_pct NUMERIC 0 Completion percentage
completed_at TIMESTAMPTZ null When the course was completed
enrolled_at TIMESTAMPTZ NOW() Enrollment timestamp

Companion: lesson_progress (unique on (enrollment_id, lesson_id)) holds is_completed, last_position_seconds, and completed_at per lesson.

Transaction (Order)

transactionssrc/lib/lms-schema.ts. This is the course/bundle order record.

Column Type Default Meaning
id SERIAL Primary key
customer_id INT FK → customers (ON DELETE CASCADE)
amount_cents INT 0 Total charged (cents)
subtotal_cents INT null Subtotal before discount (cents)
discount_cents INT 0 Discount applied (cents)
tax_cents INT 0 Tax (cents)
currency VARCHAR(5) 'INR' ISO currency code
gateway VARCHAR(40) '' Payment gateway used
gateway_ref VARCHAR(255) '' Gateway reference/txn id
status VARCHAR(20) 'pending' pending · paid · failed · refunded
coupon_code VARCHAR(60) '' Applied coupon, if any
items JSONB [] Line items (course/bundle ids, prices)
created_at TIMESTAMPTZ NOW() Created
paid_at TIMESTAMPTZ null Paid timestamp

Revenue split is recorded in instructor_earnings (gross_cents, commission_pct, net_cents, status of pending/available/paid) and disbursed via payouts (amount_cents, method, status of requested/approved/paid/rejected).

Customer (Learner / Instructor account)

customerssrc/lib/vendor-schema.ts. One row per portal account; account_type distinguishes a learner from an instructor.

Column Type Default Meaning
id SERIAL Primary key
slug VARCHAR(255) Unique public slug
name VARCHAR(255) Display name
email VARCHAR(255) '' Email address
email_verified BOOLEAN false Email verified flag
phone / phone_code VARCHAR '' Phone number
phone_verified BOOLEAN false Phone verified flag
password_hash VARCHAR(255) '' bcrypt password hash
otp_code VARCHAR(255) '' bcrypt-hashed OTP
otp_expires_at TIMESTAMPTZ null OTP expiry
otp_purpose VARCHAR(20) '' OTP context (verify/reset)
account_type VARCHAR(20) 'student' student · instructor
avatar VARCHAR(500) '' Avatar URL
bio / occupation / company / website text '' Public profile fields
twitter / linkedin / github / instagram VARCHAR(255) '' Social links
notification_prefs JSONB {} Notification preferences
is_blacklisted BOOLEAN false Block flag
is_active BOOLEAN true Active flag
created_at / updated_at TIMESTAMPTZ NOW() Timestamps

The instructor profile lives in instructors (1:1 via customer_id UNIQUE): headline, bio, expertise/social (JSONB), status (pending/approved/rejected/suspended), revenue_share_pct (default 70), payout_method, payout_details (JSONB), approved_at, seq.

Coupon

couponssrc/lib/vendor-schema.ts.

Column Type Default Meaning
id SERIAL Primary key
code VARCHAR(60) Unique coupon code
description TEXT '' Internal note
discount_type VARCHAR(10) 'PERCENT' PERCENT or fixed amount
discount_value NUMERIC 0 Percentage or amount
min_total_cents INT 0 Minimum order to qualify (cents)
max_discount_cents INT 0 Cap on the discount (cents)
max_redemptions INT 0 Global redemption limit (0 = unlimited)
max_per_customer INT 0 Per-customer limit
redemptions INT 0 Times used
applies_to VARCHAR(20) 'ALL' ALL · PRODUCTS · CATEGORIES · COURSES
course_ids / product_ids / category_ids JSONB [] Scope target ids
min_licenses / max_licenses INT 0 Enterprise seat range
is_default BOOLEAN false Auto-applied default coupon
valid_from / valid_until DATE null Validity window
is_active BOOLEAN true Active flag

Bundle

bundles + bundle_coursessrc/lib/lms-schema.ts.

bundles

Column Type Default Meaning
id SERIAL Primary key
slug VARCHAR(255) Unique URL slug
title VARCHAR(255) Bundle title
subtitle VARCHAR(500) '' Tagline
description TEXT '' Description
thumbnail VARCHAR(500) '' Image
instructor_id INT null FK → instructors (null = admin/platform bundle)
price_cents INT 0 Bundle price (cents)
sale_price_cents INT null Discounted price (cents)
currency VARCHAR(5) 'INR' Currency
is_featured BOOLEAN false Featured flag
status VARCHAR(20) 'draft' Lifecycle status

bundle_courses (join, composite PK (bundle_id, course_id))

Column Type Default Meaning
bundle_id INT FK → bundles (ON DELETE CASCADE)
course_id INT FK → courses (ON DELETE CASCADE)
sort_order INT 0 Ordering within the bundle
drip_type VARCHAR(20) 'immediate' immediate · days_after_purchase · after_previous
drip_days INT 0 Days offset for drip release

Soft Enums

Enumerations are stored as VARCHAR with documented allowed values:

Field Table Allowed values
status courses draft · pending · published · rejected · archived
status instructors pending · approved · rejected · suspended
source enrollments purchase · bundle · manual · free
status transactions pending · paid · failed · refunded
status instructor_earnings pending · available · paid (reversed on refund)
status payouts requested · approved · paid · rejected
drip_type lessons immediate · days_after_enroll · date · after_prev
drip_type bundle_courses immediate · days_after_purchase · after_previous
type lessons video · audio · text · embed · quiz · …
type quiz_questions single · multiple · true_false · fill
type survey_questions star · single_choice · multiple_choice · short_answer · long_answer · yes_no · nps
discount_type coupons PERCENT · fixed amount
applies_to coupons ALL · PRODUCTS · CATEGORIES · COURSES
account_type customers student · instructor
sender_role messages learner · instructor
billing_cycle pricing_plans monthly · yearly · one_time · lifetime

These values are read from the actual CREATE TABLE / ALTER TABLE comments in the schema source; because they are plain strings, admins and developers can extend them without altering the column type.


© CreativeCape Solutions · creative-cape.com · support@creative-cape.com