Expose GET /api/v1/admin/users/:user_id/lms-learning-activity for progress.get_any_user so admins see program/course/module/lesson completions and practices from stored completion rows.
Co-authored-by: Cursor <cursoragent@cursor.com>
Filtering matches user profile country/region (case-insensitive trim) and derived subscription state in SQL so pagination totals stay correct.
Co-authored-by: Cursor <cursoragent@cursor.com>
Support all-time, year, year+month, and custom from/to query params with filtered metrics and time-series charts.
Co-authored-by: Cursor <cursoragent@cursor.com>
Expose has_practice booleans for LMS and pre-exam hierarchy entities, wire SQL/repository mappings, and regenerate SQLC/Swagger artifacts. Also update the Resend sender display name for outbound emails.
Co-authored-by: Cursor <cursoragent@cursor.com>
Return per-module lesson and practice aggregates under unit modules listing so clients can render module depth without additional queries.
Co-authored-by: Cursor <cursoragent@cursor.com>
Expose per-unit aggregate counts under catalog-course units listing so clients can display unit depth without extra chained requests.
Co-authored-by: Cursor <cursoragent@cursor.com>
Add units, modules, and lessons aggregate counts per catalog course so clients can render hierarchy depth without extra API calls.
Co-authored-by: Cursor <cursoragent@cursor.com>
Update lesson and practice completion flows to cascade module/course/program progress only when both lesson completion and related published practice completion criteria are met, and align progress counters with the new rule.
Made-with: Cursor
Resolve false OTP already used/expired responses during registration by loading OTP rows using user_id plus submitted otp code and validating usage/expiry on the matched row.
Made-with: Cursor
Extend GetQuestionSetItems and GetPublishedQuestionsInSet queries to match
paginated fields; map audio answer join in repository instead of nils.
Made-with: Cursor
- GetSubModulePracticeByID matches sub_module_practices.id or question_set_id
- Prefer primary id when both could match (ORDER BY + LIMIT 1)
- Set Success/StatusCode on practice GET/detail and GetQuestionSetsByOwner
Made-with: Cursor
- Drop question_sets.set_type = PRACTICE filter so sub_module_practices rows list correctly
- Set Success and StatusCode on GET sub-modules/:id/practices response
- Return empty JSON array instead of null for no practices
Made-with: Cursor
Course-management GET/PUT used GetSubModuleLessonByID with is_active=TRUE,
which returned no row for inactive lessons. Align with other ByID lookups
and allow admins to view and edit inactive lessons.
Made-with: Cursor
Introduce dedicated APIs for submodule lesson detail/update and subcategory listing (including Human Language), with SQL/query wiring and handler routing updates.
Made-with: Cursor
Expose APIs to list lessons by submodule and fetch a single lesson by ID, including title, description, intro video URL, and question count.
Made-with: Cursor
Replace rename-based lesson migration with additive sub_module_lessons creation, preserve sub_module_practices as its own model, and enforce QUIZ/PRACTICE filtering in hierarchy reads to prevent cross-mixing.
Made-with: Cursor