Invoices & payments
How invoices are generated and renewed, where to find invoice and payment records, and what the client sees.
Invoices & payments
Agreements define the deal; invoices and payments are the paper trail. This page explains how invoices are created, how renewals work, and where to look when a client says "I paid".
- Invoices:
/super-admin/billing/commercial-invoices - Payments:
/super-admin/billing/commercial-payments - Client side:
/admin/billing/invoicesand/admin/billing/payments
Who this is for
Super Admins and support staff answering billing questions.
- Difficulty: Medium
- Time: 10 min
- Prerequisites: At least one active agreement.
How invoices appear
Renewal invoices — automatic, daily at 06:30
For every Active agreement whose next billing date has arrived, the renewal job:
- Creates the renewal invoice for the agreement's recurring gross amount (one-time line items are never re-billed).
- Issues it and advances the next billing date in the same database transaction — this is the idempotency anchor, so a job re-run cannot double-bill.
- Generates the invoice PDF and notifies the client.
The amount invariant The provider debit, the renewal invoice and the agreement's recurring gross amount are always the same number. If you ever see them disagree, stop and investigate — that is a reconciliation bug, not a rounding quirk.
Manual invoices and manual payments
Offline arrangements are recorded, not emailed: use Record Manual Payment on the agreement (amount, method, reference/UTR, date, apply-to-invoice, notes). This is the correct way to log a bank transfer.
Overdue marking — hourly
The payment-failure job scans issued and partially-paid invoices whose due date has passed with an amount still due, notifies the client once (no duplicate spam), and marks the invoice Overdue.
Step 1 — Read the invoice list
/super-admin/billing/commercial-invoices is an append-only list. Columns: invoice number, business, status, total, paid, due, issue date, due date, overdue flag, currency.
Internal invoice statuses: DRAFT, ISSUED, PAID, PARTIALLY_PAID, OVERDUE, VOID, CANCELLED. Draft and void invoices never reach the client.
Step 2 — Read the payments list
/super-admin/billing/commercial-payments shows every transaction: ID, business, provider, amount, status, method, provider reference, paid time.
Payment statuses: PENDING, AUTHORIZED, SUCCESS, FAILED, REFUNDED, PARTIALLY_REFUNDED.
Most payment rows are written by provider webhooks — each event is stored idempotently (unique provider + event ID) before processing, so webhook retries cannot double-count.
Step 3 — Investigate "I paid but it shows unpaid"
- Find the payment in the payments list (search by reference, provider or amount).
- If a successful payment exists but the invoice is open, the webhook may have arrived before the invoice or failed to match — check the agreement's Events and Timeline tabs.
- If no payment exists, the payment likely failed at the provider. The platform's reconciliation job (
ReconcileProviderStatus, every 30 minutes) pulls provider status and raises reconciliation alerts when records disagree — check the Payments area for alerts. - If the client paid outside the provider (bank transfer), record it manually as above.
Step 4 — Know what the client sees
In the client portal:
/admin/billing/invoices— their invoices with plain statuses: Paid / Due / Partially paid / Overdue. Draft and void invoices are invisible.- Downloads use signed URLs — safe to share from within the portal.
/admin/billing/payments— their payment history.
Expected result
Renewals appear as invoices on schedule, payments match invoices, and any mismatch surfaces through reconciliation alerts rather than a client complaint.
Common mistakes
- Re-running the renewal job expecting a second invoice. The transaction anchor prevents duplicates by design.
- Billing setup fees again at renewal. One-time line items are excluded from renewals.
- Recording a manual payment against the wrong invoice. Use "Apply to Invoice"; leave it open only when intentional.
- Deleting an invoice. Not possible — invoices are append-only; void or cancel instead.
- Treating FAILED webhook events as payments. Only captured/successful events move money.
Troubleshooting
| Symptom | What to check |
|---|---|
| Client got a renewal for the wrong amount | Agreement line items and recurring interval — the invoice mirrors the agreement |
| Invoice stuck in DRAFT | Draft invoices are not sent; issue it (or regenerate) through the agreement flow |
| Duplicate overdue reminders | Dedup is per invoice; check if multiple invoices are actually overdue |
| Payment succeeded at the provider but not here | Webhook delivery + reconciliation alerts; verify the provider secret |
| PDF download fails for the client | Signed URL expired — open the invoice from the portal again |
Technical details
- Pages:
App\Filament\SuperAdmin\Pages\Commercial\CommercialInvoicesandCommercialPayments(slugsbilling/commercial-invoices,billing/commercial-payments). - Models:
App\Models\BillingInvoice(tablebilling_invoices),App\Models\PaymentTransaction,App\Models\BillingReconciliationAlert. - Renewal job:
App\Jobs\Billing\CreateRenewalInvoice— daily 06:30, no-overlap 30 min; creates + issues + advancesnext_billing_date(viaBillingCalculator::addInterval) inside one transaction, then dispatchesGenerateInvoicePDFandBillingNotifier::invoiceCreated. - Overdue job:
App\Jobs\Billing\CheckPaymentFailures— hourly, no-overlap 20 min. - Reconciliation:
ReconcileProviderStatusevery 30 minutes;SyncAppliedChangeRequestsevery 30 minutes. - Webhooks:
/api/webhooks/razorpay,/api/webhooks/cashfree— signature-verified, idempotent events.
Related guides
Was this page helpful?
Thanks — noted. ✦