Orders that place themselves
A trade supplier raised every wholesaler order by hand, one line at a time, every morning. We built the thing that pools the morning into one list, works out who each item should come from, and places the lot on a single click.
A Monday morning, start to finish
The whole run, looping. Article names and wholesalers are redacted, the sequence and the decisions are exactly what it does. Watch the fourth line. It steps aside because nothing has been bought from that wholesaler before, and that is the thing that makes one click safe.
The process, before
Customer orders land overnight. Every one needs stock ordered from a wholesaler.
So each morning a person opened the purchase list, picked a line, looked it up on a wholesaler site, checked the price, checked whether it was actually in stock, raised the order, sent it, went back, picked the next line. The same short sequence, over and over, before the vans went out.
The morning, before
Everything either side of that red step is instant. The whole morning queues behind one person repeating the same short sequence. They put the cost at 9 to 10 hours a week between two people.
Nobody designed it that way. It's what the software allowed on day 1, and nobody had a reason to fight it.
What the helper actually does
It runs as one pass over the morning, in five steps.
The same morning, now
Same orders, same wholesalers, same system. Nobody learned a new tool. The dashed step is the one we left for a person on purpose.
1. Work out what's actually needed. It reads stock and open orders straight out of JTL-Wawi and computes needed = in orders − free stock − already on the way. Anything at zero or below never reaches the list. A recent run came out at 89 lines.
2. Find something to search with. Each line needs a barcode or a manufacturer number. If JTL holds neither, no wholesaler is asked at all, and the line is returned as an article record to fix rather than a failure.
3. Ask every wholesaler at once. Four portals, in parallel. Each one signs in once per run, and each is asked using the number that portal actually indexes: one searches on barcode, two on manufacturer number, one on either. It reads the net price, waits for the availability figure separately because it arrives after the price, and comes back with one of six answers: a price and a yes, a price and a date, not in stock, nothing found, a wording it hasn't been taught, or the site didn't answer.
4. Choose. Four rules, tried in order, first match wins:
- A standing choice someone made on this article, shown with its date and an undo.
- The wholesaler recorded on the article itself.
- A preferred partner within tolerance of the best price.
- Cheapest today.
The line always says which rule decided it, and if the winner wasn't the cheapest, it names who was.
What comes back, line by line
| Line | Article | Going to | Because | Ending |
|---|---|---|---|---|
| 01 | Sealing tape | Wholesaler A | Cheapest today | Ready to order |
| 02 | Circulation pump | Wholesaler C | Standing choice | Ready to order |
| 03 | Thermostat | Wholesaler B | First time from here | Confirm once |
| 04 | Heat pump | — | Over the value limit | Your call |
| 05 | Flange set | — | No number to search with | Article record |
Illustrative, not a real run. Every line ends in one of six places, and the ending says whose job it is: nobody's, yours, ours, or the article data's. A line that needs a person says why.
5. Place it. One order per wholesaler, not one per line. The wholesaler's own order number comes back, gets recorded on our side first, then written into JTL as a purchase order. If that write fails the number is kept anyway and the line says so, retryable. Losing an order number because a second system was briefly unavailable is not an acceptable failure.
Three traps it's built around
Every one of these came out of the build, and each would have looked entirely plausible in production.
Never the first result. A manufacturer-number search put a 580 euro radiator above the 76 euro sealing tape that number belonged to. A row has to carry our own number or a person looks at it.
Never a number from a wording it doesn't know. "Lieferung in 24 Stunden" contains a 24. Read that as a quantity and you order two dozen of something nobody wanted. An unrecognised availability wording quotes itself back instead of being guessed at, which is how six of the seven wordings it now knows were learned at no cost.
Never the price with a line through it. Every row on one portal shows a net price beside a struck-out list price. On one heat pump those two numbers were 4.097,43 and 7.731,00. Reading the wrong one is a mistake that never announces itself.
What we deliberately did not automate
The interesting part of this build is the list of things it refuses to do.
- It doesn't buy from a wholesaler it hasn't bought this article from before. It shows their name for the item beside yours and asks once. One click, and it never asks again.
- It doesn't place anything over a value limit, or anything where the match couldn't be proved by a number.
- It doesn't touch lines marked order-by-email or order-by-phone. Those come back with the contact details on the card.
- It doesn't run at all unless a person presses the button and the mode is live. Default is a preview that buys nothing.
Where it stands
Live, running against four wholesalers, with a person approving each batch. It moves to fully automatic once it's been boring for long enough, and not before. Ordering stock is spending money, and software that spends money without anyone seeing it first hasn't earned that yet.
