Budget detail
Full view of one budget: header with patient info, a main column with the line items and totals, and a sidebar with actions, metadata, and the payments card contributed by the payments module. This is where the budget moves through draft → sent → accepted and gets signed, invoiced, or renegotiated.
At a glance
- Two-column layout. Left: budget line items with catalog item, tooth, surfaces, quantity, discount, and VAT. Right (top to bottom): payments card (slot
budget.detail.sidebar, filled bypayments), totals (subtotal, discount, VAT, total), info (number, version, validity, creator, linked plan). - Status chip in the header. Available actions depend on it.
- Versioning. Each renegotiation creates a new version linked via
parent_budget_id; history is shown under Version history. - Signature and PDFs. An accepted budget stores a
BudgetSignatureplus a signed PDF whose SHA-256 is kept as a tamper-evident hash. Two downloads exist: unsigned PDF and signed PDF. - Create invoice. When the budget is accepted and still has uninvoiced items, a Create invoice button appears and takes you to
/invoices/from-budget/{id}.
Edit lines
Requires
budget.writeanddraftstatus.
- Click Edit on a line or Add item below the table.
- Change catalog item, tooth, surfaces, quantity, discount, or VAT. Totals recompute on save.
- The backend rewrites the totals invariant on save (no
updateevent yet).
Send to the patient
Requires
budget.write.
- Click Send to patient. The budget transitions to
sent, a public code is generated, and the email goes out. budget.sentis published so messaging modules can complement the email.- The sidebar then shows the public link card with the verification code.
Accept or reject
Requires
budget.writefor online acceptance,budget.accept_in_clinicfor in-clinic signed acceptance.
- Accept (online) — used when the patient accepts via the public link. Creates a
BudgetSignatureand a signed PDF. Publishesbudget.accepted. - Accept in clinic — button only visible with the matching permission. Opens the tablet signature modal (drawn signature). Same result as the online acceptance.
- Reject — records a reason and publishes
budget.rejected.
Renegotiate
Requires
budget.renegotiate.
- Click Renegotiate. Creates a new version linked to the current one; the previous becomes historical.
- Edit items and save. Publishes
budget.renegotiated.
Resend (new version of a finished quote)
Requires
budget.write. Only visible while the quote is rejected, expired or cancelled.
- Click Resend. A new draft (version +1) is created with the same lines and a fresh public link, and the screen navigates to it.
- The linked treatment plan automatically follows the new version (
budget.supersededevent); its status is untouched. - Edit the draft if needed and send it to the patient. If the plan was closed as rejected by the patient and the patient accepts this new version, the plan auto-reactivates to In progress.
Permissions
| What you see / can do | Permission |
|---|---|
| View detail, lines, version history, download PDF | budget.read |
| Edit lines, send, accept online, reject, cancel, duplicate, resend | budget.write |
| Accept by signing in-clinic | budget.accept_in_clinic |
| Renegotiate (create a new version) | budget.renegotiate |
| Delete | budget.admin |
Troubleshooting
- No Create invoice button. The budget is not accepted yet (valid:
accepted), or it already has a non-cancelled invoice, or every item is already invoiced (invoiced_quantity == quantity). - Cannot edit lines. The budget is no longer in
draft. To change prices or quantities on a sent/accepted budget you must renegotiate (requiresbudget.renegotiate). - No payments card. The
paymentsmodule is not installed. The sidebar shows only totals and info. - Signed PDF returns 404. The budget is not accepted yet — the signed PDF only exists from the
acceptedstate on. - An action failed. The error toast shows the reason the server gave, not a generic message. The common ones are Cannot send empty budget (add at least one line first), Patient has no email address (fill it in on the patient record, or untick Send email and mark it as delivered by hand), and Cannot send budget from status 'sent' (it was already sent — reload the page).