Every invoice has a due_date set when it was issued (default: issue_date + net_terms, typically 30 days). At 6 AM each day, a Postgres cron job runs:
UPDATE invoices SET status='overdue'
WHERE status='sent' AND due_date < current_date; Three things happen automatically
- Status flips from
senttooverdue - A row lands in
notification_eventswithkind='invoice_overdue'targeting the client's billing-owner email - Within 60 seconds, the
send-notificationsdrainer reads that row and sends an email via Resend (subject: "Invoice #N is past due")
What your admin sees
- The invoice now appears in the Overdue tab in your Invoices view
- The outstanding-balance banner at the top of every page reflects it
- Optional weekly digest summarizes all overdue invoices (BACKLOG)
What the client sees
- If they have client-portal access, the invoice appears in their Overdue tab too
- The outstanding-balance banner at the top of THEIR portal reflects it
- They get the email notification we just sent
Marking it paid
Two paths:
- Manual — admin clicks "Mark Paid" on the invoice. Sets
amount_paid = total,paid_at = now(), status flips topaid. - QuickBooks webhook — if QBO is connected, when YOU record payment in QBO, Intuit fires a webhook back to TradelyHQ and we flip the status automatically.
Suppressing the auto-mark
If for some reason you want an invoice to stay sent even after the due date (e.g., you've granted an extension), check the "Don't auto-flag overdue" box on the invoice. The cron skips it.