Invoices

The Invoices module handles the full billing lifecycle — from creating an invoice through to payment reconciliation. Invoices can be paid manually or via Stripe online payments. Overdue and recurring invoices are managed automatically by scheduled cron jobs.


Creating an Invoice

  1. Navigate to Invoices in the left sidebar.
  2. Click + New Invoice.
  3. Fill in the invoice form:
Field Required Notes
Client Yes Select from existing client records
Invoice Number Auto Generated automatically; can be overridden
Issue Date Yes Defaults to today
Due Date Yes Payment deadline
Notes / Payment Terms No e.g. "Payment due within 30 days of issue"
  1. Click Create Invoice to save the draft and open the line items editor.

Adding line items

Field Required Notes
Description Yes Service or deliverable name
Quantity Yes Number of units
Unit Price Yes Price per unit in display currency

The subtotal (subtotal_cents in the database) is calculated as the sum of all line item totals.

ℹ️
Amounts are stored in cents

Internally, all monetary amounts are stored in cents (e.g. £1,500.00 is stored as 150000). The UI handles this conversion automatically — always enter amounts in your display currency.


Sending an Invoice

Once the invoice is ready:

  1. Open the invoice.
  2. Review all line items and the total.
  3. Click Send Invoice.
  4. Confirm the recipient email.
  5. Click Send.

What happens:

  • The invoice status changes from draft to sent.
  • The client receives an email via Resend with a link to view the invoice in their portal.
  • The invoice shows a Pay Now button if Stripe is configured.

Marking an Invoice as Paid (Manual)

If a client pays by bank transfer, cheque, or another method outside Stripe:

  1. Open the invoice.
  2. Click Mark as Paid.
  3. Optionally enter a payment reference or note.
  4. Click Confirm.

The invoice status changes to paid and the payment date is recorded.


Stripe Integration

When Stripe is configured (see Settings), clients can pay invoices online.

How it works

  1. The client opens the invoice in their portal and clicks Pay Now.
  2. They are redirected to a Stripe Checkout page for secure card payment.
  3. On successful payment, Stripe sends a payment_intent.succeeded webhook to the CRM.
  4. The webhook handler automatically marks the invoice as paid and records the payment timestamp.

Stripe webhook

The webhook endpoint is: /api/webhooks/stripe

The STRIPE_WEBHOOK_SECRET environment variable validates that events are genuinely from Stripe. This is configured in Vercel and does not require any manual setup.

⚠️
Do not mark Stripe-paid invoices as paid manually

If a client has paid via Stripe, the webhook will mark it paid automatically within seconds. Manually marking it paid before the webhook fires can cause duplicate payment records. Wait for the webhook, or check Stripe dashboard to confirm payment before acting.


Overdue Invoices

The CRM runs a cron job daily at 02:00 UTC to identify overdue invoices.

What the cron does

  1. Queries all invoices in sent status where due_date < today.
  2. Updates their status to overdue.
  3. Sends a reminder email to the client.
  4. Sends an admin notification.
ℹ️
Cron endpoint

The overdue cron runs at /api/admin/appointments/cron and is protected by the CRON_SECRET environment variable. It is triggered by Vercel Cron — no manual action is needed.

Manual overdue handling

If you want to flag an invoice as overdue before the cron runs:

  1. Open the invoice.
  2. Click the Actions menu.
  3. Select Mark as Overdue.
  4. Optionally send a manual reminder email from the same menu.

Recurring Invoices

Invoices can be set to recur automatically at a defined interval. The cron runs daily at 03:00 UTC to generate due recurring invoices.

Setting up a recurring invoice

  1. Create or open an invoice.
  2. In the invoice settings, enable Recurring.
  3. Select the interval:
Interval Description
monthly New invoice generated each month on the same date
quarterly New invoice generated every 3 months
annual New invoice generated once a year
  1. Save the invoice.

How recurring invoices work

When the cron fires:

  1. It identifies recurring invoices where the next generation date has passed.
  2. It creates a new invoice with the same client, line items, and settings.
  3. It sets the new invoice's issue date to today and calculates a new due date.
  4. The new invoice is created in draft status — you must send it manually, or enable Auto-Send in the recurring settings.
💡
Review recurring invoices

Even with auto-send enabled, check your recurring invoice list monthly to ensure the amounts and line items are still current. If your service rates change, update the source recurring invoice.


Downloading an Invoice PDF

  1. Open the invoice.
  2. Click Download PDF.
  3. A PDF is generated with your company branding, client details, line items, and payment instructions.
ℹ️
PDF branding

The PDF uses the company name, logo, and address configured in Settings → Company Info. Ensure these are up to date before sending invoices.


Invoice Statuses

Status Meaning
draft Created but not yet sent to the client
sent Delivered to the client; payment not yet received
paid Payment received (manual or Stripe)
overdue Due date has passed without payment