Commit Graph

790 Commits

Author SHA1 Message Date
1589813dae fix: relink legacy AUDIO questions to audio_conversation_type definition
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-12 03:26:46 -07:00
0e31a08903 feat: add GET /practices/:id/full for practice with question set and questions
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-12 02:15:37 -07:00
c9f4a9c428 feat: auto-assign and return display_order for question set items
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-12 01:38:27 -07:00
8409f69d56 feat: return premium catalog content on GET for client-side lock UI
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-11 01:14:04 -07:00
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