Skip to content

feat: LP catalog + Oxbridge migration + per-module training quiz - #1

Merged
mashhoodr merged 2 commits into
mainfrom
feat/lp-catalog-and-training-quiz
Jul 14, 2026
Merged

feat: LP catalog + Oxbridge migration + per-module training quiz#1
mashhoodr merged 2 commits into
mainfrom
feat/lp-catalog-and-training-quiz

Conversation

@mashhoodr

Copy link
Copy Markdown
Contributor

Summary

Two independent features on one branch — both flowed from the ICT simulation-week (Jul 14–21) partner conversations.

Commit 1 (7d80a4b) — LP catalog + Oxbridge migration (70 rows)

  • New table lesson_plan_catalog with polymorphic source column (`oxbridge`, `taleemabad_core`, `nbf`, `beaconhouse`, …).
  • Idempotency key: unique (source, source_row_id).
  • scripts/migrate-lesson-plans.py — one-shot Oxbridge migration from Taleemabad `fde_production.lesson_plan_externallessonplan` (source='oxbridge', 70 active rows).
  • Already applied to live NIETE-Rumi Supabase — schema_versions v1.0.4, 70 rows verified.

Commit 2 (2f10117) — per-module training quiz (non-blocking)

  • Root cause: Kamal on Card feat: LP catalog + Oxbridge migration + per-module training quiz #1 flagged the per-module quiz gap; the feature was defined in CONTEXT.md but never implemented in bot code (grand quizzes worked; per-module quizzes did not).
  • Adds startTrainingQuiz(userId, moduleId, phoneNumber) in quiz-delivery.service.js, wires into handleModuleDone in content-delivery.service.js (fire-and-forget parallel — quiz Q1 goes out ahead of next-module video).
  • Polymorphic attempts via quiz_kind discriminator column + CHECK constraint on `training_assessment_attempts`.
  • Schema reconcile already applied to live Supabase — `quiz_kind`, `training_module_id`, CHECK constraint, unique in-progress index for training-module attempts.
  • 6 new tests in `tests/training/training-quiz.test.js` — all pass; full suite unchanged from baseline (20 pre-existing failures, 0 new).

Test plan

  • Merge to main → auto-deploy to NIETE-Rumi Railway service
  • On WhatsApp +92 320 6281951: complete a training module with questions attached → verify training quiz fires (Q1 arrives; teacher answers → "quick check — done" message; next module video also delivered)
  • Complete a training module with 0 questions → verify no quiz, next module delivered as before
  • Verify LP catalog data is queryable via portal / bot (70 Oxbridge rows across Grades 6-12)

Refs

New `lesson_plan_catalog` table with polymorphic `source` column for
multi-vendor content (oxbridge, taleemabad_core, nbf, beaconhouse, …).
Idempotency via unique (source, source_row_id).

Also adds scripts/migrate-lesson-plans.py — one-shot Oxbridge migration
from Taleemabad fde_production.lesson_plan_externallessonplan
(source='oxbridge', 70 active rows). HTML content, no PDFs.

Certified counts after migration (verified live via PostgREST):
  Grade Six: 4, Seven: 12, Eight: 11, Nine: 16, Ten: 5, Eleven: 12, Twelve: 10
  Subjects: Biology 13, Chemistry 14, Computer Science 11, General Science 16, Physics 16
  Total: 70 (matches source 1:1)

Applied to live Supabase via schema_versions v1.0.4.

Refs: FEAT-080 (Ramisha), FEAT-059 (Sabeen)
…attempts

Kamal on Card #1 flagged: 'we completed the training but cannot access
the quiz — legacy NIETE app has a quiz after every training.' Root cause
was not migration or routing — the per-module training-quiz code path
simply wasn't implemented in NIETE-Rumi (only grand quizzes were).

Adds:
- startTrainingQuiz(userId, moduleId, phoneNumber) in quiz-delivery.service:
  filters training_questions by training_module_id, creates attempts
  with quiz_kind='training_module'. No cooldown, feedback-only grading.
- sendQuestion/handleQuizButton/gradeAttempt now branch on quiz_kind.
- handleModuleDone in content-delivery.service: counts active questions
  for the module, fires startTrainingQuiz *fire-and-forget*, then
  continues to deliverNextModule (non-blocking parallel model per
  CONTEXT.md's training-quiz spec).
- Schema reconcile on training_assessment_attempts: adds quiz_kind
  (default 'grand') + training_module_id BIGINT + CHECK enforcing
  exactly one of (grand_quiz_id, training_module_id). Idempotent via
  ADD COLUMN IF NOT EXISTS + DO block for the constraint. Applied to
  live Supabase before this commit lands.
- tests/training/training-quiz.test.js: 6 tests covering eligibility
  gate, filter-by-module, fire-and-forget non-blocking, silent-skip
  when 0 questions.

Refs: Card #1 (Kamal — teacher training migration is not fully migrated)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant