fix(coherence): Align education types with DDL (E-COH-005, ST1.5)

- Updated src/modules/education/types/education.types.ts with DDL alignment
- Added all missing enums: DifficultyLevel, CourseStatus, LessonContentType, etc.
- Added AchievementType enum (course_completion, quiz_perfect_score, etc.)
- Updated Course interface to match DDL fields exactly
- Updated Module interface (displayOrder, xpReward)
- Updated Lesson interface (LessonContentType, attachments, displayOrder)
- Updated Enrollment interface (completedLessons, totalLessons, totalXpEarned)
- Updated LessonProgress interface (isCompleted, videoProgressSeconds, xpEarned)
- Updated Quiz interface (passingScorePercentage, xpReward, xpPerfectScoreBonus)
- Updated QuizQuestion interface (displayOrder)
- Updated QuizAttempt interface (scorePoints, maxPoints, scorePercentage, xpEarned)
- Added new interfaces: Certificate, UserAchievement, UserGamificationProfile, UserActivityLog
- Added LessonAttachment interface for JSONB attachments field
- Deprecated old type aliases for backward compatibility

All types now fully aligned with education.* DDL schema.
Note: Services will need migration in separate task (breaking changes documented).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Adrian Flores Cortes 2026-01-26 18:02:18 -06:00
parent d73253130f
commit 0563d4bc9b

View File

