Lessons · Lesson 4 of 5
Accountable is not liable
How the delay engine decides who is accountable for an order shipping late, which of its five parties it can never name, and the two functions that would settle the cost if anything called them.
Lesson 4 of 5 · 22 min
What this lesson is about
When an order ships late, two different questions get asked and they sound alike. Who caused it. Who pays for it. The first is a matter of record and the second is a matter of contract. Software can do a lot for the first, and almost nothing for the second on its own.
This application has an engine for the first question, and it is a good one. It also contains, fully written and fully tested, the machinery for the second question. That machinery is not connected to anything. This lesson explains both halves, because knowing what is built and unused is as useful as knowing what is missing.
What the engine measures
The engine builds a chain of milestones for one order. Each milestone carries a planned date, an actual date, and an owning party. It then compares the two dates on every milestone and adds up the days.
Three rules govern what counts, and each one is a deliberate refusal to guess.
- A milestone with no actual date contributes nothing. An overdue stage that has not finished yet is not treated as though it finished today.
- A milestone that finished early or on time contributes nothing. Only positive slip is counted.
- Total slip is the sum of every positive milestone slip, and each party's share is its own slip divided by that total.
The chain is assembled from three sources. Production stages with both a planned and an actual end date, owned by the factory. The order's ex-factory and ship dates, planned against actual, also owned by the factory. And each purchase order on the order, comparing its required-by date against the last goods-receipt date recorded on it, owned by the supplier. A purchase order only contributes once it is marked received.
Cascade counting, worked through
This is where the arithmetic surprises people, so here it is with real dates on ORD-1358. One thing went wrong. The fabric arrived six days after the date the purchase order asked for.
Everything downstream moved by the same six days. Cut started late and ended late. Sew ended late. The order left the factory late, and the container sailed late.
| Milestone | Owner | Slip in days |
|---|---|---|
| Materials: PO-1094 | Supplier | Six |
| Production: Cut | Factory | Six |
| Production: Sew | Factory | Six |
| Ex-factory | Factory | Six |
| Ship | Factory | Six |
| Total attributable slip | — | Thirty |
The factory owns four of those five milestones, so it owns twenty-four of the thirty days, which is 80% of the total. The supplier owns six days, which is 20%. The line the app writes on Nadeesha's exception card reads "Factory accountable — 24 days late (80% of the slip)".
Read that against what actually happened. One supplier was six days late and nothing else went wrong. The order shipped six days late, which the engine also records separately and correctly as the ship slip.
The engine is not broken. It is measuring exactly what it says it measures, which is the sum of positive slips per owner. It has no model of cause, so it cannot know that four of those five slips are the same slip seen four times.
The half that is built and unused
The engine exports three functions. One attributes slip to parties, and that one is wired into the app. The home page calls it once for every order in the exception feed, and prints the resulting line on the card.
The other two are about money, and nothing in the application calls either of them.
The first settles a single cost onto one party. Give it an amount and a cause, and it returns the amount, the party that bears it, and how that party was chosen. The cause can be explicit, naming a party directly, in which case the basis it records says simply that the cause was explicit. Or the cause can be the slip itself, in which case it picks the party with the largest share, and records a basis saying that this was the root-cause slip at 80% of the total. It refuses outright to settle a slip cause when no party slipped, rather than picking one.
The second splits a cost across every slipped party in proportion to their share. It refuses when nothing slipped.
Both are complete. Both validate their inputs and reject a negative or non-finite amount. Both are covered by tests, including the air-freight case the file's own comment names. Search the application for either of them outside its own test file and you find nothing.
Where the line appears
One line, in one place. It is computed on the home page for each order that already has an exception, and rendered on that order's exception card.
It is not on the order detail page, not in a report, and not on the supplier record. There is no history of it either, so an accountability line is a statement about the milestones as they stand right now. Complete a stage late today and the line changes today, with nothing keeping what it said last week.
Check yourselfSanjeewa reads that the factory is accountable for 80% of ORD-1358's delay and wants to take it up with Chathura. Say what you would check first, and why the number might be misleading here.Show the answer
Check whether the milestones counted against the factory are independent or consequential. The engine sums positive slips per owner with no model of cause, so one late input that pushes four downstream stages by the same amount is counted four times against whoever owns those stages. On this order a single six-day fabric delay produces twenty-four days of factory slip and six of supplier slip, which is where 80% and 20% come from. The ship slip, recorded separately, is six days, and that is the number that matches what the buyer experienced. Before the conversation with Chathura, open the chain and ask which stages started late only because the one before them did.
Check yourselfA brand delays a fit approval by three weeks and the order ships late as a result. Describe what the accountability line will say, and explain why.Show the answer
It will name the factory, or the supplier, or nothing at all, and it will never name the brand. The chain builder builds milestones from production stages, the ex-factory and ship dates, and purchase-order receipts. Those are owned by the factory and the supplier only. Brand is a valid party in the engine's type, and no code path ever assigns it. So the three weeks the brand cost will appear in the chain as slip on whichever factory stages were pushed by it, and the line will read that the factory is accountable. That is the strongest reason to treat the line as a prompt rather than a finding, and to keep the approval dates themselves where a person can read them.
Prompt · Is that accountability line telling me what I think?
When the exception card names a party and you are about to repeat it to somebody.
Help me read a MerchandiserOS accountability line properly before I act on it. I will tell you: the line the exception card shows, the order's milestones with their planned and actual dates, and who I was about to blame. The engine sums positive slip per owning party. A milestone with no actual date contributes nothing. An early or on-time milestone contributes nothing. It builds the chain from production stages with both a planned and an actual end, the ex-factory and ship dates, and each received purchase order's required-by date against its last goods receipt. Production, ex-factory and ship are owned by the factory. Purchase orders are owned by the supplier. Brand, agent and forwarder exist as parties in the engine and no code path ever assigns them, so those three can never appear in the answer. The engine has no model of cause, so one late input that pushes four downstream stages is counted four times against whoever owns those stages. Work through my milestones and reproduce the calculation, showing each party's days and share. Then tell me which of the counted slips are independent failures, and which are the same failure appearing again downstream. Then tell me the ship slip on its own, because that is the number the buyer actually experienced. Finally, if the real cause was a party the engine cannot name, say so plainly and tell me where the evidence for it lives instead.
AI can make mistakes — check anything you act on.