Quote Approval & Conversion
Once a quote is ready, NexusRMS provides multiple ways to send it to your client for review, approval, or rejection. The system tracks every interaction — when the quote was sent, when it was viewed, and how it was approved — giving you full visibility into your sales pipeline.
Sending a quote
From the quote detail page, click Send to Client. This triggers the markAsSent() action, which sets the sent_at timestamp and changes the status from draft to sent. The client receives an email with the quote PDF attached and a link to view it online.
Only draft quotes can be sent. If the quote is already in sent, viewed, or any other status, the Send button is disabled.
Public link system
Every sent quote can have a shareable public link that allows clients to view, approve, or reject the quote without logging in.
- Generate link — The generatePublicLinkToken() method creates a unique approval_token (UUID) and sets the token_expires_at date. The expiry period is configurable in Financial Settings via the quote_public_link_expiry_days setting (default 30 days).
- Get the URL — The getPublicUrl() method returns the full shareable URL using the tenant's domain.
- Track views — Each time the public link is accessed, incrementAccessCount() increments the public_link_access_count field, so you can see how many times the client has viewed the quote.
- Check validity — The isPublicLinkValid() method verifies that the token exists and has not passed its token_expires_at date.
- Revoke access — Use revokePublicLink() to invalidate the token immediately, preventing further access via the public URL.
Client approval page
When a client opens the public link, they see a dedicated approval page (QuoteViewer.vue) with the following features:
Quote display
- Full PDF viewer showing the complete quote document
- A countdown timer showing days remaining until the quote expires, with colour-coded urgency indicators: green (more than 7 days), amber (3–7 days), and red (fewer than 3 days)
- If the quote has passed its valid_until date, an expired overlay is displayed and the approval buttons are disabled
Approve dialog
When the client clicks Approve, a dialog appears with the following fields:
- Signer Name (required) — The full name of the person approving the quote
- Signer Email (required) — Their email address for the approval record
- Signature (required) — A SignaturePad canvas where the client draws their electronic signature. The signature_data is stored via the DocumentSignature model.
- Comments (optional) — Any additional comments from the client, stored in acceptance_comments
Reject dialog
When the client clicks Reject, a dialog appears with the following fields:
- Signer Name (required) — The name of the person rejecting the quote
- Signer Email (required) — Their email address
- Reason (required) — The reason for rejection, between 10 and 1,000 characters. This is stored in the rejection_reason field.
The approved_by_contact_id field links the approval to the specific ClientContact record, and the approval_method records how the quote was approved: public_link, portal, or manual.
Quote status flow
Quotes follow a defined status progression:
- draft — Initial state when the quote is created
- sent — After markAsSent() is called, setting sent_at
- viewed — After markAsViewed() is called when the client first opens the quote, setting viewed_at
- accepted — After approve() is called, setting approved_at and approved_by
- declined — After decline() is called, setting declined_at and the rejection_reason
- expired — Automatically set when valid_until passes. The system checks isExpired() (valid_until in the past and status is not accepted).
- converted — After the quote is converted to an invoice
The canBeApproved() method returns true only when the status is sent or viewed and the quote has not expired. This prevents approval of draft, expired, or already-processed quotes.
Expiry notifications
The system sends notifications for quotes expiring within 3 days. Once a notification is sent, the expiry_notification_sent_at timestamp is set to prevent duplicate alerts on the same day.
Quote revisions
If a client requests changes to a quote, use the Create Revision action rather than editing the original. The createRevision() method creates a new quote with:
- A new quote number
- The parent_quote_id set to the original quote's ID
- All line items cloned from the original
- Status reset to draft, with sent_at, viewed_at, approved_at, and approval_token all cleared
The full revision chain is visible on the quote detail page, showing every version of the quote in chronological order.
Converting to an invoice
Once a quote is accepted, you can convert it into an invoice. The canBeConverted() method verifies that the status is accepted and no converted_invoice_id exists yet (preventing duplicate conversions).
Click Convert to Invoice on the quote detail page. The convertToInvoice() method:
- Creates a new Invoice with the client, project, currency, tax rate, discount, and terms copied from the quote
- Copies all line items from QuoteItems to InvoiceItems
- Sets the converted_at timestamp and stores the converted_invoice_id on the quote
- Changes the quote status to converted
Project synchronisation
When a quote is linked to a project, NexusRMS provides bi-directional synchronisation between quote line items and project equipment:
Push to project (syncToProject)
- Preview first — Use previewSyncToProject() to see what would be added, updated, or removed from the project before committing
- Sync — The syncToProject() method pushes equipment items from the quote to the project's equipment list, updating quantities and prices
- Only items with item_type of equipment and a valid item_id are synced; custom line items remain on the quote only
Pull from project (refreshFromProject)
- Preview first — Use previewRefreshFromProject() to see what equipment would be added, updated, or removed from the quote
- Refresh — The refreshFromProject() method pulls the current project equipment list into the quote, updating names, quantities, prices, and dates
- Custom items (non-equipment line items) are preserved by default
- Only draft quotes can be refreshed; sent or approved quotes require a force override
Tips
- Use public links for faster approvals — Clients can approve instantly without needing a NexusRMS account. Share the link via email, messaging, or any channel.
- Monitor the access count — If a client has viewed the quote multiple times without responding, it may be a good time to follow up.
- Create revisions instead of editing — Revisions maintain a complete audit trail. Editing a sent quote loses the history of what was originally proposed.
- Preview before syncing — Always use the preview functions before pushing or pulling project data to avoid unexpected changes to your quote or project.
Next steps
Continue to the next article to learn how to create invoices, add line items with section headers, and configure payment terms.
Was this article helpful?