T6B SC-FEES / W10 Approved Product Contract¶
Decision date: 2026-08-17 Approver: requesting user (explicit approval of all 30 recommendations) Status: IMMUTABLE PRODUCT APPROVAL — ENGINEERING MAY ENTER T6B.1 Scope: SC-FEES V1 / W10 Billing and Payment only
This record authorizes engineering to implement the decisions below. It does not certify the existing Fees code, does not authorize demo/production promotion, and does not approve SC-FIN, gateway payment, accounting posting, CBT, Foundation, or other optional workflows.
Approved decisions¶
| # | Approved contract |
|---|---|
| 1 | SC-FEES owns fee products, rules, templates, and schedules. SC-FIN owns accounting, journals, and accounting reports. |
| 2 | Rules are effective-dated and versioned. Active rules are never edited in place; existing bills freeze their rule version and amount. |
| 3 | Only an active student with a valid same-company enrollment may be billed. Draft, withdrawn, rejected, archived, or foreign-tenant students are not billable. |
| 4 | Student, enrollment, batch, course, fee rule, bill, payment, journal, and payment method must belong to the active company. Mixed-company foreign keys fail atomically. |
| 5 | Maker-checker is mandatory. A creator cannot approve, verify, post, refund, or reverse their own object. Capabilities remain atomic: view, configure, receive_cash, verify, refund, and manage. |
| 6 | Billing balance is visible only to authorized billing viewers, treasurers, and explicitly entitled school administrators, subject to tenant scope and field projection. |
| 7 | Parents see only active linked children in the same company. Guessed IDs fail closed without existence disclosure. |
| 8 | Students see and pay only their own billing records. |
| 9 | Cashiers may record receipt and upload proof. Treasurers may verify. Cashiers cannot change fee rules or verify their own transactions. |
| 10 | School administrators may configure approved master data only. They do not automatically receive verify, refund, or accounting authority. |
| 11 | T6B V1 supports manual cash and bank transfer only. Midtrans/Xendit gateway payment is deferred to a separately approved tranche. |
| 12 | Manual cash/transfer requires amount, channel, reference, payer, timestamp, and required proof. Balance changes only after verification. |
| 13 | Gateway payment is excluded from T6B V1. A future gateway tranche must add provider signature, replay protection, reference uniqueness, timeout, and callback idempotency. |
| 14 | Proof accepts PDF/JPG/PNG up to 10 MB, requires antivirus scanning, private download, and default seven-year retention subject to DPO/Finance policy. |
| 15 | Durable idempotency is required for enrollment bill, bill creation, payment submission, verification, callback, receipt, refund, and reversal. Same key with different payload is rejected. |
| 16 | Timeout produces pending_reconciliation, never silent success. Retries are bounded; exhausted retries enter a recovery/dead-letter queue. |
| 17 | Overpayment is rejected by default. No automatic carry-forward or refund is performed. Approved correction uses the refund/credit workflow. |
| 18 | Partial payment is allowed. Remaining balance is computed server-side from immutable bill amount minus verified payments and approved corrections. |
| 19 | Refund/reversal is allowed only for verified/paid payments, requires a separate requester and approver, a reason, and an audit event. Payment records are never deleted. |
| 20 | Failed payment remains unpaid/pending and does not reduce balance. Retry is idempotent and cannot create a second bill. |
| 21 | Receipt is issued only after verified payment, is immutable, and is idempotent. One valid payment yields at most one receipt. |
| 22 | SC-FEES V1 must not call account.payment.register.sudo() or create hidden accounting journals. Fees payment state remains separate from accounting posting. |
| 23 | Accounting posting belongs to SC-FIN, not SC-FEES. Fees→Finance is a future separately entitled and certified bridge. |
| 24 | Basic discount/installment may be owned by SC-FEES. Complex scholarship policy is separate. Negative balances are rejected server-side. |
| 25 | Admission→Fees is optional. SC-FEES works standalone; the bridge activates only when both packages and entitlements are active. |
| 26 | Fees→Finance is excluded from T6B. No accounting/BOS surface may be exposed through SC-FEES. |
| 27 | Notification is best-effort and not the transaction source of truth. A committed financial transaction remains successful if notification fails; outbox retry and audit are required. |
| 28 | Audit records actor, acting role, tenant, action, object, before/after state, before/after amount, reason, idempotency key, timestamp, correlation ID, and failure detail. |
| 29 | Installed-but-unentitled and package-OFF fail closed at menu, route, API, service, ORM/RPC, and existing-session levels. Entitlement is re-evaluated for sensitive requests. |
| 30 | Native Odoo/OpenEduCat fees, account.move, account.payment.register, /web/dataset, legacy controllers, and public callbacks are not alternate lifecycles. They remain denied or are exposed only through a separately certified bridge. |
Tranche boundaries¶
T6B.1 — SC-FEES Core Billing¶
Implement fee rules, enrollment billing, manual cash/transfer, partial payment, receipt, tenant isolation, authorization, idempotency, and recovery.
T6B.2 — SC-ADM ↔ SC-FEES bridge¶
Implement only after standalone T6B.1 is green. Both package entitlements are required.
Deferred¶
Gateway payment is deferred to T6B.3. Accounting/journal posting and Fees→Finance are deferred to T6G/SC-FIN. Neither may be smuggled into T6B.1.
Approval effect¶
Engineering may now replace the blocked product gate with implementation work, but T6B remains uncertified until the complete topology, authorization, runtime, concurrency, recovery, Core-regression, and immutable-evidence gates pass an independent audit.