Skip to content
Insights · Engineering

Which quote did that customer accept?

Name the quote that customer accepted: id, status, and total. Another quote can name a different customer, and another account does not list it.

Scroll
EngineeringOct 30, 202612 min readBy Salman Naqvi, Founder & CEO
Which quote did that customer accept?

A customer says they accepted the price, or says they never saw it. Tonight, three proofs, in a console you administer. Name the quote that customer accepted: the quote id, the status, and the total. If the status is still draft, write draft, and write that the number was null. Show a different quote whose id, or whose customer, is not this one. Show another account's list that does not contain this quote. If any of the three needs the person who wired billing, you have not named the quote. You have a PDF and a guess.

This is the quote on one customer. It is not the invoice the charge paid. Which invoice did that charge pay? is the invoice id, the status, and the total on a charge. A quote can be accepted while the invoice field on a different sample is null, and an invoice can exist while the quote that was supposed to create it is a different id. It is not the product. Which product did that price sell? is the product id and the unit amount on a price. A price can be right while no quote stores it. It is not the figure on the screen. Show the price they accepted is the amount they were shown. A screen can print a total the quote object does not store. It is not the milestone on an issue, and it is not the run on a thread. Those are different objects, and they are not this id.

None of what follows is a rate for this product, and none of it is legal advice. The fields below are one processor's current description of a quote, and the four samples are not the same object. The counts below that are a 2021 thesis about one manufacturer's historical quotes. A total on an example is not a census of your buyers. A model that never opened your quote cannot name the status on the quote you opened tonight. They do tell you which numbers people mix up when they try to sound precise about an acceptance they have not opened.

Stripe's create response prints id qt_1Mr7wVLkdIwHu7ixJYSiPTGq, object quote, amount_subtotal 2198, amount_total 2198, created 1680130691, and expires_at 1682722691. The id is 27 characters. The customer on that object is cus_NcMfB0SSFHINCV, 18 characters. Status is draft. number is null. invoice is null. accepted_at, canceled_at, and finalized_at are all null. A null number is not a missing quote. livemode is false. collection_method is charge_automatically. total_details prints amount_discount 0, amount_shipping 0, and amount_tax 0. 2198 minus 0 minus 0 minus 0 is 2198. The subtraction matches the total, and it does not turn a draft into an acceptance. expires_at minus created is 2592000 seconds. 2592000 divided by 86400 is 30 exactly. 30 days is the sample's lifetime. It is not a status, and it is not the one second you will see on the other samples. The create request on the same page sends a customer placeholder, a price placeholder, and line_items quantity 2. 2 is not 2198. 2198 divided by 2 is 1099. The page does not print 1099. Do not invent a unit amount because the division is tidy. The version header on the example is 2026-10-28.endive. That string is 17 characters. It is not the integer 1680130691 (Stripe, Create a quote).

The status names are four, and the create sample is only the first. The object page lists accepted, canceled, draft, and open. Four names. accepted means the customer has accepted and an invoice, a subscription, or a subscription schedule has been created. canceled means the quote is no longer valid. draft means it can still be edited and has not been sent. open means it has been finalized and is awaiting the customer. draft is not open. open is not accepted. The create sample is draft, with number null. A null number is the draft sample's stored fact. It is not a reason to copy a number off a different id. Four names are not 2198, and four names are not 30 days (Stripe, The Quote object).

The accept call is a second page, and it is not the create sample. The accept response prints id qt_1Mr7YsLkdIwHu7ixoRgFs97D. Also 27 characters, and not qt_1Mr7wVLkdIwHu7ixJYSiPTGq. Status is accepted. amount_subtotal and amount_total are again 2198. The customer is cus_NcMHflMGStIAoB, also 18 characters, and not the create sample's customer. created is 1680129226. expires_at is 1682721226. The difference is again 2592000, which is again 30 days, on a different quote. number is QT-7F68F7D2-0001-1, 18 characters. The draft sample's number was null. Null is not 18 characters. invoice is in_1Mr7YtLkdIwHu7ixzgJJpJ3L, 27 characters, the same length as a quote id, and a different prefix. subscription is null. subscription_schedule is null. The status text said an invoice, a subscription, or a schedule. The sample stored one of those three, not all three. accepted_at is 1680129227. finalized_at is 1680129227. The gap between them is 0. created to accepted_at is 1 second. 1 is not 2592000. 1 is not 30 days. A one-second gap on an example is not the moment your customer clicked (Stripe, Accept a quote).

