Partial delivery is where revenue disappears quietly. One deal identifier, a line-level state machine, a field table with real values, and three orphan reports.
Key takeaways
- The revenue-loss mechanism is partial delivery: a four-line order ships in two consignments, the invoice is written against the first, and the line that ran late falls out of everyone's attention.
- The identifiers do not have to be the same number. They have to point at each other in a searchable field - a `deal_id` on every document.
- The link must exist at line level, not document level. An invoice line with no originating `order_line_id` cannot be audited.
- A state machine with defined transitions separates "cancelled", "not delivered" and "delivered but not invoiced" - three states that look identical in a spreadsheet.
- The control is three orphan reports running every morning, not a folder search at month end.
A single deal identifier is a field created with the quote and carried into the order, the delivery note and the invoice. Without it you cannot answer the one question that costs money: which approved and delivered lines were never invoiced. Lost revenue does not sit in the quote that was rejected. It sits in the line that shipped and was forgotten.
How a delivered line never becomes an invoice
Here is the case in numbers. Quote Q-2026-00418 to a business customer, 38,400 ILS before VAT, three lines:
| Line | Description | Qty | Unit price | Amount |
|---|---|---|---|---|
| 1 | Initial implementation | 1 | 18,000 | 18,000 |
| 2 | Annual licences, 12 users | 12 | 1,200 | 14,400 |
| 3 | Training, 4 sessions | 4 | 1,500 | 6,000 |
The quote was approved by email on 3 March. Implementation completed 19 March, licences activated 1 April, training postponed at the customer's request to June. Invoice INV-2026-1123 was issued on 31 March for 18,000. In June two of the four sessions took place, the customer's contact changed jobs, and line three was never invoiced. Six thousand shekels vanished with no alert, because no system held the sentence "line 3 of quote 00418 was approved, partially delivered, and is not yet invoiced".
That is the mechanism. It is not caused by disorganisation; it is caused by the invoice being built against a delivery event rather than against the originating line. With a deal_id at line level, that case appears in the orphan report the day after the second session.
Why is a document-level link not enough?
A document-level link is not enough because delivery and billing are almost never one-to-one. One quote produces one order, but the order produces two delivery notes and three invoices, and sometimes one invoice covers two orders.
- One quote → one order: the simple ratio, and even that breaks when a customer approves part of the quote.
- One order → several delivery notes: normal in any business holding stock or delivering a service in stages.
- Several orders → one invoice: common in consolidated monthly billing for a retained customer.
- One invoice → several receipts: partial payment, instalments, partial credit.
The moment any of those relationships is not one-to-one, an order_id field on the invoice stops answering the question. What is needed is a deal_id on the document and a source_line_id on every line.
The state machine for a deal line
The line, not the document, is the unit that moves between states. Six states and defined transitions only:
draft- written on a quote, not yet sent. Transitions tosent.sent- the quote went to the customer. Transitions toapprovedorlost.approved- the customer approved this line. Transitions todelivered_partial,deliveredorcancelled.delivered_partial- less than the ordered quantity was supplied. Transitions todeliveredorcancelled_remainder.delivered- supplied in full. Single transition: toinvoiced.invoiced- an invoice line points at it. Terminal, except for a credit.
Two rules turn this from a diagram into a mechanism. First: there is no direct transition from approved to invoiced - it must pass through delivery, otherwise nothing records what actually shipped. Second: a price or quantity change after approved does not overwrite the line, it opens a new version referencing the previous one and requires approval. In case 00418, line 3 would have been sitting in delivered_partial with 2 of 4, which is precisely what the orphan report looks for.
The minimum fields on every document
| Field | Example | Appears on |
|---|---|---|
deal_id | D-2026-0418 | Quote, order, delivery note, invoice |
doc_type | quote / order / delivery / invoice | Every document |
doc_number | INV-2026-1123 | Every document |
source_line_id | Q-2026-00418-L3 | Order line, delivery line, invoice line |
line_state | delivered_partial | Deal line |
qty_ordered / qty_delivered / qty_invoiced | 4 / 2 / 0 | Deal line |
version | 2 | A line changed after approval |
changed_by / changed_at | dana / 2026-06-11T09:14+03:00 | Every post-approval change |
The three quantity columns are the heart of it. Any inequality between them is an open commercial question; equality is a closure. A business holding only qty_ordered cannot produce the reports in the next section.
The three orphan reports that recover money
The control is three queries that run every morning and create tasks, not a report to read:
- Approved with no order - lines in
approvedwith no linked order line after three business days. Usually indicates an approval given by phone and never recorded. - Delivered with no invoice - lines in
deliveredordelivered_partialwhereqty_invoicedis belowqty_deliveredbeyond a defined number of days. This is the report that would have caught the 6,000 in case 00418. - Invoice with no source - invoice lines with no
source_line_id. Not necessarily an error, but every such line is revenue that cannot be attributed to a quote, and therefore cannot be measured for profitability.
Each report has an owner and a target date, not just a recipient. A report sent to everybody is nobody's responsibility. The link between this line and a signed document is covered in evidence for a signed quote, and the front end of producing the quote in from call to quote.
What happens when the invoice is issued in another system?
When the invoice is produced in an external system, the identifier has to travel out with it and come back. The practical pattern is sending deal_id and source_line_id in a free-text field the receiving system echoes back, and storing the returned document number on the originating line in the same operation.
Three things break in practice: a system that truncates the free-text field and cuts the identifier short; an invoice created manually in the external interface, which therefore returns with no identifier at all; and a credit note raised against the invoice rather than against the line. In Israel there is an additional field to carry - the allocation number required for invoices above a threshold set in law - and it belongs on the line too. The technical detail is in the invoice allocation number for developers.
Sources
Frequently asked questions
Do all the documents have to carry the same number?
No, and usually they cannot, because the invoicing system generates its own running numbers. What is required is a searchable link field present on every document, preserved even when the document is created elsewhere. Uniform numbering is a convenience; the link is the requirement.
What do you do with orders that arrive on WhatsApp?
Open a record with an identifier before working on them, even when the details are incomplete. A message that stays only in a chat is not part of the process and will therefore never appear in any orphan report. The simple rule: if there is no record, the order does not exist as far as the controls are concerned.
How long should a line sit as delivered-not-invoiced before it alerts?
That is a commercial decision rather than a universal rule, and it should differ by line type. Physical delivery justifies a short threshold of a few days, while staged services may justify weeks. What matters is that the threshold is written down and enforced by a query, rather than depending on whoever happens to look.
What about lines that were already lost in the past?
Run the orphan report backwards over a closed period and you get a finite list of lines delivered but never invoiced. What to do about each one is a commercial conversation with the customer, but producing the list is a technical exercise the moment a line-level link exists.
Keep reading
Related service
Custom Business Software
The internal system that replaces the spreadsheet you outgrew.
About the author
Yehonatan Saadia
Freelance automation, web & MVP developer
I'm Yehonatan Saadia, a senior developer who builds business automation, custom websites, and MVPs for small and mid-sized companies across the US, Europe, and Israel. These guides come from real client work, not theory.
Work with meHave a project like this?
Tell me what you're trying to automate or build. I reply within 24 business hours with a few targeted questions, then we walk through it on a free 30-minute call, with no commitment. You come away with a scope, a timeline and a fixed price - or a straight answer that it isn't worth building.
