Trường Số PRD/18 Online learning
Trường Số · Product Requirements · 09/2026

PRD 18 · Online learning and test preparation

Wires the centre product to the FLYER LMS that already runs (study.flyer.us, teacher.flyer.us): learner profile linked at conversion, centre class mapped to a FLYER class so homework is assigned per lesson and session, results synced into the student record and assessments, Cambridge and IELTS practice packages sold as a fee-plan type with entitlement grant and revocation, and single sign-on from the parent portal. No new LMS is built.

Key facts, origin and limits
Status
Draft v1
Owning module
Đào tạo
Backend
EXISTING learner links, assign-tests, exams, parent reports, feature-configs · EXTEND fee_plan, learning tab, school-config · NEW class mapping, lesson-bound homework, package entitlements, SSO token exchange
Phase
P1 learner link, homework, result sync · P2 centre-authored courses, games, test-prep certificate
Depends on
02 Students, 03 Classes, 13 Assessments, 14 Curriculum, 19 Service packages

Drafted by an AI assistant in a single session on 16/09/2026, extending the PRD set under the original request quoted verbatim on the hub page. A proposal for team discussion, not a decision of the product team.

Sources

  • Public competitor research (PSE ONE, pse4.one), the center-crm-frontend codebase and the staging /v3 OpenAPI specification (182 paths), as of 10/09/2026.
  • The existing / extend / new tags on this page come from a comparison with the staging /v3 specification at that date.
  • A second scan of PSE ONE's public sources on 16/09/2026 (features page, pricing, user-guide articles).
  • Competitor reference: the public scan of pse4.one on 16/09/2026 shows an Enterprise tier (1,000,000 VND/month) adding "online curriculum building, advanced courses, test preparation, student accounts with online courses, educational games"; a separate "Luyện thi Cambridge" site (Starters, Movers, Flyers) presented as a partner initiative; "an e-learning platform with courses and practice tests" listed as a module; and integrations named as Zalo, Facebook, YouTube and Google Form. The competitor must build and supply content itself.

Limits

  • To verify in a hands-on survey of the application, because automated login to the reference product was not authorised in the drafting session:
    • Whether the competitor's e-learning platform is a module inside the same login or a separate site with separate student accounts.
    • How the competitor creates student accounts for online courses: automatically from the student record or by hand, and what students sign in with.
    • Whether their online courses attach to centre classes and sessions or are standalone self-study courses.
    • Who supplies the Cambridge practice content, whether it follows the current exam formats, and whether it is sold to parents directly.
    • Whether online results flow back to the student record, gradebook or parent reports, and whether homework reminders go out through Zalo.
    • Whether "educational games" attach to lessons or form a shared library, and whether they produce result data.
    • Whether the Enterprise tier caps the number of online students or courses.

Proposed design

Eight desktop screens and two mobile screens in operating order: academic staff link a class to its FLYER class, the teacher assigns homework per lesson and session, results flow back into the student record, accounting sells a test-prep package as a fee plan, and the parent opens the learner app through single sign-on; the point to notice is that Trường Số builds no player of its own, every screen only links, assigns, reads results and grants access.

1 · Class online-learning settings (linked)

/classes/:id/settings#elearning · desktop

Class online-learning settings
The header card carries the four items of section 4: link status (Đã liên kết chip with the FLYER class name), the authorised FLYER teacher with assignment rights still valid, last sync, and how many students are in the FLYER class; Tách liên kết, Liên kết lớp có sẵn and Đồng bộ ngay sit in the page header. The roster table has every column: name, student code, FLYER username, enrolment, status with the three states Đã vào lớp FLYER, Chưa có tài khoản (with Tạo tài khoản and Liên kết actions) and Chờ đồng bộ for a student who just transferred in (ELN-02); the last row is a member added by hand on FLYER without an enrolment, flagged Ngoài danh sách and not auto-removed (rule 3).

2 · Unlinked state and the Link existing class dialog

/classes/:id/settings#elearning · desktop

Link existing class
Behind the dialog is the empty state in the exact wording of section 4 ("Lớp chưa liên kết với FLYER. Liên kết để giao bài tập về nhà và theo dõi kết quả.") with Liên kết lớp có sẵn and Tạo lớp FLYER. The dialog lists the lead teacher's FLYER classes: the row matching 12/13 students is selected, a row with 7 out-of-roster members carries an amber warning, and the row already mapped to Movers 2B is greyed out because a FLYER class cannot map to two centre classes (rule 2, PUT returns 409); the note states who will be added and who lands in the Chưa liên kết list. Cancel is far left, the primary button is Liên kết và đồng bộ.

3 · Class homework

/classes/:id#homework · /teach/classes/:id/homework · desktop

Class homework
Status filter Đang mở, Đã hết hạn, Đã đóng plus a date range; a note says results are synced from FLYER every 15 minutes (ELN-05). The table has every column: homework with a type chip, lesson by curriculum code, session (an off-schedule revision has an empty session but still a mandatory lesson, rule 5), due date with a red Quá hạn chip and the count not yet submitted, submitted / total bar, average score, last reminder (24 hours before or 12 hours after the deadline, parent count and channel, ELN-04) and the four actions Xem, Nhắc ngay, Gia hạn, Thu hồi; closed homework keeps only Xem, and homework deleted on FLYER becomes Đã thu hồi with reminders stopped (edge case).

4 · Assign homework drawer

/classes/:id#homework · desktop

Assign homework
The form of ELN-03: lesson defaults to the latest session's lesson, session may be empty for off-schedule work, suggested assignments from the curriculum with two selected and a FLYER library search, due date defaulting to 2 hours before the next session with a 6-hour minimum after assigning (rule 6), parent reminder offsets per the PRD 07 channel policy, audience whole class / present students / hand-picked, and the Tính điểm vào kỳ đánh giá switch bound to the Giữa kỳ 1 period (PRD 13). The note confirms the lead teacher still has assignment rights (rule 4); the primary button reads "Giao 2 bài cho 12 học viên".

5 · Homework detail

/classes/:id#homework · desktop

Homework detail
Wide drawer for an overdue Speaking task: four summary tiles (submitted 10/14, not submitted 3, average 71%, link to per-question analysis on FLYER), a per-student table with Đã nộp, Nộp muộn, Chưa nộp, Đang làm states, percentage score, AI-graded speaking sub-scores, duration and a Xem báo cáo link to attempts/{id}/report; students who have not submitted show the last reminder and whether it was seen. Footer: Thu hồi, Gia hạn (only later, rule 6) and the primary Nhắc 3 học viên chưa nộp.

6 · Student learning tab (extended)

/students/:id#learning · desktop

Student learning tab
Five summary cards: study time 7 and 30 days, 30-day submission rate, open homework, last activity and the linked FLYER account (link source, date, staff, ELN-01). The Gói học trực tuyến section is the entitlement table with product, start, expiry, status chip and related invoice: the Movers package with 14 days left has a Gia hạn button, the renewal row sits in Chờ cấp quyền because its invoice is only partly paid (edge case), and the Starters package has expired. The homework section lists per class with lesson, due date, status, score and Xem báo cáo; the attempts section shows per-skill scores, the Cambridge shields or CEFR scale and the Đã ghi vào điểm thi flag per PRD 13 (ELN-05).

7 · Online package in the fee-plan catalogue

/settings/fee-plans?type=online_package · desktop

Online package in the fee-plan catalogue
The PRD 05 fee-plan catalogue with the Gói học trực tuyến tab selected; four tiles count entitlements in force, expiring within 14 days, awaiting grant, and failed grants (retried 3 times, a Kích hoạt thủ công task created, ELN-06). The table adds the Sản phẩm FLYER and Đang hoạt động columns next to type, duration, price, grant moment and status; one IELTS package is discontinued and one centre-authored course is a draft marked P2.

8 · Online package form

/settings/fee-plans/:id · desktop

Online package form
When the plan type is an online package the form adds the FLYER product from the FLYER-supplied catalogue, duration in months, grant moment (on full payment or at invoicing), an auto-renew switch for paid renewal invoices and expiry notice days 14, 3. The duration field shows a validation error for 0 with the explanation that the term counts from the grant date (rule 9); the note summarises revocation, pausing and retention of learning data.

9 · Parent portal: Learning

/parent/learning · mobile

10 · Open the learner app via single sign-on

/parent/learning · mobile

Parent portal: Learning
Open the learner app via single sign-on
Screen 9: switcher between the two linked students; the Bài tập cần làm card with name, class, due date and per-item status and the Mở ứng dụng học button right below; the Tuần này card with study time, submissions and average score; the latest attempt with a report link; the test-prep package card with 14 days left and a Gia hạn button that opens the invoice with a QR code (ELN-07). Screen 10: the bottom sheet after tapping Mở ứng dụng học names the learner session, states that the one-time code is valid for 60 seconds and bound to this device, shows the countdown, offers the mobile app or study.flyer.us as destinations and notes that every issuance is logged (rule 10).

1Purpose

Practice between sessions is fragmented today: teachers assign work in a learning application, academic staff track it in spreadsheets, parents cannot see progress, and results never return to the student record or the centre's gradebook. FLYER already operates a complete LMS: class assignments, exams, checkpoints, daily challenges, AI speaking grading and weekly parent reports. This PRD rebuilds none of it; it specifies how Trường Số connects the centre's students, classes, curriculum and fee plans to their FLYER counterparts so that assigning, reminding, syncing results and selling practice packages become one operational flow.

In scope

Out of scope

2Today

Trường Số already has the running FLYER system and only needs to connect the two sides.

Existing capabilityEndpointKeep?
Link a CRM customer to learner profiles (several learners, one primary); search learners by username, phone, emailGET/POST /v3/crm/customers/{id}/learners, POST/DELETE .../learners/{link_id}, POST .../set-primary, GET /v3/crm/customers/learners/searchKeep; foundation of the identity link step (PRD 01, 02)
Assignments per FLYER class with submission status; rollup across a teacher's classes; per-question analysisGET /v3/teacher/classes/{class_id}/assign-tests, GET /v3/teacher/viewer/rollup-assign-tests, GET /v3/teacher/assign-tests/{assign_test_id}/analytics/question-analysisKeep; source of submission rates and analysis links
Teacher-created examsGET/POST /v3/teacher/exams and sub-pathsKeep; assessment periods (PRD 13) pick exams here
Learner side: exams, continue journey, daily challenges, attempt reportGET /v3/learner/exams, GET /v3/learner/journey/continue, POST /v3/learner/daily-challenges, GET /v3/learner/attempts/{id}/reportKeep unchanged in the learner application; Trường Số only reads results and opens reports
Weekly and overall parent reportsGET /v3/parent/learner/{id}/weekly-report, /reportKeep; source of the Học tập tab (PRD 02) and progress reports (PRD 07)
Teacher subscriptions; per-learner feature configurationGET /v3/teacher/package/my-subscriptions, GET /v3/learner/feature-configsKeep; verify a teacher may assign; extend to reflect entitlements from online packages
Class lesson reminder through app, email, ZaloPOST /v3/teacher/class-schedules/{id}/remind (PRD 07)Keep; reuse the messaging layer for due-date reminders
Class mapping; homework bound to lesson and session; package entitlements; SSO token exchangenoneBuilt new in this PRD

3User stories and acceptance criteria

ELN-01Learner profile linked at conversion
The consultant completes conversion without leaving the wizard to create a learning account.
  • Given a lead at the conversion step (PRD 01) or a student created directly (PRD 02)
  • When the "Tài khoản FLYER" step offers create new (username generated from name and birth year) or link existing (search by username, guardian phone, email through learners/search)
  • Then the student record stores learner_profile_id; the link is written through POST /v3/crm/customers/{id}/learners and set primary if it is the first learner; credentials are shown once and can be resent to the guardian (PRD 02); conversion cannot complete without a learner profile unless the tenant setting "allow students without a FLYER account" is on.
ELN-02Centre class mapped to a FLYER class
Academic staff link a class to a FLYER class once; the roster then syncs by itself.
  • Given a class (PRD 03) whose main teacher has a FLYER teacher account
  • When they open Lớp → Cài đặt → Học trực tuyến and choose "Tạo lớp FLYER" or "Liên kết lớp có sẵn" from the main teacher's FLYER classes
  • Then a mapping record is Đã liên kết; every active enrollment with a learner profile is added to the FLYER class; later enrollments, transfers and enrollment ends sync within 5 minutes; students without a learner profile appear in a "Chưa liên kết" list with create or link buttons; unlinking deletes neither the FLYER class nor learning data.
ELN-03Homework assigned per lesson and session
The teacher assigns from the curriculum in under a minute after class.
  • Given today's session of a linked class, and the matching lesson (PRD 14) has suggested FLYER assignments
  • When from the attendance sheet or the session page they choose "Giao bài", pick one or more suggested assignments (or search the FLYER library), set the due date (default 2 hours before the next session), and choose whole class or present students
  • Then the assignment is created on FLYER for the mapped class; a homework record stores assign_test_id, lesson_id, session_id, due date; it appears on the class page, the session page and each student's Học tập tab; guardians receive a "Bài tập về nhà" message under the PRD 07 channel policy.
ELN-04Automatic due-date reminders
Guardians are reminded before the deadline with no extra teacher action.
  • Given a homework with a due date and one or more students not yet submitted
  • When 24 hours remain (tenant offset, an extra 2-hour offset may be added) or the deadline passed 12 hours ago
  • Then a "Nhắc bài tập" message goes to guardians of unsubmitted students through the first available channel (Zalo OA within the 48-hour window, in-app, email), respecting quiet hours 21:30–07:00; each student receives at most one message per offset; students who submit while queued receive nothing; delivery status shows on the class homework table.
ELN-05Results synced into the student record and assessments
Academic staff see online results inside the student record and the centre gradebook.
  • Given a student submitted a homework or completed an exam attempt on FLYER
  • When the scheduled 15-minute sync runs, or a FLYER submission webhook is received (if available)
  • Then the Học tập tab (PRD 02) shows the homework, submission status, percentage score, per-skill accuracy, duration and a "Xem báo cáo" link to attempts/{id}/report; homework flagged "tính điểm" writes one score row into the matching assessment period in PRD 13 with source flyer_assign_test, not hand-editable, overridable only with a reason; results arriving after the period close are still written with a "sau hạn" flag.
ELN-06Selling a practice package, granting and revoking entitlement
The accountant sells a practice package as an invoice line; access follows exactly what was paid.
  • Given the fee-plan catalogue has a plan of type online_package (PRD 05) pointing to a FLYER practice product (for example Movers 6 months) configured in PRD 19
  • When an invoice with that line is fully paid (or at creation, per the tenant setting shared with session packages); later the expiry date arrives, the invoice is voided or refunded, or the student is paused
  • Then an entitlement is created with start date, expiry and FLYER product; FLYER is called to grant and learner/feature-configs reflects it within 5 minutes; the guardian receives a "Kích hoạt gói luyện thi" message with login guidance; on grant failure the invoice stays valid and a "Kích hoạt thủ công" task is created for academic staff. On expiry, void, refund or pause the entitlement becomes Hết hạn, Đã thu hồi or Tạm dừng and FLYER is called to revoke or freeze; a pause extends expiry by the paused days; the guardian receives "Sắp hết hạn" 14 and 3 days before with a renewal link on the parent portal; learning data is never deleted.
ELN-07Parent sees progress and signs in once to the learner application
The guardian opens the FLYER learner application from the parent portal without knowing the student's password.
  • Given a guardian signed in to the parent portal by OTP (PRD 07) and a student with a linked learner profile
  • When they open the student's Học tập tab and choose "Mở ứng dụng học"
  • Then the portal calls the token exchange endpoint, receives a one-time code valid for 60 seconds, and redirects to the FLYER learner application (web or deep link to the mobile app) with the right learner's session; the tab shows open homework with due dates, submitted work with scores, this week's study time, the weekly report, and the practice package status with expiry date.
ELN-08Usage analytics per class
The branch manager knows which classes are not practising between sessions.
  • Given a branch with linked classes
  • When they open Báo cáo → Học trực tuyến for a date range
  • Then a per-class table shows assignments given, on-time rate, late rate, average score, average study time per student per week, students inactive 14 days, and unlinked classes; drill-down to students and xlsx export; a student inactive 14 days creates a follow-up task for the student's care owner (as in ATT-06).
ELN-09Centre-authored online course and certificate (P2)
Academic staff package a sequence of lessons into a self-study course with a certificate.
  • Given the curriculum (PRD 14) has lessons with FLYER assignments, and the tenant holds elearning.course.author
  • When they create a course: order lessons, attach required assignments and educational games per lesson, set completion rules (share of required items, minimum final exam score), choose a certificate template with the centre logo
  • Then the course can be sold as an online package or attached free to a class; students see it in their FLYER journey; when the rules are met a certificate with a lookup code is generated as PDF, shown on the parent portal and written to the Học tập tab; the template never uses an exam board's name or logo.

4Screens

Class online-learning settings /classes/:id/settings#elearning

Header: link status (Chưa liên kết / Đã liên kết với [FLYER class name] / Lỗi đồng bộ), authorised FLYER teacher, last sync. Buttons: Tạo lớp FLYER · Liên kết lớp có sẵn · Đồng bộ ngay · Tách liên kết. Student table: name, student code, FLYER username, status (Đã vào lớp FLYER / Chưa có tài khoản / Chờ đồng bộ), actions Tạo tài khoản, Liên kết. Empty state: "Lớp chưa liên kết với FLYER. Liên kết để giao bài tập về nhà và theo dõi kết quả."

Class homework /classes/:id#homework · /teach/classes/:id/homework

Table: homework (name, type chip), lesson (curriculum code), session (date), due date (red "Quá hạn" chip), submitted / total, average score, last reminder, actions Xem · Nhắc ngay · Gia hạn · Thu hồi. Filters: status (Đang mở / Đã hết hạn / Đã đóng), date range. + Giao bài opens a form: lesson (defaults to the latest session's lesson), suggested assignments from the curriculum with a FLYER library search, due date, audience (whole class / present students / hand-picked), "Tính điểm vào kỳ đánh giá" switch. Homework detail: students, submission status, score, link to per-question analysis on FLYER. Empty state: "Chưa có bài tập nào. Giao bài từ buổi học gần nhất."

Student learning tab (extended) /students/:id#learning

Adds to the PRD 02 tab. Summary cards: study time 7 and 30 days, 30-day submission rate, open homework count, last active date. Online packages section: entitlement table (product, start, expiry, status chip, related invoice) and a Gia hạn button (creates an invoice, PRD 05). Homework section: per class with lesson, due date, status, score, Xem báo cáo link. Attempts section: exam, date, per-skill scores, scale (Cambridge shields, CEFR, IELTS band), "đã ghi vào điểm thi" flag (PRD 13). Empty state: "Chưa có dữ liệu học tập. Kiểm tra liên kết tài khoản FLYER."

Online package in the fee-plan catalogue /settings/fee-plans?type=online_package

The PRD 05 fee-plan form adds fields when the type is online package: FLYER product (from the FLYER-supplied catalogue: Starters, Movers, Flyers, IELTS, centre-authored courses in P2), duration (months), grant moment (on full payment / at invoicing), auto-renew when a renewal invoice is paid, expiry notice days. The catalogue table adds columns FLYER product and Active (entitlements currently in force).

Parent portal: Learning /parent/learning

Switcher between linked students (PRD 07). "Bài tập cần làm" card (name, class, due date, Mở ứng dụng học button), "Tuần này" card (study time, submissions, average score), recent attempts with report links, practice package card with expiry and a Gia hạn button (opens the invoice with QR code). "Mở ứng dụng học" performs single sign-on. Empty state: "Học viên chưa có tài khoản học tập. Vui lòng liên hệ trung tâm."

5Business rules

  1. A student (PRD 02) points to exactly one FLYER learner profile; one learner profile may be pointed to by several student records at different branches. Changing the link requires academic staff or above, a reason and an audit entry; the previous link is kept in history.
  2. A centre class maps to at most one FLYER class at a time; a FLYER class may not map to two centre classes. Unlinking requires no open homework.
  3. Trường Số is the authority on class membership; the FLYER roster is derived from active enrollments. Members added by hand on FLYER without an enrollment show an "Ngoài danh sách" warning and are not removed automatically in P1.
  4. A teacher may assign only to classes where they are main teacher, assistant or substitute for the day, and must hold a FLYER teacher account with assignment rights (checked through package/my-subscriptions); otherwise the action is blocked with a clear message and academic staff may assign on their behalf.
  5. Each homework binds to exactly one lesson and at most one session; off-schedule homework (revision, holidays) has an empty session_id and a mandatory lesson.
  6. Default due date is 2 hours before the next session; minimum is 6 hours after assignment; extensions only move later and are audited.
  7. Reminders follow the PRD 07 channel policy and quiet hours; at most one message per offset per student; submitted students receive none. The "Nhắc bài tập" template carries student name, class, homework name, due date.
  8. Results synced from FLYER are read-only in Trường Số. Scores entering an assessment period (PRD 13) follow that period's formula; overrides need a reason and show the original value.
  9. Online package entitlements are granted when the invoice meets the tenant condition (fully paid, or at invoicing); duration counts from the grant date. Renewal before expiry stacks from the old expiry. Void or refund revokes immediately; pause suspends and extends accordingly; withdrawal does not revoke paid access before expiry.
  10. Single sign-on is available only to guardians linked to the student within the tenant, or to adult students authorising themselves; the exchange code is single-use, valid 60 seconds, bound to the issuing device; every issue is audited.
  11. P2: certificates of completion carry the centre's name and logo, a public lookup code, and are never described as an exam board's certificate.

6Data model

EntityFieldsNotes
student (PRD 02)+ learner_link_id uuid null; learner_linked_at; learner_link_source enum(convert, create, import, manual)extend; learner_profile_id already exists
class_lms_linkid uuid; tenant_id (center_id); school_id; class_id; flyer_class_id int64; teacher_profile_id int64; status enum(linked, syncing, error, unlinked); last_synced_at; last_error; created_by; created_at; unlinked_atnew; unique (class_id) while status ≠ unlinked; unique (flyer_class_id)
class_lms_memberid; link_id; student_id; learner_profile_id; enrollment_id; status enum(active, pending, removed, external); synced_atnew; external = on FLYER without an enrollment
homeworkid uuid; tenant_id; school_id; class_id; link_id; lesson_id (PRD 14) not null; session_id null; assign_test_id int64; title; type; assigned_by_staff_id; assigned_at; due_at; audience enum(class, present, selected); grade_into_assessment bool; assessment_period_id null (PRD 13); status enum(open, expired, closed, revoked); reminder_offsets_hours int[]new; unique (assign_test_id)
homework_resultid; homework_id; student_id; learner_profile_id; attempt_id int64 null; status enum(not_started, in_progress, submitted, late); submitted_at; score_pct; skill_scores jsonb; duration_sec; synced_at; late_after_close boolnew; unique (homework_id, student_id); read-only. Study time and last active date are aggregated per day from weekly reports into learning_activity_daily
homework_reminderid; homework_id; student_id; offset_hours; message_id (PRD 07); sent_at; outcomenew; unique (homework_id, student_id, offset_hours)
fee_plan (PRD 05)type gains online_package; + flyer_product_code; duration_months; grant_on enum(paid, invoiced); auto_renew_on_payment bool; expiry_notice_days int[]extend
online_entitlementid uuid; tenant_id; school_id; student_id; learner_profile_id; fee_plan_id; flyer_product_code; tuition_id; starts_at; ends_at; status enum(pending, active, paused, expired, revoked, failed); paused_at; pause_days int; flyer_grant_ref; last_error; created_at; updated_atnew; one row per grant or renewal
sso_exchangeid uuid; tenant_id; guardian_id; student_id; learner_profile_id; code_hash; issued_at; expires_at; consumed_at null; device_fingerprint; ipnew; only the code hash is stored
online_course, course_enrollment, course_certificate (P2)course: id; tenant_id; title; level_code; lesson_ids uuid[] ordered; required_assign_test_ids int64[]; game_ids; completion_rule jsonb {min_required_pct, final_exam_min_score}; certificate_template_id; status enum(draft, published, archived). enrollment: course_id; student_id; source enum(entitlement, class, manual); progress_pct; completed_at. certificate: course_id; student_id; number; lookup_code; issued_at; pdf_file_idnew; unique (course_id, student_id) on certificates
elearning_policy (tenant setting)require_learner_account bool (default on); default_due_hours_before_next_session 2; reminder_offsets_hours [24]; inactive_days_threshold 14; default grant_on; expiry_notice_days [14, 3]; sso_enabled boolstored in school config (PRD 10)

Scoping: every entity carries tenant_id; class- and student-bound entities also carry school_id so the branch filter and permission scopes apply directly. flyer_class_id, assign_test_id, attempt_id and learner_profile_id are FLYER-side int64 keys and are never shown to guardians.

7API contract

MethodPathPurposeStatus
GET/POST · POST/DELETE · POST/v3/crm/customers/{id}/learners · .../learners/{link_id} · .../set-primaryList, create, remove customer-learner links; set primary learnerexisting
GET/v3/crm/customers/learners/searchFind a learner profile to linkexisting
GET/PUT/DELETE/v3/school/classes/{id}/lms-linkRead; create or link ({flyer_class_id} | {create: true, teacher_profile_id}); unlink. PUT returns 409 when the FLYER class is mapped elsewherenew
POST/v3/school/classes/{id}/lms-link/syncSync roster now → {added, removed, pending, external}new
GET/v3/school/lessons/{lesson_id}/suggested-assign-testsSuggested FLYER assignments for a lesson (PRD 14)new
GET/POST/v3/school/classes/{id}/homeworkList; create {lesson_id, session_id?, assign_test_ids[], due_at, audience, student_ids?, grade_into_assessment, reminder_offsets_hours?} → creates the assign-test on FLYER then the homework recordnew
GET/PATCH/DELETE · POST/v3/school/homework/{id} · /remindDetail with per-student results; extend {due_at, reason}; revoke; remind unsubmitted students now (PRD 07 messaging)new
GET/v3/teacher/classes/{class_id}/assign-tests · /v3/teacher/viewer/rollup-assign-tests · /v3/teacher/assign-tests/{assign_test_id}/analytics/question-analysisSubmission status source for the sync; teacher screen; per-question analysis linkexisting
GET/POST/v3/teacher/exams and sub-pathsPick exams for assessment periods (PRD 13)existing
GET/v3/learner/attempts/{id}/report · /v3/parent/learner/{id}/weekly-report · /reportAttempt report; source of study time, skills, activityexisting
GET/v3/school/students/{id}/learningAggregate for the Học tập tab: activity, homework, attempts, entitlements (merged from FLYER endpoints and Trường Số tables)new
POST/v3/school/homework/results/ingestReceiver for a FLYER submission webhook (if published); the scheduled sync is the fallbacknew
GET/PUT/v3/school/fee-plans/{id}Adds the online_package fieldsextend
GET/POST · POST/v3/school/students/{id}/entitlements · /v3/school/entitlements/{id}/revoke · /pause · /resume · /retryList; manual grant {fee_plan_id, starts_at, reason}; revoke, pause, resume, retry; reason and audit on every action. Sellable FLYER products come from /v3/school/online-productsnew
GET/v3/teacher/package/my-subscriptionsVerify the teacher's assignment rightsexisting
GET/v3/learner/feature-configsReflects the learner's entitlements; adds source school_entitlementextend
POST/v3/parent/learner/{id}/sso-codeIssue a one-time exchange code to a guardian signed in to the portalnew
POST/v3/learner/auth/exchangeExchange the code for a learner session; 410 when used or expirednew
GET/v3/parent/learner/{id}/learningAggregate for the parent portal: to-do homework, this week, attempts, packagesnew
GET/v3/school/reports/elearningschool_id, from, to, group_by=class|student; format=xlsxnew
GET/PUT/v3/teacher/school-configelearning_policy blockextend
GET/POST/PATCH · POST · GET/v3/school/courses · /{id}/publish · /{id}/certificates · /v3/public/certificates/{lookup_code} (P2)Centre-authored courses from PRD 14 lessons; publish; issue certificates; public lookupnew

8Permissions

Permissionownerbranch_manageradmissionsacademic_adminteacheraccountantparent
elearning.learner.linkallbranchat conversionbranchnonono
elearning.class.linkallbranchnobranchassigned classes (create, not unlink)nono
elearning.homework.assignallbranchnobranchassigned classesnono
elearning.homework.viewallbranchstudents being consultedbranchassigned classesnolinked students
elearning.results.overrideallbranchnobranchnonono
elearning.entitlement.manageallbranchnobranchnoview, grant through invoiceno
elearning.sso.usenonononononolinked students
elearning.report, elearning.exportallbranchnobranchassigned classes (no export)package reportno
elearning.policyyesnononononono
elearning.course.author, elearning.certificate.issue (P2)allbranchnobranchnonono

9Analytics events

EventProperties
learner_linkedsource (convert|create|import|manual), mode (create|link), by_role
class_lms_linked · class_lms_syncmode, roster_size, unlinked_students · trigger (schedule|manual|enrollment), added, removed, pending, external, outcome
homework_assignedfrom (attendance|session|class), suggested_used, assign_test_count, audience, hours_to_due, grade_into_assessment, seconds_to_assign
homework_reminder_sentoffset_hours, channel, outcome, remaining_unsubmitted
homework_result_syncedvia (webhook|schedule), lag_minutes, status, late_after_close
entitlement_granted · entitlement_revokedflyer_product_code, grant_on, duration_months, renewal, outcome, latency_ms · reason (expired|void|refund|paused|manual)
entitlement_expiry_notice_sentdays_before, channel, renewed_within_7d (updated later)
parent_sso_usedtarget (web|app_deeplink), latency_ms, outcome
course_published · certificate_issued (P2)lesson_count, required_count · course_id, days_to_complete

10Edge cases

11Open questions

Trường Số (truongso.net) · FLYER internal