Commit Graph

786 Commits

Author SHA1 Message Date
a4792206f7 fix: use two-phase bump when shifting sort_order on content insert
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-10 05:26:17 -07:00
a704c3b29f fix: avoid sort_order collisions when inserting content at a specific position
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-10 05:20:12 -07:00
4f873fe9de chore: temporarily disable exam-prep subscription enforcement
Add ExamPrepSubscriptionGateDisabled so learners can access exam-prep content without an IELTS or Duolingo plan. LMS subscription gating is unchanged.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-10 04:44:18 -07:00
c9a4bc1306 free/premium feature 2026-06-10 04:23:47 -07:00
26cf7d2908 feat: scope subscriptions by content type and make Duolingo plans lifetime
LEARN_ENGLISH plans unlock LMS only; IELTS and DUOLINGO unlock matching exam-prep catalog courses. Enable category subscription gating, restrict programs to Learn English, and treat Duolingo subscriptions as non-expiring one-time purchases.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-10 03:59:26 -07:00
58790f0998 fix: avoid unique sort_order conflicts during LMS hierarchy reorder
Bump sort_order before reassignment for programs, courses, and modules so batch reorder no longer violates uq_courses_program_sort and sibling constraints.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-10 03:42:40 -07:00
dfdb2a52dc feat: add LMS lesson reorder endpoint within a module
Add PUT /api/v1/modules/:moduleId/lessons/reorder with lessons.reorder permission, matching the existing modules and exam-prep lesson reorder patterns.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-10 03:28:13 -07:00
e56bea3abf feat: add hierarchy publish status and resolve question type definition IDs
Extend DRAFT/PUBLISHED to programs, courses, modules, and exam-prep hierarchy entities with learner visibility gating and progress exclusion. Resolve question_type_definition_id in question responses for legacy system types and unlinked dynamic questions.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-10 02:40:16 -07:00
5c6cb1b8d3 feat: send in-app and push learner notifications for key milestones
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-09 05:11:16 -07:00
ad4c739722 fix: omit payment_url from admin payments list response
Use a list-specific DTO so GET /api/v1/admin/payments no longer exposes checkout URLs while get-by-id is unchanged.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-09 04:33:14 -07:00
8dd1d40a16 feat: limit Learn English parents to one LMS practice each
Reject creating a second practice on the same course, module, or lesson with 409 Conflict, and enforce the rule in the database via unique partial indexes.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-09 04:28:14 -07:00
b780db5307 feat: expire stale pending payments with background worker
Add a configurable cron worker to bulk-mark PENDING payments past expires_at as EXPIRED. Also remove obsolete integration docs and refresh Swagger/go.mod artifacts.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-09 04:10:17 -07:00
be7946955d fix: show exam-prep catalog courses to learners when subscription gate is disabled
Align catalog list filtering with middleware so student/open-learner tokens return courses instead of an empty list while category subscription enforcement is bypassed.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-09 00:51:15 -07:00
22464479ae feat: add full practice update endpoints for LMS and exam prep
PUT /practices/:id/full and PUT /exam-prep/practices/:id/full sync practice shell, question set settings, and questions in one request.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-08 02:43:34 -07:00
55df6b8b0b fix: allow audio-only dynamic questions without text stimulus
DYNAMIC question create no longer requires QUESTION_TEXT, INSTRUCTION, or TEXT_PASSAGE in dynamic_payload; validation follows the type definition only.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-08 02:20:11 -07:00
685e1d104f feat: add GET notification by ID endpoint
Expose read-only in-app notification details at GET /notifications/:id with owner scoping and list-all admin access.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-05 05:31:46 -07:00
bb03ee1668 feat: paginate question type definitions list API
Add limit and offset query params to GET /questions/type-definitions with total_count metadata. Update integration docs, Postman collection, and page clamping tests.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-05 04:33:41 -07:00
b5b9ef03b5 refactor: consolidate stimulus audio under AUDIO_PROMPT
Remove AUDIO_CLIP from the stimulus component catalog and use AUDIO_PROMPT for all question-side audio. Update integration, practice, and Postman docs accordingly.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-05 03:34:01 -07:00
ab986a08f0 feat: expand builder docs, add practice LMS guide, remove CHART stimulus kinds
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>
2026-06-05 02:54:44 -07:00
33355a4b23 feat: PDF_ATTACHMENT stimulus, dynamic question_text rules, admin builder docs
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>
2026-06-04 11:07:02 -07:00
08a2886654 feat: optional dynamic question_text and OPEN_LEARNER completed access
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>
2026-06-04 09:48:33 -07:00
2605877f12 Resolve question-set question-types to builder definitions.
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>
2026-06-02 06:46:54 -07:00
a75700ffaa Add GET question-sets question-types endpoint for practice sets.
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>
2026-06-02 06:35:46 -07:00
256183ae64 Align learner progress rollups with practice-scoped lesson counts.
Count only children that have published practices at module and above for LMS and exam prep; keep lesson at 100% after one practice and module at 100% after direct module practice.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-02 02:56:12 -07:00
a83745fd93 Fix Chapa verify JSON parsing when amount is numeric.
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>
2026-06-02 02:27:13 -07:00
632371c3d0 apple sign in 2026-06-01 01:02:28 -07:00
c00ab684c5 Fix LMS sequential gating when sort_order has gaps.
Resolve the immediate predecessor by sort_order (and id) instead of requiring sort_order - 1, so learners cannot skip locked programs, courses, or modules when ordering numbers are non-consecutive.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-30 04:04:38 -07:00
fbad083ca4 Add admin payments list API with filters and fix /admin route conflict.
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>
2026-05-29 05:50:46 -07:00
6423bb261e Sanitize Chapa checkout customization text for initialize API.
Strip disallowed characters from customization title and description so subscription payments pass Chapa validation.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-29 04:38:55 -07:00
d3bbd8c95a Add backend Chapa payment success HTML page.
Serve /payment/success and /api/v1/payments/chapa/success to verify tx_ref on redirect and activate subscriptions, and share the payment success template with ArifPay.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-29 04:29:05 -07:00
ed743cf841 field options update 2026-05-28 06:34:31 -07:00
038df4e3db Normalize ArifPay checkout payment URLs before returning.
Clean malformed provider paths (such as /checkout//{session_id}) so subscribe responses persist and return stable payment_url values.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-28 03:25:41 -07:00
71e605a07a Revert "Normalize ArifPay checkout payment URLs before returning."
This reverts commit cd4e3b7811.
2026-05-28 03:16:21 -07:00
cd4e3b7811 Normalize ArifPay checkout payment URLs before returning.
Clean malformed provider paths (such as /checkout//{session_id}) so subscribe responses persist and return stable payment_url values.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-28 03:08:03 -07:00
853bd730bb Fix payment status update parameter typing for ArifPay verification.
Use explicit SQL casts and named sqlc args to avoid PostgreSQL 42P08 ambiguity during nonce/session status updates, and align repository bindings with regenerated sqlc types.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-28 02:07:18 -07:00
d225b45166 Fix ArifPay verification when nonce is missing.
Resolve payments by nonce or session_id in webhook/verify processing so status checks can complete and activate subscriptions even when ArifPay verify responses omit nonce.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-28 02:01:47 -07:00
408cd3fd7d Use practice completion to unlock next student lesson.
Switch lesson accessibility gating from deprecated lesson-complete records to published practice completion of the previous lesson so unlocking follows /progress/practices completion flow.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-28 01:09:46 -07:00
fc67de935d Publish question sets by default and backfill existing sets.
Set question_set creation fallback status to PUBLISHED and add a migration that publishes existing draft/inactive sets while updating the database default status for future records.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-28 00:41:31 -07:00
c77a97b40d Return learner-visible practices with access metadata.
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>
2026-05-28 00:32:44 -07:00
ffbb885d06 Fix LMS practice visibility and completion publish checks.
Require question_sets.status to be PUBLISHED for learner-visible practices and reject completion for non-published practice sets so learner progress reflects only publish-ready content.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-28 00:11:48 -07:00
474bf3282a Fix hierarchical learner progress percentage rollups.
Compute program/course/module/lesson progress using lesson-completion rollups from completed practices, with direct module/course practice completion forcing parent completion as required.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-27 23:57:21 -07:00
8eaac9206e subscription enforced reversed 2026-05-27 11:40:24 -07:00
2e1f9432f6 subscription enforced 2026-05-27 09:56:23 -07:00
a1c6b3c15a progress precentage fix 2026-05-27 09:18:25 -07:00
d3225ca61a Improve Google Android login error diagnostics.
Preserve the underlying Google token validation failure and log safe request context so ID token issues are easier to debug.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-26 06:32:15 -07:00
79fb95ce36 Add category-based subscription controls for LMS and exam prep.
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>
2026-05-26 06:20:49 -07:00
7a4253edf4 Add explicit payment provider selection for subscriptions.
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>
2026-05-26 04:18:24 -07:00
82de00b1e7 Add LMS progress summary endpoint.
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>
2026-05-26 04:07:19 -07:00
56cc009579 progress tracking fix 2026-05-26 03:50:46 -07:00
afdd07d65d Update learner progress to use practice completions only.
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>
2026-05-26 03:27:54 -07:00