Skip to main content

14 — Payment Plans

What it is: Lets a fan pay for an order in installments over time instead of all at once. Two tables: a per-program plan definition (tbl_payment_plans) the admin configures, and the per-order installment schedule (tbl_payment_plan_installments) created when a fan checks out on a plan. See the narrative walkthrough in Chapter 26 — Payment Plans.


Tables

tbl_payment_plans — the plan definition

One row per configured plan, scoped to a program. This is what the admin sets up; it does not belong to any order.

FieldNotes
paymentPlanIdPK
programIdthe Flex program this plan belongs to
title / descriptionadmin-facing label (title ≤ 100 chars)
packIds / packageIdsJSONB arrays — which game-packs / preset-packages the plan applies to (null = not restricted by pack)
accountGroupIdsJSONB array — gate the plan to specific account groups (see Account Groups & Ledgers)
minEventCountmin events in the cart for the plan to be offered (nullable)
minTotalAmount / maxTotalAmountorder-total bounds for eligibility (nullable)
scheduleTypefixed or dynamic
scheduleConfigJSONB, discriminated by scheduleTypefixed: { dates: ['YYYY-MM-DD', …] }; dynamic: { cadence, intervalDays? } where cadencedaily · weekly · biweekly · monthly · monthly_first · monthly_last · every_n_days (every_n_days also needs intervalDays)
totalInstallments / endDatedynamic bounding — at least one is required when scheduleType = 'dynamic'
installmentAmountfixed per-installment amount (nullable — otherwise the total is split evenly)
firstInstallmentAmountoptional override for the first charge (e.g. a larger deposit)
daysPriorToChargecharge this many days before each due date (default 0)
isDynamicShrinkdefault true — whether the schedule recomputes if the order total changes
isActivedefault true — only active plans are offered
displayOrdersort order among plans (default 0)

tbl_payment_plan_installments — the per-order schedule

One row per scheduled charge, created at checkout when a fan picks a plan.

FieldNotes
installmentIdPK
orderIdFK to tbl_orders — the order being paid off
userIdthe fan
paymentPlanIdFK to the plan definition above
installmentNumber / totalInstallments"charge 2 of 4"
dueDatewhen this installment is due
amountscheduled amount
amountActuallyChargedwhat actually went through (nullable until charged)
statuspending · processing · charged · failed · cancelled (the first installment is charged at checkout; the rest start pending)
vendorInvoiceIdvendor reference for the charge (nullable)
chargedAttimestamp of the successful charge
attemptCount / lastAttemptAtretry tracking for failed charges
reminderSentAtwhen the upcoming-charge reminder was sent
lastFailureCode / lastFailureReason / failureHistoryfailure diagnostics (failureHistory is a JSONB log of attempts)

Key rules

  • A plan definition is per-program config; the installments are per-order and reference both the order and the plan.
  • Eligibility for a plan is decided by the cart: pack/package match, account group, event count, and order-total bounds must all pass.
  • The first installment is charged at checkout (status = charged); subsequent ones are scheduled pending and charged daysPriorToCharge days before their dueDate.
  • scheduleConfig shape depends on scheduleType — don't read dates on a dynamic plan or cadence on a fixed one.

See Also