Payment Plans & Installments

Payment plans allow clients to pay invoices in scheduled installments rather than a single lump sum. NexusRMS automatically generates installment schedules, tracks payment progress, handles late fees, and supports digital agreement signing for a complete payment plan lifecycle.

Creating a payment plan

Navigate to Financial > Invoices, open an invoice, and select Create Payment Plan from the actions menu. The form fields are:

  • Invoice (required) — The invoice being split into installments. The client is inherited automatically.
  • Total Amount — Defaults to the invoice total. This is the full amount to be collected across all installments.
  • Deposit Amount — An optional upfront deposit collected before the installment schedule begins. The deposit is subtracted from the total before dividing into installments.
  • Number of Installments (required) — How many equal payments the remaining balance is divided into
  • Frequency (required) — How often installments are due: weekly, fortnightly, monthly, quarterly, or custom
  • Start Date (required) — When the payment plan begins
  • End Date — Expected completion date, calculated automatically from the number of installments and frequency
  • First Payment Date (required) — Due date of the first installment
  • Late Fee Percentage — Percentage charged on overdue installments
  • Late Fee Amount — Fixed monetary amount charged on overdue installments
  • Terms — Terms and conditions for the payment plan agreement
  • Notes — Internal notes visible only to staff

The plan_number is auto-generated in the format PP-YYYY-#### (e.g., PP-2026-0001), incrementing from the last plan created in the current year.

Automatic installment generation

When a payment plan is created, the generateInstallments() method automatically creates all PaymentPlanInstallment records. The system calculates each installment amount by subtracting the deposit from the total and dividing equally across the number of installments. Due dates are spaced according to the selected frequency:

  • weekly — Each installment due 7 days after the previous
  • fortnightly — Each installment due 14 days after the previous
  • monthly — Each installment due one calendar month after the previous
  • quarterly — Each installment due three calendar months after the previous
  • custom — Defaults to monthly spacing; individual due dates can be adjusted manually after creation

Payment plan statuses

A payment plan progresses through the following statuses:

  1. active — The plan is in progress and accepting payments. This is the initial status on creation.
  2. completed — All installments have been paid and amount_remaining has reached zero. The completed_at timestamp is recorded automatically.
  3. suspended — The plan has been temporarily paused via suspend(). No installments are collected while suspended. Use reactivate() to resume.
  4. defaulted — The client has failed to pay and the plan is in default. This is triggered automatically after three or more consecutive failed payment attempts on an installment, or can be set manually via markAsDefaulted().
  5. cancelled — The plan has been permanently cancelled via cancel(reason, cancelledBy). The cancelled_at timestamp, cancellation_reason, and cancelled_by fields are recorded.

Installment tracking

Each PaymentPlanInstallment record tracks individual payment progress with the following fields:

  • installment_number — Sequence number (1, 2, 3, etc.), ordered automatically
  • status — One of seven statuses: pending (not yet due), due (due date is today), paid (fully paid), overdue (past due date), partial (partially paid), failed (payment attempt failed), waived (forgiven without payment)
  • amount_due — Original amount due for this installment
  • amount_paid — Amount actually received so far
  • late_fee — Late fee charged on this installment
  • total_due — Amount due plus any late fees (amount_due + late_fee)
  • due_date — When this installment is due
  • paid_date — When the installment was fully paid
  • days_overdue — Number of days past the due date

Recording payments

Use the recordPayment(amount) method on an installment to record a payment. The method updates amount_paid and calculates the new status: if the remaining balance reaches zero, the status changes to paid with the paid_date set; if a partial amount is received, the status changes to partial. The parent payment plan's totals are automatically updated via the plan's recordInstallmentPayment(amount) method, which recalculates amount_paid, amount_remaining, installments_paid, and transitions the plan to completed if the full balance has been collected.

Late fees

The calculateLateFee() method on each installment checks whether the installment is overdue and applies late fees from the parent plan:

  • If the plan's late_fee_percentage is greater than zero, the percentage is applied to the installment's amount_due
  • If the plan's late_fee_amount is greater than zero, the flat amount is added on top
  • The installment's late_fee and total_due fields are updated accordingly

Late fees are recalculated by the updateOverdueStatus() method, which also transitions the installment status to overdue and records days_overdue.

Failed payments and defaulting

When a payment attempt fails, call markAsFailed(reason) on the installment. This increments payment_attempts, records last_payment_attempt_at and payment_failure_reason, and sets the status to failed. If the installment reaches three or more failed attempts, the parent payment plan is automatically marked as defaulted via markAsDefaulted().

Waiving installments

Use the waive() method to forgive an installment without requiring actual payment. This sets the status to waived, records amount_paid equal to total_due, and updates the parent plan's totals as though the payment were received. Waiving is useful for goodwill gestures or when an installment amount is negligible.

Agreement signing

Payment plans support digital agreement signing for a formal record of the client's consent:

  • agreement_signed — Boolean indicating whether the client has signed
  • agreement_signed_at — Timestamp of the signature
  • agreement_signature_ip — IP address of the signer for audit purposes
  • agreement_signature_data — Base64-encoded signature image captured via the signing pad

Call signAgreement(signatureData, ipAddress) to record the digital signature. The agreement terms are stored in the terms field and presented to the client before signing.

Reminders

Each installment can send payment reminders via the sendReminder() method. This creates a PaymentReminder record linked to the installment through polymorphic association, updates the installment's reminder_sent_at and reminder_count fields, and dispatches the reminder for delivery. See the Payment Reminders article for details on reminder types and escalation.

Tips

  • Collect a deposit for high-value plans — Set the deposit_amount to secure an upfront payment before the installment schedule begins, reducing your financial risk.
  • Use monthly frequency for most plans — Monthly installments align with most business accounting cycles and are easiest for clients to budget for.
  • Monitor overdue installments regularly — Use getOverdueInstallments() or check the payment plan detail page to identify at-risk plans before they reach default status.
  • Suspend rather than cancel — If a client requests a temporary pause, use suspend() to preserve the plan and reactivate() to resume, rather than cancelling and creating a new plan.
  • Require agreement signing for large amounts — Digital signatures create a formal record of the client's consent to the payment schedule, protecting both parties in case of disputes.

Was this article helpful?