Trường Số QA/11 Data model, API and imports
Trường Số · QA test suite · Phase 1 · 10/09/2026

11 · Data model, API and imports

Test cases for PRD 11. Every case names the fixture data it needs (see the dashboard fixtures table), numbered steps, and one observable expected result. Trace points to the user story or rule in the PRD.

Key facts, origin and limits
Cases
27
P0 / P1
6 / 16
Regression pack
8
PRD
11 Data model, API and imports
Phase
P1

Drafted by an AI assistant in a single session on 10/09/2026 as part of the Trường Số QA suite, under the request quoted verbatim on the dashboard. A proposal for team review, not a sign-off.

Sources

  • The Trường Số PRD set (Draft v1, 10/09/2026): user stories, screen tables, business rules and permission matrices, plus the Cloud theme reference.

Limits

  • Phase 1 (authoring) only. Cases are executed in Phase 2 against the local build; results are recorded in testcases.json and runs/run-1/, and every result field is still not_run.
  • Cases inherit any open question or inconsistency in the PRDs they trace to.

1Summary

P0
6
P1
16
P2
5
P3
0
Typefunctionalui-uxedgenegativeregressionflowa11yperfsecurityi18n
Count17002110132

2Test cases

IDTitleTypePriorityPhasePreconditionsStepsExpected resultPRD traceData neededRun 1
TS-DAT-001List endpoints paginate with the standard envelopefunctionalP1P1API session.
  1. GET /api/v3/school/students?limit=50&page=2.
  2. GET with limit=500.
Response ListResponse with pagination {limit, page, prev_page, next_page, total_pages, total_count}; limit above 200 clamped or rejected (400).11 §1 envelopes, 12 §2 limit ≤ 200Fixtures belowNot run
TS-DAT-002Error envelope and domain codesfunctionalP1P1API.
  1. Trigger CLASS_FULL, CONFLICT, STALE_VERSION, INVALID_TRANSITION, PENDING_APPROVAL, INSUFFICIENT_STOCK (P2).
Each returns ErrorRespone {code, message, details} with the documented code and HTTP 409 (202 for PENDING_APPROVAL).11 §1 errorsFixtures belowNot run
TS-DAT-003X-Locale header changes API labelsi18nP1P1API.
  1. GET /permissions-catalog with X-Locale vi then en.
Labels Vietnamese then English; error messages likewise.11 §1 auth header, 12 §8Fixtures belowNot run
TS-DAT-004Cross-tenant ids return 404 on every new /v3/school endpointsecurityP0P1Two tenants; ids from the other tenant.
  1. For each new endpoint family (students, guardians, classes, sessions, enrollments, attendance, fee-plans, tuitions, payments, debt, packages, messages, rooms, levels, staff, audit-logs) request a foreign id.
404 for every one; never 200 or 403; no data leak in the body.12 §3 authorisation, test seed 00/10Fixtures belowNot run
TS-DAT-005Tenant is resolved from the token, not from client idssecurityP0P1API as U-ACAD-A.
  1. POST /school/students with school_id of branch B (not in scope) and with a school_id from another tenant.
Branch B: 403 (out of scope); other tenant: 404; nothing created.12 §3Fixtures belowNot run
TS-DAT-006Jobs pattern for long operationsfunctionalP2P1API.
  1. Start an import; GET /v3/school/jobs/{id} repeatedly.
Status pending → running (progress %) → done with result or error report; UI never blocks.11 §1 jobsFixtures belowNot run
TS-DAT-007Domain events published for writesfunctionalP2P1Event stub log.
  1. Change a student status; save attendance; record a payment.
Events student.status_changed, attendance.saved, payment.recorded appear with tenant_id and ids; messaging and aggregates consume them (message row / dashboard tile updates).11 §1 eventsFixtures belowNot run
TS-DAT-008Import templates per entity download with allowed valuesfunctionalP0P1As U-OWNER /crm/imports (or /settings/data).
  1. Choose entity Học viên; download template.
xlsx with the VI header row exactly per PRD 11 (Mã HV, Họ tên, Ngày sinh, Giới tính, Chi nhánh, Trạng thái, Trình độ, Trường, Địa chỉ, PH1 họ tên, PH1 SĐT, PH1 quan hệ, PH1 email, PH1 Zalo đồng ý, PH2 ..., Tài khoản FLYER, Ghi chú), one example row, hidden sheet with enums and branch codes.11 §4 templatesFixtures belowNot run
TS-DAT-009Column mapping auto-maps by header and allows remapfunctionalP1P1A students file with one renamed header.
  1. Upload; read the mapping step.
Known headers auto-mapped; the renamed column listed as unmapped with a manual select; custom fields offered for students.11 §4 wizardFixtures belowNot run
TS-DAT-010Validation preview with errors, warnings, error file, skip togglefunctionalP0P1Students file: 10 rows, 2 invalid phones, 1 missing birthday, 1 unknown level.
  1. Run validation.
Counts: 3 errors (phones and birthday), 1 warning (level created as custom); download error file lists row numbers and reasons; "Bỏ qua dòng lỗi" toggle enables commit of 7 rows.11 §4 validation previewFixtures belowNot run
TS-DAT-011Phone normalisation rulesfunctionalP1P1File with phones "0901234567", "+84 901 234 567", "84901234567", "12345".
  1. Validate.
