#systems

What a Quotation Line Actually Is

· 7 min · 1,111 words · by xweng

I spent more time than I expected getting the answer to a question that seemed trivial: what is a quotation line?

I was building a tool to automate part of a trading workflow for aluminum extrusions. The core problem: a new-die RFQ arrives as three separate documents — a drawing PDF with the profile geometry, a factory quotation with pricing, and an email thread with the customer’s order lines. Each document knows part of the story. The drawing knows the alloy and weight. The factory knows the price. The email knows the cut lengths and quantities. My job was to join them.

The join key was the die number — a supplier-specific identifier stamped on all three documents. Simple enough. One die, one entry, one quotation line. That was my first model.

It was wrong within a week.


First correction: the cut length is the unit, not the drawing

The first real RFQ I ran through the pipeline had a golden output to check against: a finished quotation with ten drawing entries and eighteen lines.

Most drawings had multiple cut lengths. One drawing alone had nine — seven under the bare die, one under cavity -1, one under cavity -2. The customer wasn’t ordering one thing; they were ordering nine different cut lengths of the same extrusion profile, each with its own quantity and length.

A quotation line isn’t a drawing. It’s a cut length. The drawing is the profile — geometry, alloy, weight class. The line is one order of that profile at a specific length. The structure in the downstream quotation format confirms this: the drawing entry holds the profile, and the line entries are nested under it.

The merge key became (drawing, part_number). Each email cut-length, identified by its customer part number, attaches to its drawing entry as a separate line. I updated the merge, re-ran the golden, got eighteen lines. Good.


Second correction: when there’s no part number, length is identity

A few days later: a different RFQ. Two cut lengths of the same die, no customer part number on either:

Profile T2986   6005-T5 at 192" Length, Mill Finish
Profile T2986   6005-T5 at 85.5" Length, Mill Finish

My line identity was (drawing, part_number). With no part number, both lines keyed to ("T2986", ""). The email de-duplication logic saw two records with the same key, kept the first, and treated the second length as a conflict to be flagged — which was then discarded. The dashboard showed one line at 192”. The 85.5” cut vanished silently.

The fix: when a line has no customer part number, its length is part of its identity. Two lines under one die with different lengths are two distinct quotation lines. The same length restated across threads is one line mentioned twice.

Key becomes (drawing, part_number or length). The tradeoff: if someone typos a length across threads — 85.5 versus 85.6 — you get two lines instead of one conflict. I judged that the lesser evil. A line a trader can delete is better than a line that was silently dropped.


Third correction: finish is also identity

Another RFQ. One part, two finishes, two quantities:

Part #1548, ¼" X 8" ADA Saddle extrusion
EAU:
30,000 mill finish
8,000 black ano finish
Length: 151", 6063-T5

The customer wants 30,000 mill finish and 8,000 black anodize of the same part at the same length. In the downstream format, that’s two finish groups under one drawing, each with its own line entries — two lines, both referencing part 1548.

My identity was (drawing, part_number or length). Both records keyed to the same thing. The second record — the anodize finish with 8,000 pieces — was discarded. It survived only as a conflict record on the finish field, which was also discarded. The dashboard showed one line: mill finish, 30,000. The anodize order was gone.

Finish joined the key. A line’s identity is now the full tuple: (drawing, part_number or length, finish_group). The finish group is the complete (grade, class, color, color_code) — not just “Ano” but “Ano, 15um, Black” — because the same part in two colors under one drawing are also two distinct lines.

Same tradeoff as before: a finish typo’d differently across threads becomes two lines instead of one conflict. Same judgment: surfacing the extra line is safer than dropping one.


The twist: alloy splits differently

At this point I expected alloy to be next. A die quoted in two alloys — 6061 and 6063 — looks like the same pattern. Same die, two variants, should split into two lines the same way finish does.

It doesn’t. And the reason isn’t in the domain. It’s in the output schema.

The downstream format carries alloy at the drawing level — one alloy per drawing entry, no per-line alloy slot. A line has no place to put a second alloy. If I tried to express “same die, two alloys” as two lines under one drawing, the alloy would collapse on export: the drawing entry would carry whichever alloy I wrote last, and the distinction would be lost.

Two alloys means two drawings, not two lines. I gave them a parenthesised variant suffix so they get distinct drawing-level entries that share the same die number for cost grouping but differ in alloy. The trader creates a variant by editing a line’s alloy and getting a prompt: split this cut into a new drawing variant, or change the whole die’s alloy?

Finish splits at the line level because the output format has a native finish group structure. Alloy splits at the drawing level because the output format has no per-line alloy field. The same surface phenomenon — one die, two variants — has two different structural answers, forced entirely by where the output schema puts the field.


What I should have done first

Nothing I described above was derivable from first principles. I could read the output spec, understand the three-document structure, and still not know that finish belongs in the line key and alloy doesn’t. The spec tells you the output shape. It doesn’t tell you what happens when the input violates your assumptions about what a line is.

The corpus did. Each RFQ taught me something a spec reading couldn’t: that most drawings have multiple cut lengths, that part numbers are often absent, that one part in two finishes is two orders not one, that alloy lives at a different level than finish.

The document corpus wasn’t test data. It was the specification — the part that tells you what a quotation line actually is.

tags: #systems share on x