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
Cases
67
P0 / P1
23 / 30
Regression pack
26
PRD
05 Tuition and finance
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
23
P1
30
P2
14
P3
0
Typefunctionalui-uxedgenegativeregressionflowa11yperfsecurityi18n
Count43168001062

2Test cases

IDTitleTypePriorityPhasePreconditionsStepsExpected resultPRD traceData neededRun 1
TS-FIN-001Add fee plans of each type to a coursefunctionalP0P1As U-ACC on /settings/fee-plans.
  1. On course Movers 2 add: one_time "Trọn khoá" 9,600,000 with 2 instalments (50% now, 50% after 30 days); monthly 1,200,000; session_package 24 sessions 6,000,000 validity 6 months; material "Sách" 180,000 VAT 5.
  2. Open the conversion wizard step 3 and the enrollment form for a Movers 2 class.
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-01Fixtures belowNot run
TS-FIN-002Fee plan validationnegativeP1P1Fee plan form.
  1. Price -1; package sessions 0; validity 0; VAT 11; instalment pcts summing to 90.
Each rejected inline; VAT range 0–10; instalments must sum to 100.FIN-01, 05 §5 formFixtures belowNot run
TS-FIN-003Default VAT per type: fee 0, material 5functionalP1P1New fee plan form.
  1. Choose type one_time then material.
VAT field defaults 0 then 5; editable; tenant defaults changeable in /settings/finance.05 §11 VATFixtures belowNot run
TS-FIN-004Create an invoice from a fee plan with QRfunctionalP0P1As U-ACC on /finance/tuition/new?student_id=<S3>.
  1. Student prefilled S3; line = FP1 qty 1; due date default today+7; Tài khoản nhận BA1; Gửi thông báo Zalo ticked.
  2. Save.
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-02Fixtures belowNot run
TS-FIN-005Invoice total formula with line discount, invoice discount and VATfunctionalP0P1Invoice form.
  1. Lines: FP1 9,600,000 line discount 100,000; MAT1 qty 2 unit 180,000 VAT 5%.
  2. Invoice discount 5%.
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 1Fixtures belowNot run
TS-FIN-006Discount above role limit sets pending approvalfunctionalP0P1As U-ACAD-A (limit 5%).
  1. Create an invoice with 10% discount, reason "Anh chị em".
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-02Fixtures belowNot run
TS-FIN-007Approve and reject a pending invoicefunctionalP0P1INV-5 pending; as U-BM-A.
  1. Open INV-5; click Duyệt.
  2. On another pending invoice click Từ chối with note.
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/rejectFixtures belowNot run
TS-FIN-008Accountant cannot approve discountssecurityP1P1As U-ACC on INV-5.
  1. Look for Duyệt; call POST /tuitions/{id}/approve.
Button absent; 403.05 §9 finance.discount.approveFixtures belowNot run
TS-FIN-009Invoice form validationnegativeP1P1Invoice form.
  1. No lines; unit price -1; VAT 12; due date empty; instalments summing less than total; no receiving account.
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 formFixtures belowNot run
TS-FIN-010Session package credits on full payment by defaultfunctionalP0P1S3 invoice FP3 unpaid; credit_on_create off.
  1. Check S3 balance after creating the invoice.
  2. Record full payment.
Before payment balance 0 (package pending); after payment balance 24 with expiry = today + 6 months, status active.FIN-02 Then, 05 §6 rule 4Fixtures belowNot run
TS-FIN-011Tenant setting credits on creationfunctionalP1P1credit_on_create on.
  1. Create an FP3 invoice for S3.
Balance 24 immediately; package status active with expiry from credit date.05 §6 rule 4Fixtures belowNot run
TS-FIN-012Voucher applied at invoice creationfunctionalP2P2Voucher group "BACK2SCHOOL" 10%, valid, applicable to Movers 2.
  1. Enter voucher code on the FP1 invoice.
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-09Fixtures belowNot run
TS-FIN-013Voucher not stackable with percent discount unless flaggednegativeP2P2Voucher and 5% discount on the same invoice.
  1. Save.
Error "Không kết hợp mã giảm giá với giảm giá %" unless the group is stackable.05 §6 rule 7Fixtures belowNot run
TS-FIN-014Invoice list KPI tiles and tabsfunctionalP0P1As U-ACC, branch A.
  1. Open /finance/tuition.
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 belowNot run
TS-FIN-015Invoice list columns and formattingui-uxP1P1/finance/tuition.
  1. Read columns for INV-3.
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 columnsFixtures belowNot run
TS-FIN-016Invoice list filters and searchfunctionalP1P1/finance/tuition.
  1. Filter fee plan type Gói buổi; search "TS1A0001"; search "Nguyễn An".