@ -1,16 +1,83 @@
/** /**
* Education Module Types * Education Module Types
* Type definitions for education module
* Aligned with education.* DDL schema (apps/database/ddl/schemas/education/00-enums.sql)
*/ */
// ============================================================================ // ============================================================================
// Enums // Enums (Aligned with DDL)
// ============================================================================ // ============================================================================
export type CourseLevel = 'beginner' | 'intermediate' | 'advanced' | 'expert'; // Alineado con education.difficulty_level (DDL)
export type DifficultyLevel = 'beginner' | 'intermediate' | 'advanced' | 'expert';
export enum DifficultyLevelEnum {
BEGINNER = 'beginner',
INTERMEDIATE = 'intermediate',
ADVANCED = 'advanced',
EXPERT = 'expert',
}
/**
* @deprecated Use DifficultyLevel instead for DDL alignment
*/
export type CourseLevel = DifficultyLevel;
// Alineado con education.course_status (DDL)
export type CourseStatus = 'draft' | 'published' | 'archived'; export type CourseStatus = 'draft' | 'published' | 'archived';
export enum CourseStatusEnum {
DRAFT = 'draft',
PUBLISHED = 'published',
ARCHIVED = 'archived',
}
// Alineado con education.lesson_content_type (DDL)
export type LessonContentType = 'video' | 'article' | 'interactive' | 'quiz';
export enum LessonContentTypeEnum {
VIDEO = 'video',
ARTICLE = 'article',
INTERACTIVE = 'interactive',
QUIZ = 'quiz',
}
/**
* @deprecated Use LessonContentType instead for DDL alignment
*/
export type ContentType = 'video' | 'text' | 'quiz' | 'exercise' | 'resource'; export type ContentType = 'video' | 'text' | 'quiz' | 'exercise' | 'resource';
// Alineado con education.enrollment_status (DDL)
export type EnrollmentStatus = 'active' | 'completed' | 'expired' | 'cancelled'; export type EnrollmentStatus = 'active' | 'completed' | 'expired' | 'cancelled';
export type QuestionType = 'multiple_choice' | 'true_false' | 'multiple_answer' | 'short_answer';
export enum EnrollmentStatusEnum {
ACTIVE = 'active',
COMPLETED = 'completed',
EXPIRED = 'expired',
CANCELLED = 'cancelled',
}
// Alineado con education.question_type (DDL)
export type QuestionType = 'multiple_choice' | 'true_false' | 'multiple_select' | 'fill_blank' | 'code_challenge';
export enum QuestionTypeEnum {
MULTIPLE_CHOICE = 'multiple_choice',
TRUE_FALSE = 'true_false',
MULTIPLE_SELECT = 'multiple_select',
FILL_BLANK = 'fill_blank',
CODE_CHALLENGE = 'code_challenge',
}
// Alineado con education.achievement_type (DDL)
export type AchievementType = 'course_completion' | 'quiz_perfect_score' | 'streak_milestone' | 'level_up' | 'special_event';
export enum AchievementTypeEnum {
COURSE_COMPLETION = 'course_completion',
QUIZ_PERFECT_SCORE = 'quiz_perfect_score',
STREAK_MILESTONE = 'streak_milestone',
LEVEL_UP = 'level_up',
SPECIAL_EVENT = 'special_event',
}
// ============================================================================ // ============================================================================
// Category // Category
@ -38,34 +105,34 @@ export interface CreateCategoryInput {
} }
// ============================================================================ // ============================================================================
// Course // Course (Aligned with education.courses DDL)
// ============================================================================ // ============================================================================
export interface Course { export interface Course {
id: string; id: string;
title: string; title: string;
slug: string; slug: string;
description?: string;
shortDescription?: string; shortDescription?: string;
fullDescription?: string;
categoryId: string;
difficultyLevel: DifficultyLevel;
thumbnailUrl?: string; thumbnailUrl?: string;
previewVideoUrl?: string; trailerUrl?: string;
categoryId?: string;
level: CourseLevel;
tags: string[];
isFree: boolean;
price: number;
currency: string;
requiresSubscription: boolean;
minSubscriptionTier?: string;
durationMinutes?: number; durationMinutes?: number;
lessonsCount: number; prerequisites?: string[];
enrolledCount: number; learningObjectives?: string[];
averageRating: number; instructorId: string;
ratingsCount: number; instructorName?: string;
isFree: boolean;
priceUsd?: number;
xpReward: number;
status: CourseStatus; status: CourseStatus;
publishedAt?: Date; publishedAt?: Date;
instructorId?: string; totalModules: number;
aiGenerated: boolean; totalLessons: number;
totalEnrollments: number;
avgRating: number;
totalReviews: number;
createdAt: Date; createdAt: Date;
updatedAt: Date; updatedAt: Date;
} }
@ -119,7 +186,7 @@ export interface CourseFilters {
} }
// ============================================================================ // ============================================================================
// Module // Module (Aligned with education.modules DDL)
// ============================================================================ // ============================================================================
export interface Module { export interface Module {
@ -127,8 +194,8 @@ export interface Module {
courseId: string; courseId: string;
title: string; title: string;
description?: string; description?: string;
sortOrder: number; displayOrder: number;
unlockAfterModuleId?: string; xpReward: number;
createdAt: Date; createdAt: Date;
updatedAt: Date; updatedAt: Date;
} }
@ -146,32 +213,25 @@ export interface CreateModuleInput {
} }
// ============================================================================ // ============================================================================
// Lesson // Lesson (Aligned with education.lessons DDL)
// ============================================================================ // ============================================================================
export interface LessonResource {
name: string;
url: string;
type: string;
}
export interface Lesson { export interface Lesson {
id: string; id: string;
moduleId: string; moduleId: string;
courseId: string;
title: string; title: string;
slug: string; description?: string;
contentType: ContentType; contentType: LessonContentType;
videoUrl?: string; videoUrl?: string;
videoDurationSeconds?: number; videoDurationSeconds?: number;
videoProvider?: string; videoProvider?: string;
contentMarkdown?: string; videoId?: string;
contentHtml?: string; articleContent?: string;
resources: LessonResource[]; attachments?: LessonAttachment[];
sortOrder: number; displayOrder: number;
isPreview: boolean; isPreview: boolean;
aiGenerated: boolean; isMandatory: boolean;
aiSummary?: string; xpReward: number;
createdAt: Date; createdAt: Date;
updatedAt: Date; updatedAt: Date;
} }
@ -196,44 +256,46 @@ export interface CreateLessonInput {
} }
// ============================================================================ // ============================================================================
// Quiz // Quiz (Aligned with education.quizzes DDL)
// ============================================================================ // ============================================================================
export interface QuizOption { export interface Quiz {
id: string; id: string;
text: string; moduleId?: string;
isCorrect: boolean; lessonId?: string;
title: string;
description?: string;
passingScorePercentage: number;
maxAttempts?: number;
timeLimitMinutes?: number;
shuffleQuestions: boolean;
shuffleAnswers: boolean;
showCorrectAnswers: boolean;
xpReward: number;
xpPerfectScoreBonus: number;
isActive: boolean;
createdAt: Date;
updatedAt: Date;
} }
// ============================================================================
// Quiz Question (Aligned with education.quiz_questions DDL)
// ============================================================================
export interface QuizQuestion { export interface QuizQuestion {
id: string; id: string;
quizId: string; quizId: string;
questionType: QuestionType; questionType: QuestionType;
questionText: string; questionText: string;
explanation?: string; options?: Record<string, unknown>;
options?: QuizOption[]; correctAnswer?: string;
correctAnswers?: string[]; correctAnswers?: string[];
explanation?: string;
points: number; points: number;
sortOrder: number; displayOrder: number;
createdAt: Date; createdAt: Date;
} }
export interface Quiz {
id: string;
lessonId?: string;
courseId: string;
title: string;
description?: string;
passingScore: number;
maxAttempts?: number;
timeLimitMinutes?: number;
shuffleQuestions: boolean;
showCorrectAnswers: boolean;
aiGenerated: boolean;
createdAt: Date;
updatedAt: Date;
}
export interface QuizWithQuestions extends Quiz { export interface QuizWithQuestions extends Quiz {
questions: QuizQuestion[]; questions: QuizQuestion[];
} }
@ -262,7 +324,7 @@ export interface CreateQuizQuestionInput {
} }
// ============================================================================ // ============================================================================
// Enrollment // Enrollment (Aligned with education.enrollments DDL)
// ============================================================================ // ============================================================================
export interface Enrollment { export interface Enrollment {
@ -271,14 +333,13 @@ export interface Enrollment {
courseId: string; courseId: string;
status: EnrollmentStatus; status: EnrollmentStatus;
progressPercentage: number; progressPercentage: number;
lessonsCompleted: number; completedLessons: number;
totalLessons: number;
enrolledAt: Date; enrolledAt: Date;
expiresAt?: Date; startedAt?: Date;
completedAt?: Date; completedAt?: Date;
paymentId?: string; expiresAt?: Date;
certificateIssued: boolean; totalXpEarned: number;
certificateUrl?: string;
certificateIssuedAt?: Date;
createdAt: Date; createdAt: Date;
updatedAt: Date; updatedAt: Date;
} }
@ -295,19 +356,19 @@ export interface CreateEnrollmentInput {
} }
// ============================================================================ // ============================================================================
// Lesson Progress // Lesson Progress (Aligned with education.progress DDL)
// ============================================================================ // ============================================================================
export interface LessonProgress { export interface LessonProgress {
id: string; id: string;
userId: string; userId: string;
lessonId: string;
enrollmentId: string; enrollmentId: string;
videoWatchedSeconds: number; lessonId: string;
videoCompleted: boolean; isCompleted: boolean;
startedAt?: Date; videoProgressSeconds?: number;
completedAt?: Date; completedAt?: Date;
userNotes?: string; xpEarned: number;
notes?: string;
createdAt: Date; createdAt: Date;
updatedAt: Date; updatedAt: Date;
} }
@ -319,13 +380,14 @@ export interface UpdateLessonProgressInput {
} }
// ============================================================================ // ============================================================================
// Quiz Attempts // Quiz Attempts (Aligned with education.quiz_attempts DDL)
// ============================================================================ // ============================================================================
export interface QuizAnswer { export interface QuizUserAnswer {
questionId: string; questionId: string;
answer: string | string[]; answer: string | string[];
isCorrect: boolean; isCorrect: boolean;
points: number;
} }
export interface QuizAttempt { export interface QuizAttempt {
@ -333,12 +395,16 @@ export interface QuizAttempt {
userId: string; userId: string;
quizId: string; quizId: string;
enrollmentId?: string; enrollmentId?: string;
score: number; isCompleted: boolean;
passed: boolean; isPassed: boolean;
answers: QuizAnswer[]; userAnswers?: QuizUserAnswer[];
scorePoints: number;
maxPoints: number;
scorePercentage: number;
startedAt: Date; startedAt: Date;
submittedAt?: Date; completedAt?: Date;
timeSpentSeconds?: number; timeTakenSeconds?: number;
xpEarned: number;
createdAt: Date; createdAt: Date;
} }
@ -347,6 +413,11 @@ export interface SubmitQuizInput {
answers: { questionId: string; answer: string | string[] }[]; answers: { questionId: string; answer: string | string[] }[];
} }
/**
* @deprecated Use QuizUserAnswer instead
*/
export type QuizAnswer = QuizUserAnswer;
// ============================================================================ // ============================================================================
// Reviews // Reviews
// ============================================================================ // ============================================================================
@ -381,6 +452,126 @@ export interface CreateReviewInput {
reviewText?: string; reviewText?: string;
} }
// ============================================================================
// Certificates (Aligned with education.certificates DDL)
// ============================================================================
export interface Certificate {
id: string;
userId: string;
enrollmentId: string;
courseId: string;
certificateNumber: string;
issuedAt: Date;
expiresAt?: Date;
certificateUrl?: string;
metadata?: Record<string, unknown>;
createdAt: Date;
}
export interface CreateCertificateInput {
userId: string;
enrollmentId: string;
courseId: string;
certificateNumber: string;
expiresAt?: Date;
}
// ============================================================================
// User Achievements (Aligned with education.user_achievements DDL)
// ============================================================================
export interface UserAchievement {
id: string;
userId: string;
achievementType: AchievementType;
title: string;
description?: string;
iconUrl?: string;
xpAwarded: number;
earnedAt: Date;
metadata?: Record<string, unknown>;
createdAt: Date;
}
export interface CreateAchievementInput {
userId: string;
achievementType: AchievementType;
title: string;
description?: string;
iconUrl?: string;
xpAwarded?: number;
metadata?: Record<string, unknown>;
}
// ============================================================================
// User Gamification Profile (Aligned with education.user_gamification_profile DDL)
// ============================================================================
export interface UserGamificationProfile {
userId: string;
totalXp: number;
currentLevel: number;
currentStreak: number;
longestStreak: number;
totalCoursesCompleted: number;
totalLessonsCompleted: number;
totalQuizzesPassed: number;
totalAchievements: number;
lastActivityAt?: Date;
createdAt: Date;
updatedAt: Date;
}
export interface UpdateGamificationProfileInput {
totalXp?: number;
currentLevel?: number;
currentStreak?: number;
longestStreak?: number;
totalCoursesCompleted?: number;
totalLessonsCompleted?: number;
totalQuizzesPassed?: number;
totalAchievements?: number;
lastActivityAt?: Date;
}
// ============================================================================
// User Activity Log (Aligned with education.user_activity_log DDL)
// ============================================================================
export interface UserActivityLog {
id: string;
userId: string;
activityType: string;
entityType?: string;
entityId?: string;
metadata?: Record<string, unknown>;
ipAddress?: string;
userAgent?: string;
createdAt: Date;
}
export interface CreateActivityLogInput {
userId: string;
activityType: string;
entityType?: string;
entityId?: string;
metadata?: Record<string, unknown>;
ipAddress?: string;
userAgent?: string;
}
// ============================================================================
// Attachments (for lesson attachments JSONB field)
// ============================================================================
export interface LessonAttachment {
name: string;
url: string;
type: string;
size?: number;
}
// ============================================================================ // ============================================================================
// Pagination // Pagination
// ============================================================================ // ============================================================================