Quotations — New
What it is
The quotation builder, starting from nothing: pick the customer, add lines by hand or by importing an RFQ, price them from the catalogue, and save.
The subtitle states the pricing rule the whole screen runs on: the price list is held in INR and converted to the quotation's currency at the USD rate on the header.
Who can open it
Any signed-in staff account that is active. Two gates, both in proxy.ts: account status, then
the sales.quotations feature grant while FEATURE_GRANULAR_RBAC is on, with the owner bypassing.
Before you start
🔴 Check the quote number before you save. It is guessed in the browser, not allocated by
the system: the screen reads the single most recently created quotation across all entities,
strips out everything that is not a digit, adds one, and formats it QT-<year>-<NNN>. That means:
- it ignores the entity's own quote prefix;
- the digits can come from another entity's numbering;
- two people building a quote at the same time will be handed the same number.
A quote built from an RFQ instead — the Build Quote → button on the RFQ — does allocate a proper number for the entity. If the number matters, start from the RFQ, or overwrite the number here before saving.
🔴 Saving is not a single transaction on this screen. The quotation is written first, then its lines. If the lines fail you are left with a saved quotation carrying no items, and the message "Quote saved but items failed". If you see it, open the quote and add the lines rather than saving again — saving again creates a second quotation. (The edit screen does save atomically; the inventory's "optimistic-locked atomic save" note for A2Z-F037 describes that screen, not this one.)
⚠️ Saving also writes to the shared catalogue. Any line marked as new with a cost on it is inserted into the price list under an auto-generated code, not scoped to an entity — it is a global catalogue row. Saving additionally records the prices you used, so they can be suggested next time.
Every control on the page
Title bar:
| Control | What it does |
|---|---|
| 📂 File for Backfill | Attach the customer's original Excel RFQ. Once attached the button becomes 🎯 Update Original RFQ, which writes your prices back into the customer's own workbook and downloads it — the layout they sent, filled in. |
| ⬇ Excel | Greyed out here. Its tooltip says "Save quote first to export as Excel". Export from the saved quotation. |
| Produces the PDF. | |
| ✓ Save Quote | Saves and takes you to the new quotation. |
Header form — customer, entity, quote number, quote date, valid-until, currency, USD rate, status, vessel, port, notes and discount. Any custom quotation fields your company has configured appear directly beneath it.
Global controls strip:
| Control | What it does |
|---|---|
| Global Markup % | Re-prices every line at that markup immediately. Default 22. |
| Global Discount % | A header-level discount. The money it takes off is shown beside it in red. |
| 📥 Import RFQ | Opens the import dialog — see below. |
| Auto-fill IMPA | Looks up IMPA codes for the descriptions on the sheet and fills them in, along with the master unit and category where a line has none. |
The line table — description, quantity, unit, unit cost, markup %, unit price, GST %, line total, plus maker's reference, drawing number, purchase unit and conversion factor, supplier notes and ex-works days, and a dangerous-goods declaration per line.
- Typing in description offers matches from the price list and from the IMPA/HSN master; arrow keys move through them, Enter accepts, Escape dismisses.
- The picker is port-aware. With a port on the header it prefers catalogue rows for that port and falls back to the global row; with no port set it shows global rows only. So setting the port changes the prices you are offered.
- There is a code search for IMPA and HSN, an auto-calculate GST action, and add / remove row.
Import RFQ dialog — two tabs, file and paste:
- File takes the customer's spreadsheet.
- Paste takes the text of their request; there is also an AI parse for free-form text.
- Parsed rows are shown for review before they are added. Where a row could match several catalogue items you choose which; rows with no match are flagged as new.
- Unit mismatch prompt: when the catalogue's unit differs materially from the customer's, you are asked which to use, and can have the original noted in the line's remarks.
- Apply appends the reviewed rows to the sheet; reset discards them.
Dangerous goods warning. As soon as any line carries an IMDG class, a banner appears warning that carriers require an IMDG packaging declaration and may reject mixed DG and non-DG consignments.
Status bar (bottom) lists what is still missing before the quote can be saved: Client is required, Quote number is required, Entity is required, Add at least one line item, Some items have zero price. It also shows catalogue loading progress on first open.
What it writes
| Action | What it writes |
|---|---|
| ✓ Save Quote | Inserts one quotations row, then its quote_items — two separate steps, see "Before you start". Pricing rules are applied first and the winning rule is recorded on each line. |
| ✓ Save Quote, continued | Inserts new catalogue rows into price_list for lines flagged as new (global, entity-less), and records the prices used for future suggestions. |
| 📂 File for Backfill + save | Uploads the workbook to the rfq-source-files bucket and saves its path on the quotation. If the upload fails the quote still saves, and you are told the file must be re-uploaded from the edit screen. |
| 🎯 Update Original RFQ | Writes nothing — it builds and downloads the filled workbook. |
When it goes wrong
"Select a client and set a quote number first." Both are required; the status bar lists whatever is missing.
"Add at least one line item before saving." A line only counts once it has a description.
"Quote saved but items failed." The quotation exists with no lines. Open it and add them — do not press save again, which creates a second quotation.
"Quote saved, but the source RFQ file could not be persisted." The quotation is fine. Re-upload the workbook from the edit screen if you want the backfill later.
The quote number clashes with someone else's. Expected — see "Before you start". Change it and save again, or build the quote from the RFQ instead.
The catalogue looks empty or the prices are wrong for the port. The picker only offers rows for the header's port, falling back to global rows. Set the port before pricing.
The screen sits on "Loading..." for a while. It loads the entire active price list in blocks of 1,000 and shows the progress at the bottom.
Related screens
- Quotations — the list this saves back to.
- Quotations — Id Edit — the same builder for an existing quote, with an atomic save.
- RFQs — Id — Build Quote → starts a quote from an RFQ and numbers it properly.