Each narrows correctly; payment code search finds INV-1.05 §5 filtersFixtures belowNot run
TS-FIN-017Invoice detail sections and buttonsfunctionalP1P1INV-4 (paid).
  1. Open /finance/tuition/<INV-4>.
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 detailFixtures belowNot run
TS-FIN-018Void an invoice only without paymentsfunctionalP1P1INV-1 (no payments) and INV-2 (partial).
  1. Huỷ INV-1 with reason.
  2. Try Huỷ on INV-2.
INV-1 status Đã huỷ, excluded from KPI tiles; INV-2 Huỷ disabled and API 409.05 §8 void only when no valid paymentsFixtures belowNot run
TS-FIN-019Bulk monthly billing preview and commit with prorationfunctionalP0P1As 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.
  1. Click Lập hoá đơn tháng; select C3; month next month; prorate on; channels Zalo.
  2. Read the preview; commit.
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-03Fixtures belowNot run
TS-FIN-020Billing run dry_run does not writefunctionalP1P1Preview open.
  1. Cancel at preview.
No invoices created (list unchanged); network shows dry_run=true only.05 §8 group-invoices dry_runFixtures belowNot run
TS-FIN-021Record a cash payment and issue a numbered receiptfunctionalP0P1INV-1 unpaid; as U-ACC.
  1. Click Thu tiền: amount default 9,600,000; method Tiền mặt; account CD-A; payer "Trần Thị Hoa"; date now; Gửi biên lai Zalo on.
  2. Confirm.
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-04Fixtures belowNot run
TS-FIN-022Partial cash paymentfunctionalP0P1INV-1 unpaid.
  1. Thu tiền 4,000,000.
Status Thanh toán một phần; Còn lại 5,600,000; receipt issued for 4,000,000.FIN-04 partialFixtures belowNot run
TS-FIN-023Overpayment refusednegativeP0P1INV-2 remaining 700,000.
  1. Thu tiền 800,000.
Inline error "Vượt số còn lại (700.000 đ)"; API 400/409; no payment.05 §6 rule 2Fixtures belowNot run
TS-FIN-024Payment date cannot be in the futurenegativeP1P1Payment dialog.
  1. Set date tomorrow.
Rejected "Không được chọn ngày tương lai".05 §5 payment dialogFixtures belowNot run
TS-FIN-025Receipt numbering is sequential under concurrencyedgeP0P1Two cashiers (U-ACC in two sessions).
  1. Record two cash payments at the same second on different invoices at branch A.
Numbers are consecutive and unique (e.g. 0003 and 0004); no duplicate; no gap.05 §6 rule 3, test seed 05Fixtures belowNot run
TS-FIN-026Receipt numbering per branch per monthfunctionalP1P1Branch B payment.
  1. Record a cash payment at branch B; next month record another at A.
B receipt PT-TD-<YYYYMM>-0001; A next month restarts at 0001.05 §6 rule 3Fixtures belowNot run
TS-FIN-027Void a payment keeps the number and requires reasonfunctionalP0P1Payment PT-Q1-...-0002.
  1. Click Huỷ phiếu on the payment; enter reason.
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 voidFixtures belowNot run
TS-FIN-028Card payment methodfunctionalP2P1Payment dialog.
  1. Choose Thẻ; record.
Payment method CARD stored; receipt issued; appears in cash book under the chosen account.05 §8 method CARDFixtures belowNot run
TS-FIN-029Receipt PDF signed URLsecurityP1P1A payment.
  1. Open GET /payments/{id}/receipt.pdf link; tamper the signature.
Valid link serves the PDF; tampered link 403; link expires after 15 min.05 §8 receipt.pdf signed, 12 §3Fixtures belowNot run
TS-FIN-030Accountant vs academic admin payment permissionsecurityP1P1As U-ACAD-A without cash grant.
  1. Look for Thu tiền on INV-1; call pay.
Button absent; 403; with the grant enabled by owner, cash only (bank/card methods hidden).05 §9 finance.payment.createFixtures belowNot run
TS-FIN-031SePay transfer with payment code auto-matchesfunctionalP0P1INV-1 unpaid, code TS1A0001; SEPAY stub.
  1. POST the stub with amount 9,600,000, description "TS1A0001 hoc phi", id sp-001.
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-05Fixtures belowNot run
TS-FIN-032Transfer without code lands in Chưa đối soátfunctionalP0P1SEPAY stub.
  1. POST amount 1,200,000 description "hoc phi be Binh" id sp-002.
  2. Open /finance/cashbook tab Chưa đối soát.
Row sp-002 with amount, description, received time and action "Gán vào hoá đơn"; no payment created yet.FIN-05Fixtures belowNot run
TS-FIN-033Manual match of an unmatched transfer to an invoicefunctionalP0P1sp-002 unmatched; INV-2 remaining 700,000.
  1. Gán vào hoá đơn → INV-2 for 700,000 and the rest 500,000 to student credit.
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 creditFixtures belowNot run
TS-FIN-034Partial transfer amount accepted as partial paymentfunctionalP1P1INV-1 code; transfer 5,000,000 with code.
  1. POST the stub.
