Data Model Diagram

This document presents the ResumeBuilder 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. ResumeBuilder 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

courses — src/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

lessons — src/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

enrollments — src/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)

transactions — src/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)

customers — src/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

coupons — src/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_courses — src/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