Document schema slot label assignment and usage in the admin integration guide. Add a step-by-step dynamic practice creation guide for course/module/lesson scopes. Remove CHART and FLOW_CHART from the stimulus component catalog.
Co-authored-by: Cursor <cursoragent@cursor.com>
Add PDF_ATTACHMENT stimulus kind and MinIO pdf upload (media_type=pdf) for question-side PDFs.
Reject top-level question_text on DYNAMIC create/update; omit it from API responses and derive stored text from stimulus only.
Expand DYNAMIC_QUESTION_TYPE_BUILDER_ADMIN_INTEGRATION.md with full API request/response reference and workflows.
Co-authored-by: Cursor <cursoragent@cursor.com>
Derive question_text from QUESTION_TEXT, INSTRUCTION, or TEXT_PASSAGE stimulus for DYNAMIC questions so the top-level field is no longer required on create.
OPEN_LEARNER access responses now set is_accessible and is_completed to true on all LMS and exam-prep content, with full progress when totals exist.
Co-authored-by: Cursor <cursoragent@cursor.com>
Map legacy runtime types like AUDIO to catalog keys (e.g. audio_conversation_type) so the endpoint matches type-definitions API output.
Co-authored-by: Cursor <cursoragent@cursor.com>
Returns distinct question_type values with per-type counts so clients can resolve types from question_set_id without loading full questions.
Co-authored-by: Cursor <cursoragent@cursor.com>
Accept string or number for amount in verify and webhook payloads so GET /payments/verify can complete successfully.
Co-authored-by: Cursor <cursoragent@cursor.com>
Expose GET /api/v1/admin/payments for filtered gateway transaction listing, constrain /admin/:id to integers so /admin/payments is not mistaken for an admin id, and grant payments.list_all to ADMIN.
Co-authored-by: Cursor <cursoragent@cursor.com>
Expose practices to learner roles based on practice shell publish state and include per-practice access fields derived from linked question set readiness so clients can manage completion/access UX explicitly.
Co-authored-by: Cursor <cursoragent@cursor.com>
Introduce plan and content categories across programs and exam-prep catalog roots, wire category-aware checkout and access checks, and keep learner gating temporarily bypassed until data migration is ready.
Co-authored-by: Cursor <cursoragent@cursor.com>
Require the client to choose CHAPA or ARIFPAY in the subscription checkout request body and route payment initiation and verification through the matching provider.
Co-authored-by: Cursor <cursoragent@cursor.com>
Expose a single learner endpoint that returns the nested LMS hierarchy with the same access-based progress percentages used across the existing content APIs.
Co-authored-by: Cursor <cursoragent@cursor.com>
Remove lesson completion from learner progress percentages, access completion snapshots, and LMS rollups while keeping generated SQLC and Swagger artifacts in sync.
Co-authored-by: Cursor <cursoragent@cursor.com>
Introduce admin CRUD and public version check APIs for Play Store/App Store releases with force or optional update policies, and update profile dropdown seed data for countries, regions, and learner profile fields.
Co-authored-by: Cursor <cursoragent@cursor.com>
Record playback heartbeats via POST /api/v1/videos/engagement/heartbeat and expose completion, replay, and drop-off rates on the analytics dashboard.
Co-authored-by: Cursor <cursoragent@cursor.com>
Expose user counts by education_level, occupation, learning_goal, and language_challange on GET /api/v1/analytics/dashboard.
Co-authored-by: Cursor <cursoragent@cursor.com>
Store options in field_options with public /field-options and admin CRUD; validate learner profile values on update.
Co-authored-by: Cursor <cursoragent@cursor.com>
Keeps the same response shape as STUDENT while skipping sequential locks; progress fields are still populated for completion UI.
Co-authored-by: Cursor <cursoragent@cursor.com>
Introduces invite, verify, accept, resend, and revoke flows using team_members and invitation tokens, sends the branded invitation template, and requires account activation before team login.
Co-authored-by: Cursor <cursoragent@cursor.com>
Adds CRUD and preview APIs, RBAC permissions, seeded system templates, and migrates OTP email/SMS to template rendering.
Co-authored-by: Cursor <cursoragent@cursor.com>
Add Chapa checkout, verify, webhook, and callback flows so subscriptions activate only after confirmed payment. Route subscription checkout through Chapa while keeping ArifPay for direct payments. Include integration docs and a Postman collection.
Co-authored-by: Cursor <cursoragent@cursor.com>
Expose sort_order on CreateExamPrepUnitInput; insert applies explicit index with sibling shifting (aligned with LMS course create). Updated Swagger and LMS-Personas Postman collection.
Co-authored-by: Cursor <cursoragent@cursor.com>
Migration 000065 adds nullable gender text column; persona API and Postman expose it alongside profile_picture.
Co-authored-by: Cursor <cursoragent@cursor.com>
Remove omitempty on LmsPersona.profile_picture so list/get return null when unset. Add LMS-Personas Postman collection matching current API.
Co-authored-by: Cursor <cursoragent@cursor.com>
Introduce lms_personas table, repoint practice persona_id FKs off users, validate persona refs on LMS and exam-prep practice flows, personas.* RBAC permissions, and OpenAPI docs.
Co-authored-by: Cursor <cursoragent@cursor.com>
POST /practices and exam-prep practice create accept missing or null title; persist as empty string. Refresh OpenAPI and document the behavior.
Co-authored-by: Cursor <cursoragent@cursor.com>
Migration 000062 adds lessons.publish_status (DRAFT default for new rows; existing rows published). Editors see all lessons; learners see published-only lists and GET by id. Sequential prerequisites and completion counts ignore drafts. Course lesson_count counts published lessons only. Swagger documents publish_status on create/update bodies.
Co-authored-by: Cursor <cursoragent@cursor.com>
Accept sort_order on CreateLessonInput; SQL falls back to max+1. When set, shift sibling lessons and insert at that position (same pattern as module create). Regenerate sqlc and update Swagger.
Co-authored-by: Cursor <cursoragent@cursor.com>
Migration 000061 inserts the RBAC role and demo user (openlearner@yimaru.com). STUDENT keeps sequential ApplyAccess and practice ordering; OPEN_LEARNER shares learner permissions and customer flows. Document the role in Swagger and point initial seed SQL at the migration for the demo account.
Co-authored-by: Cursor <cursoragent@cursor.com>
Parses body sort_order, shifts sibling courses in-program, and inserts at the requested slot; omitting it keeps append-after-max behavior. Swagger/sqlc regenerated.
Co-authored-by: Cursor <cursoragent@cursor.com>
Admin bulk deactivate/reactivate accepts decimal path segments matching GET /rbac/roles IDs, resolving RoleRecord.name to the platform key. Document 404 when id is unknown. Add Cursor rule: on push, commit dirty tree first without secrets.
Co-authored-by: Cursor <cursoragent@cursor.com>
Expose POST /admin/roles/:role/bulk-deactivate and bulk-reactivate for platform users and team_members, mirroring deactivate/reactivate semantics and optional team member exclusions.
Co-authored-by: Cursor <cursoragent@cursor.com>
Expose GET /api/v1/admin/users/:user_id/recent-activity (progress.get_any_user) merging account creation and LMS completion milestones, with optional practice rows.
Co-authored-by: Cursor <cursoragent@cursor.com>
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>
Null encodes when there is no active plan so clients see explicit subscription state; Swagger regenerated and GET /users description updated accordingly.
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>