Payment 5,000,000; invoice partial.FIN-05 partial amountsFixtures belowNot run
TS-FIN-035Duplicate SePay webhook dedupededgeP0P1sp-001 already processed.
  1. POST the identical webhook again.
No second payment; invoice not overpaid; log shows deduped on sepay_transaction_id.05 §11 dedupeFixtures belowNot run
TS-FIN-036One transfer for two children splitfunctionalP1P1Unmatched 2,400,000; INV for S1 and S2 each 1,200,000.
  1. Gán vào hoá đơn with split across both invoices.
Two payments created, both invoices paid, one SePay id referenced on both.05 §11 splitFixtures belowNot run
TS-FIN-037Debt list aging buckets and columnsfunctionalP0P1As U-ACC on /finance/debt.
  1. Open the page.
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-06Fixtures belowNot run
TS-FIN-038Send reminder in bulk with templatefunctionalP1P1Debt list.
  1. Select S7 and another debtor; bulk Gửi nhắc; pick template fee_reminder; send.
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_idFixtures belowNot run
TS-FIN-039Set a payment planfunctionalP1P1S7 INV-3.
  1. Kế hoạch trả: 2 parts 1,500,000 on two dates.
Plan saved; invoice detail shows parts; sum must equal remaining (validation).05 §8 payment-planFixtures belowNot run
TS-FIN-040Debt reconciliation with invoice listfunctionalP0P1Debt list totals.
  1. Sum "Còn lại" of overdue invoices in /finance/tuition tab Quá hạn.
Equals the sum of debt tiles for the same branch.REP-02 style reconciliationFixtures belowNot run
TS-FIN-041Package consumption FIFO by expiry and low-balance alert at 3functionalP0P1S1 with two packages: 2 sessions expiring next month, 3 sessions expiring in 6 months (balance 5).
  1. Mark S1 present on two sessions.
  2. Mark a third.
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-07Fixtures belowNot run
TS-FIN-042Balance 0 shows Hết buổi and red chip on rosterfunctionalP1P1S6 balance 2.
  1. Consume two sessions.
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-07Fixtures belowNot run
TS-FIN-043Consumption from an expired package refusednegativeP1P1Package expired yesterday with 3 sessions.
  1. Mark present.
Consumption refused; student shows "Hết hạn gói"; attendance still saved.05 §6 rule 5Fixtures belowNot run
TS-FIN-044Pause freezes expiryfunctionalP1P1S1 package expiry E; pause 30 days; resume.
  1. Perform pause and resume.
Expiry E + 30; frozen_days 30 on the package.FIN-07 pause freezesFixtures belowNot run
TS-FIN-045Manual package adjustment requires approvalfunctionalP2P1As U-ACC.
  1. POST /packages/{id}/adjust +2 reason "Bù lỗi".
Adjustment pending until U-BM-A approves; then balance +2; audit.05 §8 adjust approvalFixtures belowNot run
TS-FIN-046Refund estimate on withdrawalfunctionalP1P1S1 5 sessions unused, unit 250,000, admin fee 10%.
  1. GET /refund-estimate?student_id=S1.
Proposal 1,125,000 (5×250,000 − 10%) with breakdown; editable with reason.FIN-08Fixtures belowNot run
TS-FIN-047Credit note and refund with approval thresholdfunctionalP0P2S1 withdrawn; as U-ACC; threshold 5,000,000.
  1. Create credit note 1,125,000 on INV-1 (paid); create refund cash from CD-A to "Trần Thị Hoa".
  2. Repeat with 6,000,000 on another invoice.
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-08Fixtures belowNot run
TS-FIN-048Credit note boundsnegativeP1P2INV-1 total 9,600,000 with an existing credit 1,000,000.
  1. Create credit 9,000,000.
  2. Refund 9,600,000 when paid 4,000,000.
Both refused: "Vượt tổng hoá đơn trừ phiếu giảm" / "Vượt số đã thu".05 §6 rule 8Fixtures belowNot run
TS-FIN-049Create an expense and see it in the cash bookfunctionalP1P2As U-ACC on /finance/cashbook.
  1. + Phiếu chi: category Điện nước, 1,500,000, payee EVN, account CD-A, today, attachment.
Row PC-Q1-<YYYYMM>-0001 type Chi; totals update; attachment link signed.FIN-10Fixtures belowNot run
TS-FIN-050Expense above threshold needs approvalfunctionalP2P2Threshold 5,000,000.
  1. Create an expense 6,000,000.