Finalize and cancel are two more ids, and stitching them onto the accept sample is how a total gets invented. Finalize returns qt_1Mr7SqLkdIwHu7ixpI1ClZ6z, status open, number QT-5B9DA057-0001-1, created 1680128852, expires_at 1682720852, finalized_at 1680128853, invoice null. Cancel returns qt_1Mr7ZYLkdIwHu7ixvsdZr97I, status canceled, number QT-FF4741D9-0001-1, created 1680129268, expires_at 1682721268, canceled_at 1680129269, finalized_at 1680129269, accepted_at null, invoice null. Each id is 27 characters. Each number is 18 characters. Each expiry gap is 2592000. Each transition timestamp is 1 second after that sample's own created. The customers are cus_NcMBZUWCIOEgEW and cus_NcMIIkPfQZQEHR. Four customers, four ids, one repeated total. Cancel's finalized_at is set while accepted_at is null and the status is canceled. A finalized timestamp is not an acceptance. Open's invoice is null while its number is set. A number is not an invoice. The accept sample's created minus the finalize sample's created is 374 seconds, which is 6 minutes and 14 seconds. The cancel sample's created minus the accept sample's created is 42 seconds. The create sample's created minus the accept sample's created is 1465 seconds, which is 24 minutes and 25 seconds. 42 is not 374, and 374 is not 1465. These are four examples. They are not one quote's history (Stripe, Finalize a quote).

The study people reach for when they want an acceptance rate did not open this console. Jesper Gunnarsson and Jacob Tyrberg, at Lund University, predict whether a B2B quote is accepted. The abstract says feature engineering improved the models' F1-score by 10 percentage points, and that the two final models both produce about 90% F1. A later section then prints three increases, not one: 8 percentage points for logistic regression, 6 for the random forest, and 11 for the gradient boosting machine. 8 plus 6 plus 11 is 25. 25 divided by 3 is 8.333. The page does not print 8.333, and 8.333 is not 10. 11 is not 6. 6 is not 8. A single 10 in the abstract is not the three lifts the discussion counted (Gunnarsson and Tyrberg, Prediction of quote acceptance in a B2B environment).

The sample split does not land on a whole quote. They use 77845 quote samples, plus 97277 order-line samples that are not connected to a quote. 77845 plus 97277 is 175122. The page does not print 175122. Do not add the direct orders into the quote count. They say the quote set was divided 70% training, 10% calibration, 10% validation, and 10% testing. 70 plus 10 plus 10 plus 10 is 100. The percents sum. The counts do not fall out as integers. 70% of 77845 is 54491.5. 10% of 77845 is 7784.5. Neither is a whole sample. The page does not print 54491.5 or 7784.5. Do not round them into a split the thesis did not print. 54491.5 is not 2198, and 77845 is not a quote id.

The score ranges are not the abstract's about 90%. The random-forest out-of-bag scores differ from 88% to 90.5%. The gradient-boosting search differs from 89% to 90.5%. 88 is not 90. 90.5 is not 90. 89 is not 88. They trained 500 models in that boosting search, and they say none of the models used all 100000 iterations. 500 is not 100000. A ceiling you did not hit is not an F1. The calibration figure they describe, on synthetic bins, predicts 38% where the true fraction is 20%, and predicts 62% where the true fraction is 80%. 38 minus 20 is 18. 80 minus 62 is 18. The two gaps match each other, and neither gap is an acceptance rate for your customer. On the random-forest reliability diagram they then say the third bin predicts 22% while the true fraction is 5%. 22 minus 5 is 17. 17 is not 18. 5 is not 20. None of these percents is status accepted, and none of them is amount 2198.

Do the three proofs on one real quote, in the console that actually holds it. First, the binding. Copy the quote id, the status, the customer, the amount_total, the currency, and the number. If the status is draft and the number is null, write null. Do not paste QT-7F68F7D2-0001-1 onto a draft because an accepted sample has a number. If invoice is null, write null. If accepted_at is null, write null. Do not infer accepted because the customer sounded sure. Do not infer 2198 because four samples print it. Second, the other quote. A different quote, with a different id, or a different customer, is not this one. A chart of F1 scores is not that second quote. If you cannot show a quote that is not this one, you have a counter, not a record. Third, the other account. A list that belongs to someone else does not contain this quote id. If the only list is a single shared table and you cannot say whose quote it is, write that. A tenant you cannot name is the finding.

