Expert quotes
Once a lead’s BRD is approved, it enters the bid pool — the marketplace stage where matched experts can view the requirements and submit quotes. This is the most critical conversion point in the journey: if no expert quotes, the lead stalls; if the customer rejects all quotes, the lead closes. A quote that is nearly right need not be rejected — the customer can ask for changes instead, and the quote loops back to its expert.
Flow
The bid pool
When bidPool = true is set on a lead, it becomes discoverable by experts on the platform. Experts can browse open leads, review the BRD, and decide whether to submit a quote.
The platform tracks:
- How many experts have viewed the lead
- How many quotes have been submitted
- Time elapsed since the lead entered the bid pool
A daily scheduled sweep watches the bid pool deadline. When it passes and no quote has been submitted, the lead is marked Unmatched and exits the journey; when every submitted quote has been rejected, it closes as No fit instead. The assigned CSM is warned 48 hours ahead of a looming close, and the CSM and vendor are told when it closes — so a stalled lead never sits in the pool unnoticed, and a lost lead is always classified for funnel reporting. An Unmatched close signals a gap in the expert pool or an unclear BRD that failed to attract quotes. The customer’s approval never opens the pool with less than 48 hours to the deadline: an approval past it, or inside that window, moves the deadline to seven days after the approval (Requirements).
Expert quote structure
Each expert quote is submitted by a single expert and contains:
| Field | Type | Constraints | Description |
|---|---|---|---|
title | String | 3–100 chars, required | Quote headline |
summary | String | Optional | Description of the proposed approach |
price | Number | ≥ 0, required | The expert delivery cost — the customer quote adds the platform fee on top |
startDate | Date | Future date, required | Proposed project start |
endDate | Date | Future date, required | Proposed project end |
milestones | Array | — | Phased deliverables (see Delivery) |
remarks | String | Max 1000 chars | The quoting expert’s own note on their quote |
submittedAt | Date | Set on submission | When the quote first went to the manager |
reviewedAt | Date | Set on the manager’s first open | When the lead’s CSM or SDM opened the submitted quote; cleared on resubmission |
submittedAt is stamped the moment a draft is submitted and never moves again — a later edit, a
withdrawal and re-submission, or a revision answering a change request all leave it where it was, so
it records the first time the quote reached the manager. It is deliberately not the same thing as the
quote’s creation date: a quote exists from the moment the expert saves a draft, which can be days
before they send it. Quotes submitted before the field existed carry their creation date as the
closest available approximation, and quotes drafted before they were sent are therefore dated a little
early. The Customer Service Journey shows this date under each quote, labelled Submitted.
Rejecting an expert quote records the reason separately from the expert’s own note, so a rejection never
overwrites what the expert wrote. The reason is stored under whoever gave it — one field per
author (String, max 1000 chars each): managerRejectionRemarks for the reviewing manager,
awardSweepRejectionRemarks for the award sweep closing the pool, and
customerQuoteRejectionRemarks for a customer rejecting the customer quote built from the expert quote. The three
had been one shared field, which meant nobody could tell whose words a given rejection held.
Who reads which follows from that. On the quote page a manager sees every reason; the quoting expert sees all three verdicts on their own quote; and the customer of the lead sees only the reason they gave themselves — never the manager’s internal wording, which they could previously read. Each reason renders as its own card headed by its author. “Manager” here means anyone who can respond to expert quotes, and equally anyone granted quote viewing across the whole tenant: a user given that wider view by a per-user permission override sees the same cards a manager does, since the grant already opens every expert quote in the tenant to them.
The original rejectionRemarks field survives as the rows whose author could not be established
when the split was backfilled. It is written by nothing and shown to managers alone, on the
principle that an unattributed verdict is exactly what should not reach a party by default.
The reason goes to the people it concerns and no further. The rejected expert is notified with it, and it stays on the expert quote; it is not written to the lead’s activity timeline, which every expert in the bid pool can read from their own quote page. That timeline is the lead’s shared record — what happened to the lead, in words meant for everyone who can see it — so it carries no party’s free text about another party’s quote. The one reason it does carry is the qualify-out reason, which is about the lead itself.
Kept off the shared timeline is not the same as kept from everyone. Each reason is recorded on its activity entry in a field of its own, and each surface shows that field only to the audience it was written for: the quote page shows none of them, and the activity section of the Customer Service Journey shows the customer’s reason for refusing a customer quote to an admin, CSM or SDM. Splitting the field by audience is what lets one entry serve both readers — the alternative, deciding by which page the reader is on, would protect nothing the day the same list is shown somewhere else.
The quote’s name is split the same way. A rejection entry says only that a quote was declined; which quote it was travels with the entry, for the surfaces entitled to read it. A rival in the pool learns that the lead moved on and nothing about whose quote lost. The losing expert sees their own quote named, on their own quote page. The people who review the quotes see it named on the Customer Service Journey — they already see every quote on the lead, so the entry tells them nothing new. The customer sees the shared line: which quotes competed, and under what name, is not part of what their project record is for.
One expert can only submit one quote per lead — enforced by a unique index on (tenantId, lead, createdBy). Quotes begin as isDraft = true and are only visible to the customer once submitted.
Expert quote status workflow
| Status | Meaning |
|---|---|
proposal_pending | Draft — expert is still preparing the quote |
proposal_submitted | Expert has submitted; customer can review |
proposal_changes_requested | Customer has asked the expert to revise; not a rejection |
proposal_accepted | This quote has been selected; it is now final |
proposal_rejected | Customer has rejected this quote |
What each reader calls a quote’s status
The vendor, the CSM and the SDM read a quote in the demo script’s vocabulary — Submitted, Reviewed, Selected or Unsuccessful — as labels over the statuses above; the statuses themselves do not change. The expert keeps the workflow’s own words (Accepted, Rejected), and so do the customer and the admin.
| Status | Vendor, CSM and SDM read |
|---|---|
proposal_submitted | Submitted — or Reviewed once the lead’s CSM or SDM has opened it |
proposal_changes_requested | Reviewed |
proposal_accepted | Selected |
proposal_rejected | Unsuccessful — whether a manager or the award sweep rejected it |
Reviewed is recorded, not guessed: the first time the lead’s assigned CSM or SDM opens a
submitted quote’s page, the quote is stamped reviewedAt. Anyone else opening it — the vendor, the
expert, another manager — records nothing. When the expert saves a change or resubmits after a change
request, the stamp is cleared, so the new version reads Submitted until it is opened again.
An expert quote’s price is the expert’s delivery cost, so a customer does not see it: before the customer quote is
issued the customer sees no price on an expert quote, and afterwards they see the customer quote’s price on the
accepted one (see Quote & Acceptance).
An expert quote is priced in the customer’s currency — the unit its customer quote is priced in — and nothing is
converted: the expert’s own currency plays no part. The quote form says so (Price (GBP) for a
customer who reports in pounds, with “In the customer’s currency.” beneath it), and the quotes list,
the quote page and the lead’s workspace print each expert quote in its customer quote’s currency, or — for one
whose customer quote names none — in its lead’s customer’s (EUR when the customer has none).
What the SDM compares expert quotes on
Whoever reviews the expert quotes — the SDM and the admin by default, anyone granted proposal.view — sees
more than a price on each one, so three quotes for one job can be told apart:
- On each quote card in the lead’s Expert quotes section: the customer price as the headline, with the expert’s price and the platform fee (amount and rate) beneath it; the delivery timeline; the expert’s past CSAT with how many reviews it averages; their completed and active projects; and the same four ticks the match card shows (product, industry, location + language, capacity), each with its reason.
- On the quote’s own page: the milestones as a table — deliverable, target date, percentage and amount, with a total that equals the quote’s price — a price breakdown card, and a track record card beside the expert’s knowledge profile.
Until the expert quote’s customer quote is issued, its platform fee and customer price are a preview at the tenant’s rate today, priced by the same rule that issues the customer quote, and say so. Once the customer quote is issued, the expert quote shows the customer quote’s own figures: the rate is fixed at issue and never re-read.
The expert sees their own quote with their own price and milestone amounts at that price, and never the fee, the customer price, their track record or the ticks. The customer sees milestone amounts only once the customer quote is issued, as each milestone’s share of the customer quote’s price — never the expert’s price or the fee.
Accepting an expert quote closes the pool: every other expert quote still awaiting review on the lead moves to
proposal_rejected in the same acceptance, each losing expert is notified that the lead was
awarded elsewhere, and that reason is recorded on the losing quote’s awardSweepRejectionRemarks —
leaving each expert’s own remarks as they wrote it.
That sweep runs after the award has been committed, so it cannot roll one back: a rejection that fails leaves its quote open with no one told. Each failure is recorded — the lead, the quote, the winning quote and the error — and the Customer Service Journey marks any expert quote still open on an awarded lead for whoever holds quote review, with the Reject that closes it. The flag says in plain words which failure left the quote open (its rejection failed, or the other quotes could not be listed); the recorded error itself stays in the stored record and is never shown, because it names the platform’s own servers. Awarding is also refused outright on a lead that already has an accepted expert quote, so one left open cannot be turned into a second award.
One award per lead is a rule the database itself holds, not only the check that runs before an award. Two people accepting different expert quotes on the same lead at the same moment used to be able to both succeed — two customer quotes to the customer, two experts told they had won, and the lead’s expert decided by whichever save landed last. Now only one of them can win, and the other is told the lead has already been awarded, in the same words they would see a moment later.
A decision closes the expert quote to its own expert — the award and the rejection alike. An accepted expert quote can no longer be edited: its price, dates, summary and milestones are what the customer quote was built from, so changing them after the award is refused, both on the quote’s edit page and by the server behind it. A rejected expert quote is closed for the mirror reason — a decision has been made and recorded, and an edit would put the quote back in front of whoever made it as though it were new.
Neither can be withdrawn back to draft, and neither can be archived by its expert: archiving an expert quote takes its activity, the customer quote and that quote’s invoices with it, so an expert who could archive their awarded quote could take the customer quote out of circulation on their own. Every surface asks the same question the server does, so a decided expert quote simply does not offer the controls — no edit link, no move to draft, no archive, and none of the matching levers on the workspace rail. This is a status rule rather than a permission one: the expert keeps every grant they had. An expert who needs something on a decided quote to change speaks to their manager; there is no self-service route back.
A status outside the table above
The five statuses are matched exactly — a stored value that differs from one of them by letter case or surrounding spaces is not that status, it is a status the platform cannot read. Such a quote is not treated as one with no status at all: it keeps its stored value and every surface refuses it the same way. It offers no accept, no reject, no change request, no resubmit and no edit link, it can be neither withdrawn to draft nor archived by its expert, and it shows “Unrecognised status” where its status would be.
Whoever holds quote review is told which value is stored, because getting it corrected is the only way to make the quote answerable again; the expert is told only that the status is not one we recognise and to ask their manager. A draft or archived quote is still refused as a draft or an archive, whatever its stored status — correcting the value would not make either answerable.
The negotiation loop
A submitted quote has a third outcome beside accept and reject, and it is the only
non-terminal one. The customer asks for changes with a written message; the quote moves to
proposal_changes_requested and goes back to its expert, who reads the feedback on the quote,
revises it, and resubmits — which returns it to proposal_submitted. Every round is recorded on
the quote and shown to the customer, the expert and the managers.
- A change request is not a rejection. The quote stays live and the lead stays open: competing quotes continue and the bid pool deadline stands while the round-trips happen.
- The loop is capped at three rounds. After the third the customer’s affordance is gone and the SDM steps in — accept, reject, or take the conversation off the platform. Quote review is the SDM’s; the CSM holds no expert quote permission.
- A manager can still close it out mid-loop. Accept and reject stay available from
proposal_changes_requested, and rejection stays terminal. - The expert has one way out. While a round is open the quote cannot be withdrawn to draft, and editing it does not by itself answer the customer — only resubmitting does.
- Nobody has to go looking. The expert and the SDM are notified when changes are requested; the customer and the SDM when the revision lands. The lead’s CSM is told both times too, because the CSM handles the customer and needs to know the customer is waiting on a revision. The CSM holds no expert quote permission, so their notice is about the lead, not the quote: it names no quote, carries only its title, and links to the lead’s workspace. A CSM who is also the lead’s SDM gets only the SDM’s quote notice. The lead board still flags a lead with a round open.
What happens next
Accepting an expert quote triggers the Quote & Acceptance stage: a customer quote is generated from the expert quote’s price, and the lead transitions to an active project.
The SDM selects the expert and sends the quote. The SDM handles everything with the expert — Expert Match, the bid pool, the review of each expert quote — and accepting an expert quote is how the customer quote reaches the customer: there is no separate send step. The CSM handles everything with the customer, including the customer’s questions on the quote and their decision. Before a customer quote exists, the CSM’s Customer quote section on the lead counts the expert quotes that are in and names none of them, so the CSM can tell the customer where things stand without holding the bid pool.
Where the lead already has a customer quote, its status decides what acceptance does with it, and that is settled before the expert quote is awarded: a draft is sent to the customer, one already sent or already answered is left alone, and a status the platform cannot name refuses the acceptance outright — see the quote status workflow. Either way the accepted expert quote’s record names the customer quote it is about.