AstroBaaS

Checkout & payments

Tuition Payment Plans (Education)

Paid pluginsize Mplanned, not built

Indicative price, not an offer: €24/mo + 1% per plan; installment tracking, non-payment alerts

Generated from docs/plan/paid/tuition-payment-plans/PLAN.md in the AstroBaaS repository. Nothing described below is implemented — it is the written plan for it.

Educational institutions need flexible payment plans so families can pay tuition across semesters. This paid module enables installment schedules tied to academic dates, tracks missed payments, and automates dunning tied to enrollment status.

The problem

Families can’t pay €4,000 tuition upfront; we lose enrollment. We have no way to split payments across three installments without manual invoicing, and when a payment is missed, there’s no automated reminder or hold on the student’s enrollment.

What it does

  • Define payment plan templates: 3-installment, 6-monthly, semester-aligned, with configurable start dates and due dates
  • Create a payment plan order type (distinct from regular orders) with multiple due dates and amounts
  • Link student ID to plan; hold access to coursework portal until payment is made
  • Track each installment: due date, amount due, payment received, days overdue
  • Automated reminders: 14 days before due, on due date, +7 days overdue, +14 overdue
  • Proration: allow mid-semester start; adjust installment schedule and total due
  • Partial-payment ledger: show payment schedule with running balance
  • Integration hooks: fire ‘payment_missed’ event when installment becomes 30+ days overdue (storefront can revoke enrollment)

What it deliberately does NOT do

Each boundary carries its reason. A boundary without a reason gets crossed by the next person who reads this.

  • Academic calendar management — merchant defines term start/end dates manually. Calendar integration is a separate product for schools that use Blackboard/Canvas.
  • Refund policies or late withdrawal accounting — the module tracks money; refund rules are institution-specific and belong to policy configuration, not core.
  • Scholarship/financial-aid offsets — module has no knowledge of aid. Merchant must apply credits manually before plan creation.
  • Regional tax/reporting requirements — education VAT is complex and VAT-registration-dependent. Tax is always left to the merchant’s accounting layer.

Data model

Add plan_type to Order: ‘immediate’ | ‘installment_3’ | ‘installment_6’ | ‘semester_aligned’. Add payment_schedule array: [ { due_date, amount_cents, paid_cents, paid_date } ]. Add student_id (string, optional) to Customer to link enrollment. Add plan_metadata object: { term_start, term_end, academic_year, cohort }. No new collection; all data lives on Order.

API

  • POST /api/payment-plans/templates — create installment schedule template (admin only)
  • GET /api/payment-plans/templates — list templates
  • POST /api/orders?plan_type=semester_aligned — create order with payment plan
  • GET /api/orders/{id}/schedule — fetch payment plan with current status
  • POST /api/orders/{id}/schedule/payment — record manual payment against specific installment
  • POST /api/payment-plans/dunning/{order_id} — trigger dunning for overdue installment (admin only, auto-triggered at +14 days)
  • GET /api/reports/payment-plans?overdue=true — list all overdue payment plans

Every route added here must also appear in src/pages/openapi.json.ts — a test fails the build if it does not.

Admin

New ‘Tuition & Payment Plans’ dashboard shows active plans, upcoming due dates, and overdue installments. Merchant can define plan templates (3 installments on specific dates, or ‘every 30 days for 6 months’). Order creation screen offers ‘Installment Plan’ checkbox; if checked, merchant chooses a template or creates custom dates. Dunning log shows automated reminders and manual overrides.

The seam — why this is paid

Core owns the Order model and webhook system. Paid module owns payment schedule logic, installment validation, and dunning automation. Enrollment hold is merchant’s responsibility — module fires the ‘payment_missed’ event, and storefront checks it before granting access. The ‘payment_schedule’ array is frozen at order creation; proration happens at that point, not retroactively.

Support commitment: dunning, payment-plan math (proration), student deferment rules

Dependencies

  • payment-status-tracking — must distinguish paid vs. pending per installment
  • b2b-payment-terms-deposits — shares dunning logic and partial-payment ledger

Acceptance checks

Each of these must be able to fail. Before claiming this is done, break the code deliberately and watch each one go red.

  • Merchant creates a ‘Semester Spring’ template: 3 equal installments on Jan 15, Mar 1, May 1
  • Order created with that template; payment_schedule shows three €1,333.33 dues
  • Jan 15 due date arrives; no payment made; first dunning reminder sent automatically on Jan 29
  • Payment of €1,333.33 recorded on Feb 10; first installment marked paid; second installment now active (due Mar 1)
  • Mar 1 arrives unpaid; second dunning fires automatically; ‘payment_missed’ event is published to webhooks
  • Merchant manually records €1,333.33 payment on Mar 5; second installment marked paid
  • Custom plan: merchant creates 6-month plan starting mid-semester (Feb 15) for €600/month; total adjusts to €3,600 (6 months), first due Feb 15
  • Partial payment: €800 on first €1,333.33 installment; ledger shows €533.33 remaining on that line, next installment not unlocked until first is paid in full

Risks

Proration math must handle partial months without rounding errors that leave a remainder — sum of installments must always equal order total, and this requires careful rounding (banker’s rounding or round-to-nearest-penny, not floor). If dunning is triggered before payment webhook arrives, the same event fires twice — webhook and dunning cron must both be idempotent and use the same payment source-of-truth. Enrollment hold depends on storefront checking the ‘payment_missed’ event; if storefront ignores it, students access courses without payment (integration is the merchant’s responsibility, not the module’s).

Commercial context

Suggested price€24/mo + 1% per plan; installment tracking, non-payment alerts
Rival anchorStripe Billing: free (setup); Affirm: per-transaction; custom: €2000+

The anchor is what the nearest equivalent charges on Shopify or Magento today. It is context for a pricing decision, not the decision.


Generated from the commerce plan. See docs/COMMERCE-PLAN.md for the full catalogue and ../../AI-GUIDE.md for how to work on this repository.