Three moves feel like the proof and are a second problem. Finalizing the quote, or accepting it, because the status was embarrassing, before you have copied the id. Finalize moves a draft toward open. Accept moves an open quote toward accepted and can create an invoice. Neither call tells you which quote you were looking at if you have not copied the id first. Quoting about 90% because it looks precise, while the quote you were asked about is one row, and the 77845 samples that produced that phrase had not opened your customer. Asking a model which of the four statuses it was. The model will pick a plausible name. It will not open the quote. An invoice you have not kept, while the customer is arguing about a bill, is which invoice did that charge pay?. Opening that screen does not name the quote id.

The path is ordinary when an operator can open one merchant's price without opening the next merchant's price as the way to prove it. PayOrch is a payment orchestration dashboard: wallets, providers, merchants, fees, and fraud controls in one view. The shape that matters here is one merchant you can point at, in an account you administer, distinct from the next merchant. That case is not a quote ledger. Nothing in that sentence is a headcount, a duration, or a result figure. If the only control on the screen changes every merchant's total together, you do not have this proof. You have a totals page.

There is a version of this afternoon where hiring the path is the wrong purchase. Nothing is for sale, because the product does not take money yet. You have no product. You are still choosing who will build, and the document in front of you is a term sheet. The criteria for that choice sit on the page written for a top SaaS development company. That page is criteria. It does not rank anyone, including us. The only fact in the room is a thesis about someone else's quotes. 90% is not your quote, and 2198 is not your quote, and 10 percentage points is not your quote. A customer has already seen another customer's payment. Naming a status does not close a leak. Or you wanted a lawyer to say whether an accepted quote is a contract. Hire the lawyer.

When the quote is real and the console cannot name it, the missing object is specific. An admin action, in an account you administer, that shows one quote id, one status, and one total, shows a different quote that is not that one, and shows another account's list without it. A startup software development company that expects this will have put that action next to the rest of the billing screen, before a stranger's complaint is the way you discover the vendor owns the quote. One that needs a call in order for you to see which quote is stored is telling you who holds the acceptance. If the first slice is a fixed capability, an AI integration sprint is the shape where the acceptance sentence can include the three proofs. If you do not yet know which system stores the quote, a two-week AI readiness assessment maps the systems. The findings are yours. They are not a promise that a thesis applies, and they are not 2198.

The milestone an issue joined, and the run a thread started, are different objects: which milestone did that issue join? and which run did that thread start?. Do not record either on this page. A milestone number is not a quote id. A run id is not a quote status. The tax an invoice added is a different object: which tax did that invoice add?. Do not record it here. A percentage is not a quote status. The balance a customer held is a different object: which balance did that customer hold?. Do not record it here. An ending balance is not a quote status.

Before you tell them the customer accepted, do the three proofs and write the status. Name the quote, the status, and the total, or write that the number was null and the status was draft. Show a different quote that is not that one. Show another account's list that does not hold it. Do not accept a quote to avoid reading the status, and do not ask a model which of the four it was. A thesis can tell you how far an F1 moved on someone else's history, including the 10 that is not the mean of 8, 6, and 11. The binding is the quote you can defend.

Questions

Three records, in a console you administer. The quote id, the status, and the total, or a written line that the status is still draft and the number is null. A different quote whose id or customer is not this one. Another account's list that does not contain this quote. If any of the three needs the person who wired billing, you do not have the proof.

No. An F1 on someone else's historical quotes is not the id on this quote. A quote you can defend is the id, the status, and the total, or a written line that the number was null. About 90% in one thesis is not status accepted, and 2198 on a sample is not your customer's total.

When nothing is for sale, when you have no product, when you are still choosing a firm, when the only fact in the room is a thesis about someone else's quotes, when a customer has already seen another customer's payment, or when you wanted a lawyer.

Find this useful? Tell Google to show you more of it.

Let's put AI to work in your business.

A 30-minute call. You bring the workflow or the roadmap — we'll tell you what's feasible, what it costs, and what we'd build first.

Book a call→