First three normalise to +84901234567 (and warn about duplicates); "12345" is an error for a guardian.11 §4 data qualityFixtures belowNot run
TS-DAT-012Date parsing: dd/MM/yyyy, yyyy-MM-dd and Excel serialfunctionalP1P1File with birthdays "15/03/2018", "2018-03-15", serial 43174.
  1. Validate and commit.
All three become 2018-03-15.11 §4 datesFixtures belowNot run
TS-DAT-013Names trimmed and double spaces collapsed, casing preservedfunctionalP2P1Name " nguyễn Văn A ".
  1. Commit.
Stored "nguyễn Văn A".11 §4 namesFixtures belowNot run
TS-DAT-014Missing branch code offers create for owner onlyfunctionalP1P1File with branch code "BD" (missing).
  1. Validate as U-OWNER, then as U-ACAD-A.
Owner: prompt "Tạo chi nhánh BD?"; academic admin: error row only.11 §4 branch codesFixtures belowNot run
TS-DAT-015Dedupe strategies for students: skip, merge, overwritefunctionalP0P1File containing S1 (same code) with a new address and a second guardian.
  1. Commit with Bỏ qua; then Gộp; then Ghi đè.
Skip: S1 untouched. Merge: address filled only if blank, second guardian added, existing fields kept. Overwrite: fields replaced. Guardians merged by phone in all modes.11 §4 dedupeFixtures belowNot run
TS-DAT-016Commit runs as a job with progress and result tabsfunctionalP1P1Valid file 200 rows.
  1. Commit.
Progress bar; success/failed counts; detail page with Thành công and Lỗi tabs; cancel available while pending.11 §4 commitFixtures belowNot run
TS-DAT-017Rollback within 24 h when unmodifiedfunctionalP1P1Completed import.
  1. Click Hoàn tác immediately.
  2. On another import, edit one created student, then Hoàn tác.
First: created rows deleted, merged rows kept with audit note. Second: refused "Có bản ghi đã được sửa sau khi nhập".11 §4 rollbackFixtures belowNot run
TS-DAT-018Full import order on Empty CenterflowP0P1Tenant EMPTY; fixture files for steps 1–8.
  1. Import staff, courses and fee plans, rooms, classes, students and guardians, enrollments, opening balances, attendance history in that order.
Each step succeeds referencing the previous (teacher by phone, room by name, class by code); classes generate sessions from max(start_date, import date) with earlier sessions held; enrollments with capacity warnings not blocked; opening balances create packages with sessions_total = remaining flagged is_opening and a tuition "Số dư đầu kỳ" for debt; attendance history creates sheets marked by "Import".11 §4 import orderFixtures belowNot run
TS-DAT-019Classes import pattern parsingfunctionalP1P1Pattern "T3 18:00-19:30; T5 18:00-19:30" and an invalid "Thứ ba 6h".
  1. Validate.
First parses into two weekday rows; second is an error with the row number.11 §4 step 4Fixtures belowNot run
TS-DAT-020Opening balance requires at least one of sessions or debtnegativeP1P1Row with only student code.
  1. Validate.
Error "Cần Buổi còn lại hoặc Còn nợ".11 §4 step 7Fixtures belowNot run
TS-DAT-021Attendance history requires an existing sessionnegativeP1P1Row for a class date with no session.
  1. Validate.
Error "Không có buổi học ngày dd/MM cho lớp X".11 §4 step 8Fixtures belowNot run
TS-DAT-022Import of 5,000 rows validates within 60 s asynchronouslyperfP1P15,000-row students file.
  1. Validate.
Completes ≤ 60 s; UI responsive during processing; progress shown.12 §2 importFixtures belowNot run
TS-DAT-023Import permissions by rolesecurityP1P1U-BM-A, U-ACC, U-ACAD-A, U-TEACH.
  1. Open the wizard as each and choose entity.
BM: all entities; ACC: finance (balances) only; ACAD: students, classes, enrollments; teacher: no access.10 §9 settings.dataFixtures belowNot run
TS-DAT-024Leads import unchangedregressionP1P1Leads file.
  1. Run the existing leads import.
Works as before with dedupe, round-robin assignment and error report.11 §4 bulk-customers existingFixtures belowNot run
TS-DAT-025Identifier formatsfunctionalP1P1Seed data.
  1. Read codes on a student, class, receipt, expense.
HV-000123; MOV-2609-01; PT-Q1-202609-0001; PC-Q1-202609-0001; invoice code = payment_code.11 §5 identifiersFixtures belowNot run
TS-DAT-026Retention job anonymises stale leadsfunctionalP2P1Lead with last activity 25 months ago; nightly job trigger.
  1. Run the job.
Lead name/phone anonymised; audit entry; leads with recent activity untouched.11 §5 leads retention, 12 §4Fixtures belowNot run
TS-DAT-027Import wizard in en localei18nP2P1en.
  1. Open the wizard.
Steps and messages English; template headers stay Vietnamese (documented) with English key row if provided.12 §8Fixtures belowNot run

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