Status pending; U-BM-A approve; only then counted in Chi phí tiles.FIN-10Fixtures belowNot run
TS-FIN-051Daily cash close with differencefunctionalP1P2CD-A with today's cash payments 9,600,000 and expense 1,500,000.
  1. Chốt quỹ ngày: counted 8,000,000; note.
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 10Fixtures belowNot run
TS-FIN-052Void after cash close still allowed, edit blockededgeP2P2Closed day.
  1. Try to edit payer name on a closed-day payment; void it.
Edit blocked; void allowed with reason and audit.05 §6 rule 10Fixtures belowNot run
TS-FIN-053Cash book filters and exportfunctionalP2P2/finance/cashbook.
  1. Filter account CD-A, type Thu, date range; Xuất Excel.
Rows filtered; xlsx matches; columns date, code, type, category, counterparty, in, out, account, created by, attachment.05 §5 Thu chiFixtures belowNot run
TS-FIN-054E-invoice issue success and failurefunctionalP2P2Provider stub; INV-4 paid.
  1. Xuất HĐĐT with buyer details (success mode).
  2. Repeat in failure mode.
Success: number and lookup code stored, PDF link shown. Failure: provider message displayed with Thử lại; nothing stored.FIN-11Fixtures belowNot run
TS-FIN-055Finance report tiles and reconciliationfunctionalP0P1As U-OWNER, this month, branch A.
  1. Open Báo cáo tài chính.
  2. Compare Thực thu with the cash book total type Thu for the same range; compare Đã lập with the invoice list created-in-period total excluding void.
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-02Fixtures belowNot run
TS-FIN-056Report drill-down to invoices and exportfunctionalP1P1Finance report.
  1. Click billed tile; click Xuất Excel.
Lands on /finance/tuition with the period filter applied; xlsx downloads.FIN-12Fixtures belowNot run
TS-FIN-057Finance report scope by rolesecurityP1P1U-BM-A and U-ACAD-A.
  1. Open /reports finance as each.
U-BM-A sees branch A only; U-ACAD-A has no finance report (403 / hidden).05 §9 finance.reportFixtures belowNot run
TS-FIN-058Every money write is audited with before/aftersecurityP0P1Perform: create invoice, pay, void payment, discount approve.
  1. Open /settings/audit-log filtered by entity tuition/payment.
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 §6Fixtures belowNot run
TS-FIN-059Idempotency-Key on pay prevents double paymentedgeP1P1INV-1.
  1. Send POST pay twice with the same Idempotency-Key.
One payment; second response returns the same payment; no second receipt number.11 §1 idempotencyFixtures belowNot run
TS-FIN-060Parent sees only own invoicessecurityP1P2G1.
  1. GET /v3/parent/tuitions; GET /v3/parent/tuitions/<INV-3>.
Lists INV-1/INV-2 (children S1, S2); INV-3 (S7) → 404.05 §9 parent own childrenFixtures belowNot run
TS-FIN-061Money formatting vi and eni18nP1P1Invoice list in vi then en.
  1. Read 9,600,000 in both locales.
vi "9.600.000 đ"; en "9,600,000 đ" (or "VND 9,600,000" consistently across the app); no decimals.12 §8 moneyFixtures belowNot run
TS-FIN-062Currency locked to VNDnegativeP2P1Course with currency USD in the stub.
  1. Open the fee plan form for it.
Warning "Chỉ hỗ trợ VND"; plan creation blocked until currency VND.05 §11 currencyFixtures belowNot run
TS-FIN-063Instalment invoice: partial pay then withdrawedgeP2P2Two-part instalment, first part paid.
  1. Withdraw the student; open refund estimate.
Credit note proposed on the unpaid second instalment; refund limited to the paid portion minus consumed value.05 §11 instalmentFixtures belowNot run
TS-FIN-064Sibling discount reason and automatic percentfunctionalP2P1Tenant sibling percent 5%; G1 has S1 and S2.
  1. Create an invoice for S2 in the wizard/form.
Discount 5% prefilled with reason "Anh chị em"; editable.05 §11 siblingFixtures belowNot run
TS-FIN-065Package moves with the student on branch transfer; revenue staysedgeP2P1S1 transferred to B with 5 sessions.
  1. Open finance report for A and B.
A revenue unchanged; deferred revenue for the 5 sessions moves to B with an inter-branch note.05 §11 package transferFixtures belowNot run
TS-FIN-066Invoice form keyboard: add line, remove line, submita11yP2P1Invoice form.
  1. Use Tab/Enter to add a line and remove it; submit with Enter in the last field.
All actions reachable; focus returns to a sensible element after removal; totals update live.12 §9Fixtures belowNot run
TS-FIN-067Finance pages in en localei18nP2P1en.
  1. Open tuition list, debt, cashbook.
Tabs Unpaid / Partial / Overdue / Pending approval / Paid / Void; no Vietnamese leftovers.12 §8Fixtures belowNot run

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