Commit Graph

771 Commits

Author SHA1 Message Date
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
a719c0daca Add mobile app version management and refresh profile field seeds.
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>
2026-05-25 06:52:20 -07:00
3f73afb4bf Add video engagement tracking and analytics metrics.
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>
2026-05-24 02:59:46 -07:00
56089fa8fd Add users by country to analytics dashboard.
Expose by_country breakdown on GET /api/v1/analytics/dashboard from users.country.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-24 01:47:41 -07:00
e957eacf80 Add profile field breakdowns to analytics dashboard.
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>
2026-05-22 09:54:47 -07:00
f7d4b5c3fb Seed country and ethiopia_regions field options for dropdowns.
Add ISO-style country codes and Ethiopian regional states to initial and follow-up migrations.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-22 09:45:39 -07:00
a5acd00637 Add admin-managed field options API for configurable dropdowns.
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>
2026-05-22 09:21:36 -07:00
176f78515d Fix partial team member updates clearing team_role on invite accept.
Use nullable sqlc.narg fields so empty strings are not written to team_role and other optional columns.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-22 07:54:44 -07:00
215a4bd1dc Simplify team invite to email and role; collect profile on accept
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-22 06:49:28 -07:00
0ad7f094cf Include access metadata for OPEN_LEARNER with is_accessible always true
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>
2026-05-22 05:45:44 -07:00
79851d31b3 email invitation 2026-05-22 05:17:19 -07:00
31bd1e3814 Add team member email invitations for admin panel onboarding
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>
2026-05-22 03:43:00 -07:00
868e5ba001 Apply Yimaru Academy branding to email template seeds
Adds branded HTML layout matching the admin portal purple palette, updates 000066 seeds, and adds 000067 migration to refresh existing template rows.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-22 02:12:45 -07:00
5937c5505a Add admin-managed email templates and use them for OTP delivery
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>
2026-05-22 01:28:48 -07:00
1f7b38861e Integrate Chapa for learner subscription payments
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>
2026-05-21 03:35:57 -07:00
de8618191c Normalize broken FCM service account JSON (.env PEM newlines).
Repair multiline PEM inside private_key before Firebase init; add unit test; use normalized JSON for credentials.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-20 08:57:26 -07:00