A quotation system for a UAE engineering company’s water-meter sales. AI reads the customer’s enquiry and never sees the price list: fixed rules and the company’s own Excel costing sheet set every price, and the sales engineer keeps the margin.
A contractor’s procurement team emails a list of water meters for a building: sizes, flow rates, M-Bus or radio, quantities. Nothing can go back until every line is priced.
For each line, the sales engineer finds the product by size and protocol in the price list, converts the supplier’s price into dirhams, and adds freight and clearance, the fittings and the margin. Then every line is typed again into the offer template, with VAT, the letterhead and the customer’s details, and checked against the costing sheet.
The time grows with the lines. A small quote took at least 30 minutes, and a large one with several sizes and variants took two to three hours Estimate. A sales engineer could see 10 to 20 large enquiries a month Estimate.
That is selling time spent on typing. In a busy week, enquiries queue for the back office while the customer waits for a price, and every figure typed twice is one more chance to misprice.
Estimated from doing the work by hand Estimate
The system draws one hard line. AI reads the email and lists what the customer asked for. Past that line, only fixed rules and the company’s own formulas touch a number, and every commercial decision stays with the engineer.
| Step | By hand | With the system |
|---|---|---|
| Read the enquiry | Read the email and its list, line by line | The engineer drops the email into the system and sets the margin, freight and delivery time. AI reads who is asking and the items they asked for |
| List the items | Copy each size, flow rate, protocol and quantity into the costing sheet | AI turns the customer’s text into line items. When it cannot read a list it can trust, it does not guess one |
| Choose each product | Search the price list for each size and protocol, line by line | Fixed rules choose: same type, same protocol, the exact size or else the nearest one, then the shortest body. AI has no part in this step |
| Price it | Convert the currency, add freight, fittings and margin, with a calculator beside Excel | AI never sees the price list. The costing sheet prices every line with formulas: supplier price, freight, exchange rate, fittings, margin |
| Write the offer | Retype every line into the offer template, then add VAT, the letterhead and the customer’s details | The offer’s lines are formulas that point at the costing sheet, with the customer’s details, the delivery time and VAT filled in |
| Check and send | Check every figure against the costing sheet, or wait for the back office | The engineer checks one workbook and sends it. Nothing goes to a customer automatically |
Each unit price on the offer is a formula such as ='Costing Sheet'!N2, so a change on the costing sheet reprices the offer, with its subtotal, VAT and total.
Every figure here follows the same arithmetic as the real workbook.
| # | Item | Supplier € | Landed AED | Qty | Unit AED @20%@25% | Line AED |
|---|---|---|---|---|---|---|
| 1 | RW-15-MB Residential DN15 M-Bus | 39.00 | 184.08 | 120 | 230.10245.44 | 27,612.0029,452.80 |
| 2 | RW-20-MB Residential DN20 M-Bus | 45.00 | 212.40 | 24 | 265.50283.20 | 6,372.006,796.80 |
| 3 | BW-50-RD Bulk DN50 radio | 411.00 | 1,939.92 | 2 | 2,424.902,586.56 | 4,849.805,173.12 |
| 4 | BW-40-RD Bulk DN40 radio | 366.00 | 1,727.52 | 1 | 2,159.402,303.36 | 2,159.402,303.36 |
Line 4: the customer asked for DN32. The bulk range has no DN32, so the rule took the nearest size, DN40. The sheet did not mark the swap, so it rested on the engineer’s check.
| # | Item and description | Qty | Unit price AED | Total AED |
|---|---|---|---|---|
| 1 | RW-15-MB Residential DN15 M-Bus | 120 | 230.10245.44 | 27,612.0029,452.80 |
| 2 | RW-20-MB Residential DN20 M-Bus | 24 | 265.50283.20 | 6,372.006,796.80 |
| 3 | BW-50-RD Bulk DN50 radio | 2 | 2,424.902,586.56 | 4,849.805,173.12 |
| 4 | BW-40-RD Bulk DN40 radio | 1 | 2,159.402,303.36 | 2,159.402,303.36 |
Delivery: 8 to 10 weeks from payment confirmation.
I’d start with your last ten quotes: the enquiries that came in and the offers that went out.
They show how long your quotes take, which rules already decide your prices, and which decisions must stay with your engineers. The first version writes into the costing sheet and offer template your team already uses, so every quotation still goes out on your letterhead, checked by your engineer.
Discuss a system like thisThe system was a single Python web page. The model’s job ended at reading text: it never saw the price list, and choosing products and every figure on the sheets belonged to code and Excel formulas.
A Streamlit page took the email file and the three settings. OpenAI assistants each did one reading job and answered in JSON: the customer and the product text, whether that text was enough to quote, a separate check of that verdict, and the line items. Plain pandas code then matched each line to the catalogue.
openpyxl copied the company’s workbook template and wrote formulas into it, inserting a row per line with the template’s formatting, merged cells and letterhead image kept in place. The output was one .xlsx with two sheets for the engineer to download.
The email file, plus margin, freight and clearance, and delivery time
Streamlit, .eml uploadCustomer, product text, a sufficiency verdict and its check, line items
Assistants API, JSON outType, protocol, exact or nearest size, then the shortest body
select_meter, pandasCosting lines and totals, offer lines pointing at them
openpyxl, make_costingCosting sheet and offer, checked and sent by the engineer
.xlsx, two sheetsThe model turns free text into fields: who the customer is and what they asked for. It never sees the price list. Product choice and every figure come from code and formulas.
Each costing line is written as formulas such as =(D2*F2)*(E2) and =L2/(1-0.2), and each offer line points at it with ='Costing Sheet'!N2. Totals use SUMPRODUCT, VAT 5%, profit and margin.
Within the requested type and protocol, the rule takes the exact size and the shortest meter body. With no exact size, it takes the nearest size the catalogue holds for that type and protocol, then the shortest body. If nothing fits, it stops with an error.
One call judges whether the product text is enough to quote; a second, separate call checks that verdict against the text it came from. A flagged verdict counts as not found, and nothing is priced from that text.
Follow the fictional enquiry from sheet 4 through the system, from the dropped email to the workbook. The left edge of the drawing shows who does each step.
The engineer drops the .eml file into the page and sets the margin, freight and clearance, and the delivery time, then presses one button. For this enquiry: 20%, 18%, and 8 to 10 weeks.
The email’s HTML is cleaned and converted to Markdown with its From, To and Subject lines. The first call returns the company, address, project reference, contact person, phone, fax and email, and the product text as the customer wrote it.
A second call judges whether the product text is enough to quote. A third, separate call checks that verdict against its source, and a flagged verdict counts as not found.
The fourth call turns the product text into line items, each with a type, a size in DN, a flow rate, a protocol and a quantity. This is the last thing the model does.
Code filters the catalogue by meter type and by radio or M-Bus, then takes the exact size with the shortest body. The bulk range has no DN32, so line 4 gets the nearest size, DN40. Lines that land on the same item code have their quantities added together.
openpyxl writes each line into a copy of the template as formulas: supplier price plus fittings, times freight, times the exchange rate, plus the tailpiece; then unit price = cost ÷ (1 − margin). Totals follow: cost by SUMPRODUCT, price, VAT 5%, profit and margin.
The offer’s item, description, quantity and unit price point at the costing sheet. The letterhead, offer reference, customer block and delivery line are filled in, and the engineer downloads one workbook. Change the margin on the costing sheet and the offer reprices. Nothing is sent until the engineer sends it.
The system covered two product lines. A version for your team keeps the same boundary, with AI reading and your rules pricing, and adds what a team needs.
Each row is one part of the system: what it does, and what your version adds.
The times on this page are estimates from doing the work, by hand and with the system. Everything else is checked in the source code.
In the code, no price came from AI, and the offer was linked to the costing sheet by formula. The margin, freight and delivery time were the engineer’s on every quote. The 10 to 20 large enquiries a month is an estimate too.
The system covered two water-meter product lines. The method fits any business that prices from a catalogue: the rules and the template are written for yours, and AI still only reads the enquiry.
Discuss a system like thisIf your sales engineers spend their evenings retyping price lists into offer templates, the fix starts with your last ten quotes. Bring them.