Trường Số QA/05 Tuition and finance
Trường Số · QA test suite · Phase 1 · 10/09/2026
05 · Tuition and finance
Test cases for PRD 05. 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
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.jsonandruns/run-1/, and every result field is stillnot_run. - Cases inherit any open question or inconsistency in the PRDs they trace to.
1Summary
P0
23
P1
30
P2
14
P3
0
| Type | functional | ui-ux | edge | negative | regression | flow | a11y | perf | security | i18n |
|---|---|---|---|---|---|---|---|---|---|---|
| Count | 43 | 1 | 6 | 8 | 0 | 0 | 1 | 0 | 6 | 2 |
2Test cases
| ID | Title | Type | Priority | Phase | Preconditions | Steps | Expected result | PRD trace | Data needed | Run 1 |
|---|---|---|---|---|---|---|---|---|---|---|
| TS-FIN-001 | Add fee plans of each type to a course | functional | P0 | P1 | As U-ACC on /settings/fee-plans. |
| Four plans listed under the course with type chips Trọn khoá / Theo tháng / Gói buổi / Tài liệu; all appear in both pickers; deactivating one hides it from pickers while old invoices still show it. | FIN-01 | Fixtures below | Not run |
| TS-FIN-002 | Fee plan validation | negative | P1 | P1 | Fee plan form. |
| Each rejected inline; VAT range 0–10; instalments must sum to 100. | FIN-01, 05 §5 form | Fixtures below | Not run |
| TS-FIN-003 | Default VAT per type: fee 0, material 5 | functional | P1 | P1 | New fee plan form. |
| VAT field defaults 0 then 5; editable; tenant defaults changeable in /settings/finance. | 05 §11 VAT | Fixtures below | Not run |
| TS-FIN-004 | Create an invoice from a fee plan with QR | functional | P0 | P1 | As U-ACC on /finance/tuition/new?student_id=<S3>. |
| Invoice created via POST tuitions with lines[]; footer showed subtotal 9.600.000, discount 0, VAT 0, total 9.600.000; after save the drawer shows the QR image (POST /v3/payment/qr) with payment_code and a "Thu tiền ngay" button; list shows status Chưa thanh toán; invoice_created message to payer G. | FIN-02 | Fixtures below | Not run |
| TS-FIN-005 | Invoice total formula with line discount, invoice discount and VAT | functional | P0 | P1 | Invoice form. |
| Subtotal 9,860,000; invoice discount 493,000; VAT = 5% of material lines after discount (2×180,000 = 360,000 → 18,000; if the 5% invoice discount is applied proportionally, 17,100); total is a whole VND number and equals Σ(qty×unit − line_discount) − invoice_discount + VAT as displayed; no decimals anywhere. | 05 §6 rule 1 | Fixtures below | Not run |
| TS-FIN-006 | Discount above role limit sets pending approval | functional | P0 | P1 | As U-ACAD-A (limit 5%). |
| Response 202 PENDING_APPROVAL; status chip Chờ duyệt; U-BM-A notified; invoice appears in tab Chờ duyệt; payment button disabled until approved. | FIN-02 | Fixtures below | Not run |
| TS-FIN-007 | Approve and reject a pending invoice | functional | P0 | P1 | INV-5 pending; as U-BM-A. |
| Approved → status Chưa thanh toán, approved_by set, creator notified; rejected → status Đã huỷ (void) with note; audit entries for both. | 05 §8 approve/reject | Fixtures below | Not run |
| TS-FIN-008 | Accountant cannot approve discounts | security | P1 | P1 | As U-ACC on INV-5. |
| Button absent; 403. | 05 §9 finance.discount.approve | Fixtures below | Not run |
| TS-FIN-009 | Invoice form validation | negative | P1 | P1 | Invoice form. |
| Errors: "Cần ít nhất một dòng"; "≥ 0"; "0–10"; required; "Tổng trả góp phải bằng tổng hoá đơn"; "Chọn tài khoản nhận" (required for QR). | 05 §5 invoice form | Fixtures below | Not run |
| TS-FIN-010 | Session package credits on full payment by default | functional | P0 | P1 | S3 invoice FP3 unpaid; credit_on_create off. |
| Before payment balance 0 (package pending); after payment balance 24 with expiry = today + 6 months, status active. | FIN-02 Then, 05 §6 rule 4 | Fixtures below | Not run |
| TS-FIN-011 | Tenant setting credits on creation | functional | P1 | P1 | credit_on_create on. |
| Balance 24 immediately; package status active with expiry from credit date. | 05 §6 rule 4 | Fixtures below | Not run |
| TS-FIN-012 | Voucher applied at invoice creation | functional | P2 | P2 | Voucher group "BACK2SCHOOL" 10%, valid, applicable to Movers 2. |
| POST /vouchers/validate returns the discount; total 8,640,000; voucher_use recorded; a second invoice for the same single-use code fails "Mã đã dùng". | FIN-09 | Fixtures below | Not run |
| TS-FIN-013 | Voucher not stackable with percent discount unless flagged | negative | P2 | P2 | Voucher and 5% discount on the same invoice. |
| Error "Không kết hợp mã giảm giá với giảm giá %" unless the group is stackable. | 05 §6 rule 7 | Fixtures below | Not run |
| TS-FIN-014 | Invoice list KPI tiles and tabs | functional | P0 | P1 | As U-ACC, branch A. |
| Tiles Đã lập tháng này, Đã thu, Còn phải thu, Quá hạn with VND values; tabs Tất cả · Chưa thanh toán · Thanh toán một phần · Quá hạn · Chờ duyệt · Đã thanh toán · Đã huỷ with counts; INV-1 in Chưa thanh toán, INV-2 in Thanh toán một phần, INV-3 in Quá hạn (chip "45 ngày"), INV-4 in Đã thanh toán, INV-5 in Chờ duyệt. | 05 §5 Học phí | Fixtures below | Not run |
| TS-FIN-015 | Invoice list columns and formatting | ui-ux | P1 | P1 | /finance/tuition. |
| Mã HĐ, Học viên (name + class chip), Nội dung, Tổng tiền, Đã thu, Còn lại (red for overdue), Hạn (date + "Quá hạn 45 ngày" chip), Trạng thái, Nhắc gần nhất (date + channel), Thao tác Thu tiền · Gửi nhắc · In; amounts "3.000.000 đ". | 05 §5 columns | Fixtures below | Not run |
| TS-FIN-016 | Invoice list filters and search | functional | P1 | P1 | /finance/tuition. |
| Each narrows correctly; payment code search finds INV-1. | 05 §5 filters | Fixtures below | Not run |
| TS-FIN-017 | Invoice detail sections and buttons | functional | P1 | P1 | INV-4 (paid). |
| Header code, student, chip Đã thanh toán, total, paid, remaining 0, due; sections lines, payments (date, method, amount, PT-Q1-202609-0001, cashier, SePay id, PDF), credit notes, reminders log, e-invoice block, audit; buttons Thu tiền disabled, Gửi nhắc, In hoá đơn, Tạo phiếu giảm, Huỷ disabled (has payments), Xuất HĐĐT. | 05 §5 invoice detail | Fixtures below | Not run |
| TS-FIN-018 | Void an invoice only without payments | functional | P1 | P1 | INV-1 (no payments) and INV-2 (partial). |
| INV-1 status Đã huỷ, excluded from KPI tiles; INV-2 Huỷ disabled and API 409. | 05 §8 void only when no valid payments | Fixtures below | Not run |
| TS-FIN-019 | Bulk monthly billing preview and commit with proration | functional | P0 | P1 | As U-ACC; C3 monthly plan FP2; S2 active whole month; a student who started mid-month (10 of 20 sessions remaining); S4 paused whole month. |
| Preview table rows: S2 1,200,000; mid-month student 600,000 (10/20); S4 absent from the list ("Bảo lưu cả tháng"); commit creates a GroupInvoice with one Tuition per row; notifications per channel; billing_run_created event. | FIN-03 | Fixtures below | Not run |
| TS-FIN-020 | Billing run dry_run does not write | functional | P1 | P1 | Preview open. |
| No invoices created (list unchanged); network shows dry_run=true only. | 05 §8 group-invoices dry_run | Fixtures below | Not run |
| TS-FIN-021 | Record a cash payment and issue a numbered receipt | functional | P0 | P1 | INV-1 unpaid; as U-ACC. |
| Payment created; receipt number PT-Q1-<YYYYMM>-0002 (next after 0001); PDF preview opens with company legal info, branch, payer, amount in words; invoice status Đã thanh toán; receipt message to payer via ZNS; cash book shows the entry. | FIN-04 | Fixtures below | Not run |
| TS-FIN-022 | Partial cash payment | functional | P0 | P1 | INV-1 unpaid. |
| Status Thanh toán một phần; Còn lại 5,600,000; receipt issued for 4,000,000. | FIN-04 partial | Fixtures below | Not run |
| TS-FIN-023 | Overpayment refused | negative | P0 | P1 | INV-2 remaining 700,000. |
| Inline error "Vượt số còn lại (700.000 đ)"; API 400/409; no payment. | 05 §6 rule 2 | Fixtures below | Not run |
| TS-FIN-024 | Payment date cannot be in the future | negative | P1 | P1 | Payment dialog. |
| Rejected "Không được chọn ngày tương lai". | 05 §5 payment dialog | Fixtures below | Not run |
| TS-FIN-025 | Receipt numbering is sequential under concurrency | edge | P0 | P1 | Two cashiers (U-ACC in two sessions). |
| Numbers are consecutive and unique (e.g. 0003 and 0004); no duplicate; no gap. | 05 §6 rule 3, test seed 05 | Fixtures below | Not run |
| TS-FIN-026 | Receipt numbering per branch per month | functional | P1 | P1 | Branch B payment. |
| B receipt PT-TD-<YYYYMM>-0001; A next month restarts at 0001. | 05 §6 rule 3 | Fixtures below | Not run |
| TS-FIN-027 | Void a payment keeps the number and requires reason | functional | P0 | P1 | Payment PT-Q1-...-0002. |
| Payment status void with reason; number retained in the list with chip Đã huỷ; invoice returns to Chưa thanh toán / partial; cash book shows the reversal; audit entry payment.void. | 05 §6 rule 3, 05 §8 payments void | Fixtures below | Not run |
| TS-FIN-028 | Card payment method | functional | P2 | P1 | Payment dialog. |
| Payment method CARD stored; receipt issued; appears in cash book under the chosen account. | 05 §8 method CARD | Fixtures below | Not run |
| TS-FIN-029 | Receipt PDF signed URL | security | P1 | P1 | A payment. |
| Valid link serves the PDF; tampered link 403; link expires after 15 min. | 05 §8 receipt.pdf signed, 12 §3 | Fixtures below | Not run |
| TS-FIN-030 | Accountant vs academic admin payment permission | security | P1 | P1 | As U-ACAD-A without cash grant. |
| Button absent; 403; with the grant enabled by owner, cash only (bank/card methods hidden). | 05 §9 finance.payment.create | Fixtures below | Not run |
| TS-FIN-031 | SePay transfer with payment code auto-matches | functional | P0 | P1 | INV-1 unpaid, code TS1A0001; SEPAY stub. |
| Payment created with method BANK_TRANSFER and sepay_transaction_id sp-001; receipt PT issued; invoice Đã thanh toán; receipt message sent to payer; no manual step. | FIN-05 | Fixtures below | Not run |
| TS-FIN-032 | Transfer without code lands in Chưa đối soát | functional | P0 | P1 | SEPAY stub. |
| Row sp-002 with amount, description, received time and action "Gán vào hoá đơn"; no payment created yet. | FIN-05 | Fixtures below | Not run |
| TS-FIN-033 | Manual match of an unmatched transfer to an invoice | functional | P0 | P1 | sp-002 unmatched; INV-2 remaining 700,000. |
| INV-2 Đã thanh toán; S2 credit 500,000 shown on profile; sp-002 matched_by U-ACC; next invoice form for S2 offers "Dùng số dư". | FIN-05, 05 §11 early payment credit | Fixtures below | Not run |
| TS-FIN-034 | Partial transfer amount accepted as partial payment | functional | P1 | P1 | INV-1 code; transfer 5,000,000 with code. |
| Payment 5,000,000; invoice partial. | FIN-05 partial amounts | Fixtures below | Not run |
| TS-FIN-035 | Duplicate SePay webhook deduped | edge | P0 | P1 | sp-001 already processed. |
| No second payment; invoice not overpaid; log shows deduped on sepay_transaction_id. | 05 §11 dedupe | Fixtures below | Not run |
| TS-FIN-036 | One transfer for two children split | functional | P1 | P1 | Unmatched 2,400,000; INV for S1 and S2 each 1,200,000. |
| Two payments created, both invoices paid, one SePay id referenced on both. | 05 §11 split | Fixtures below | Not run |
| TS-FIN-037 | Debt list aging buckets and columns | functional | P0 | P1 | As U-ACC on /finance/debt. |
| Aging tiles 0–7, 8–30, 31–60, >60 with sums; S7 row in bucket 31–60 with guardian phone, invoices count 1, total due 3,000,000, oldest due date, last reminder, promise date, care owner; row actions Gửi nhắc, Ghi cuộc gọi, Kế hoạch trả, Thu tiền; bulk Gửi nhắc with template picker. | FIN-06 | Fixtures below | Not run |
| TS-FIN-038 | Send reminder in bulk with template | functional | P1 | P1 | Debt list. |
| Batch notify called with template_id; per-channel outcomes shown; Nhắc gần nhất updated on invoices. | FIN-06, 05 §8 notify template_id | Fixtures below | Not run |
| TS-FIN-039 | Set a payment plan | functional | P1 | P1 | S7 INV-3. |
| Plan saved; invoice detail shows parts; sum must equal remaining (validation). | 05 §8 payment-plan | Fixtures below | Not run |
| TS-FIN-040 | Debt reconciliation with invoice list | functional | P0 | P1 | Debt list totals. |
| Equals the sum of debt tiles for the same branch. | REP-02 style reconciliation | Fixtures below | Not run |
| TS-FIN-041 | Package consumption FIFO by expiry and low-balance alert at 3 | functional | P0 | P1 | S1 with two packages: 2 sessions expiring next month, 3 sessions expiring in 6 months (balance 5). |
| First two consumptions come from the earlier-expiry package; after the third, balance 2 and a "Sắp hết buổi" message to G1 plus a desk notification was sent when balance reached 3. | FIN-07 | Fixtures below | Not run |
| TS-FIN-042 | Balance 0 shows Hết buổi and red chip on roster | functional | P1 | P1 | S6 balance 2. |
| S6 in list tab "Hết buổi" / Sắp hết buổi with 0; roster and sheet show a red "Hết buổi" chip; further consumption creates no negative balance. | FIN-07 | Fixtures below | Not run |
| TS-FIN-043 | Consumption from an expired package refused | negative | P1 | P1 | Package expired yesterday with 3 sessions. |
| Consumption refused; student shows "Hết hạn gói"; attendance still saved. | 05 §6 rule 5 | Fixtures below | Not run |
| TS-FIN-044 | Pause freezes expiry | functional | P1 | P1 | S1 package expiry E; pause 30 days; resume. |
| Expiry E + 30; frozen_days 30 on the package. | FIN-07 pause freezes | Fixtures below | Not run |
| TS-FIN-045 | Manual package adjustment requires approval | functional | P2 | P1 | As U-ACC. |
| Adjustment pending until U-BM-A approves; then balance +2; audit. | 05 §8 adjust approval | Fixtures below | Not run |
| TS-FIN-046 | Refund estimate on withdrawal | functional | P1 | P1 | S1 5 sessions unused, unit 250,000, admin fee 10%. |
| Proposal 1,125,000 (5×250,000 − 10%) with breakdown; editable with reason. | FIN-08 | Fixtures below | Not run |
| TS-FIN-047 | Credit note and refund with approval threshold | functional | P0 | P2 | S1 withdrawn; as U-ACC; threshold 5,000,000. |
| First: credit shown on invoice, refund PC-Q1-... in cash book as payment out, balance zeroed. Second: status pending approval; U-BM-A approves; then paid. | FIN-08 | Fixtures below | Not run |
| TS-FIN-048 | Credit note bounds | negative | P1 | P2 | INV-1 total 9,600,000 with an existing credit 1,000,000. |
| Both refused: "Vượt tổng hoá đơn trừ phiếu giảm" / "Vượt số đã thu". | 05 §6 rule 8 | Fixtures below | Not run |
| TS-FIN-049 | Create an expense and see it in the cash book | functional | P1 | P2 | As U-ACC on /finance/cashbook. |
| Row PC-Q1-<YYYYMM>-0001 type Chi; totals update; attachment link signed. | FIN-10 | Fixtures below | Not run |
| TS-FIN-050 | Expense above threshold needs approval | functional | P2 | P2 | Threshold 5,000,000. |
| Status pending; U-BM-A approve; only then counted in Chi phí tiles. | FIN-10 | Fixtures below | Not run |
| TS-FIN-051 | Daily cash close with difference | functional | P1 | P2 | CD-A with today's cash payments 9,600,000 and expense 1,500,000. |
| Expected 8,100,000; difference −100,000 highlighted; close recorded; today's cash payments become non-editable (void only); cash_closed event difference_nonzero. | FIN-10, 05 §6 rule 10 | Fixtures below | Not run |
| TS-FIN-052 | Void after cash close still allowed, edit blocked | edge | P2 | P2 | Closed day. |
| Edit blocked; void allowed with reason and audit. | 05 §6 rule 10 | Fixtures below | Not run |
| TS-FIN-053 | Cash book filters and export | functional | P2 | P2 | /finance/cashbook. |
| Rows filtered; xlsx matches; columns date, code, type, category, counterparty, in, out, account, created by, attachment. | 05 §5 Thu chi | Fixtures below | Not run |
| TS-FIN-054 | E-invoice issue success and failure | functional | P2 | P2 | Provider stub; INV-4 paid. |
| Success: number and lookup code stored, PDF link shown. Failure: provider message displayed with Thử lại; nothing stored. | FIN-11 | Fixtures below | Not run |
| TS-FIN-055 | Finance report tiles and reconciliation | functional | P0 | P1 | As U-OWNER, this month, branch A. |
| Tiles billed, collected, outstanding, overdue, refunds, expenses, net cash, collection rate, revenue by course and by fee plan type, deferred revenue (unused sessions × unit price); both comparisons equal to the VND. | FIN-12, REP-02 | Fixtures below | Not run |
| TS-FIN-056 | Report drill-down to invoices and export | functional | P1 | P1 | Finance report. |
| Lands on /finance/tuition with the period filter applied; xlsx downloads. | FIN-12 | Fixtures below | Not run |
| TS-FIN-057 | Finance report scope by role | security | P1 | P1 | U-BM-A and U-ACAD-A. |
| U-BM-A sees branch A only; U-ACAD-A has no finance report (403 / hidden). | 05 §9 finance.report | Fixtures below | Not run |
| TS-FIN-058 | Every money write is audited with before/after | security | P0 | P1 | Perform: create invoice, pay, void payment, discount approve. |
| Four entries with actions tuition.create, tuition.pay, payment.void, tuition.approve; each has before/after including amount and status fields, actor, IP, request_id. | 05 §6 rule 11, 12 §6 | Fixtures below | Not run |
| TS-FIN-059 | Idempotency-Key on pay prevents double payment | edge | P1 | P1 | INV-1. |
| One payment; second response returns the same payment; no second receipt number. | 11 §1 idempotency | Fixtures below | Not run |
| TS-FIN-060 | Parent sees only own invoices | security | P1 | P2 | G1. |
| Lists INV-1/INV-2 (children S1, S2); INV-3 (S7) → 404. | 05 §9 parent own children | Fixtures below | Not run |
| TS-FIN-061 | Money formatting vi and en | i18n | P1 | P1 | Invoice list in vi then en. |
| vi "9.600.000 đ"; en "9,600,000 đ" (or "VND 9,600,000" consistently across the app); no decimals. | 12 §8 money | Fixtures below | Not run |
| TS-FIN-062 | Currency locked to VND | negative | P2 | P1 | Course with currency USD in the stub. |
| Warning "Chỉ hỗ trợ VND"; plan creation blocked until currency VND. | 05 §11 currency | Fixtures below | Not run |
| TS-FIN-063 | Instalment invoice: partial pay then withdraw | edge | P2 | P2 | Two-part instalment, first part paid. |
| Credit note proposed on the unpaid second instalment; refund limited to the paid portion minus consumed value. | 05 §11 instalment | Fixtures below | Not run |
| TS-FIN-064 | Sibling discount reason and automatic percent | functional | P2 | P1 | Tenant sibling percent 5%; G1 has S1 and S2. |
| Discount 5% prefilled with reason "Anh chị em"; editable. | 05 §11 sibling | Fixtures below | Not run |
| TS-FIN-065 | Package moves with the student on branch transfer; revenue stays | edge | P2 | P1 | S1 transferred to B with 5 sessions. |
| A revenue unchanged; deferred revenue for the 5 sessions moves to B with an inter-branch note. | 05 §11 package transfer | Fixtures below | Not run |
| TS-FIN-066 | Invoice form keyboard: add line, remove line, submit | a11y | P2 | P1 | Invoice form. |
| All actions reachable; focus returns to a sensible element after removal; totals update live. | 12 §9 | Fixtures below | Not run |
| TS-FIN-067 | Finance pages in en locale | i18n | P2 | P1 | en. |
| Tabs Unpaid / Partial / Overdue / Pending approval / Paid / Void; no Vietnamese leftovers. | 12 §8 | Fixtures below | Not run |
Trường Số (truongso.net) · FLYER internal