The kitchen reads "less spicy" - #744
Merged
Merged
Conversation
Release: what is on the plate, and the menu that shows it
Owner: "whenver i start polling, i see all prints are going. i dont know how 10 or 15 prints going". The chain, end to end: 1. The server keeps offering a job until last_printed_change_index advances past it. That index is the durable guard. 2. It only advances when POST /sales/markKitchenPrinted succeeds. 3. That call's answer was never looked at. fetch does not throw on a 401 or a 500 - it resolves with ok:false - so the very next line logged "Marked N order(s) as printed" whatever came back. 4. Within one run, the in-memory set hid it. 5. On a restart that set is empty, the server is still offering everything from today, and the whole day prints again. Ten or fifteen tickets, exactly as described. So the ledger in the previous commit stops the reprint, and this stops the backlog that fed it. The response is checked now, and a failure says what happens next rather than only that it failed - "they will be offered again; the print ledger is what stops them printing twice" is the part somebody reading a log at nine in the evening actually needs. THIS IS THE THIRD TIME IN THIS AREA that a return value which was the only evidence of success was thrown away: the four winspool calls, the result of silentPrint at its call site, and now this. Worth naming as a pattern rather than three separate fixes. The silentPrint one is still not fixed, on purpose: correcting it means retrying failed prints, and retries are how duplicates happen. It wants the queue and a decision.
Owner, holding a ticket: "when item print, item notes not printed. example 'less spicy' not printed in the kot. its bad very bad". He is right, and it is worse than it looks. The note is the one line on a ticket the kitchen cannot work out for itself - the dish, the table and the quantity a cook could reconstruct, the note they cannot. A customer who asks for something, is told yes, and does not get it blames the restaurant, and the restaurant never finds out it happened. WHERE IT WAS LOST, and not where anybody would look first. The note was stored correctly all along. _priceOnlineLine puts it on the sale item as item_description, and both ticket builders print it - escpos-kot renders ** less spicy ** under the dish when the field is there. Reading the printing code finds nothing wrong, because nothing is. But the kitchen ticket is not printed from sale.items. The poller builds its print jobs out of changes[].items - the record of what changed - and that list carried eight fields: id, name, quantity, process, code, unit, price, total. No note. FOUR places build that list and all four dropped it: a new order, an amended line, a cancelled line, and a line removed from the order. The fourth was nearly missed. It reads from a snapshot of the existing items taken earlier in the same function, and that snapshot did not carry the note either, so it needed fixing in two places rather than one. A removal ticket says which dish to stop, and a table with two of the same dish is told apart by the note - exactly the case where getting it wrong cancels the wrong plate. On an amendment the request's note wins over the stored one, because the request carries what the person has only now said and the stored copy is what they said before. Reading the stored one first would quietly ignore a change of mind. Also in here: the acknowledgement check from the print-ledger work, which was pushed after #741 had already been merged and so never reached main. Without it a failed markKitchenPrinted still logs success, the server keeps offering the same jobs, and a restart prints the whole day again.
Contributor
|
Merged to Try it at https://develop.posnic.io, or run it yourself: git fetch origin develop && git checkout develop
npm install && npm --prefix api install
npm run dev # then http://localhost:3000When you have tested it, say what you did and what happened, and set Reporting that something is broken is as useful as fixing it. It is |
This was referenced Sep 15, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Right, and worse than it looks. The note is the one line on a ticket the kitchen
cannot work out for itself — the dish, the table and the quantity a cook
could reconstruct; the note they cannot. A customer who asks for something, is
told yes, and does not get it blames the restaurant, and the restaurant never
finds out.
Where it was lost, and not where anybody would look
The note was stored correctly all along.
_priceOnlineLineputs it on thesale item as
item_description, and both ticket builders print it —escpos-kotrenders
** less spicy **under the dish when the field is there.Reading the printing code finds nothing wrong, because nothing is.
But the kitchen ticket is not printed from
sale.items. The poller buildsits print jobs out of
changes[].items, the record of what changed, and thatlist carried eight fields:
No note. Four places build that list and all four dropped it: a new order,
an amended line, a cancelled line, and a line removed from the order.
The fourth was nearly missed
The removed-line branch reads from a snapshot of the existing items taken
earlier in the same function, and that snapshot did not carry the note
either — so it needed fixing in two places rather than one.
It matters more than it sounds: a removal ticket says which dish to stop, and
a table with two of the same dish is told apart by the note. That is exactly the
case where getting it wrong cancels the wrong plate.
One ordering decision
On an amendment the request's note wins over the stored one, because the
request carries what the person has only now said and the stored copy is what
they said before. Reading the stored one first would quietly ignore a change of
mind.
Also in here, and it needs saying
The acknowledgement check from the print-ledger work. It was pushed after
#741 had already been merged, so it never reached
main. Without it a failedmarkKitchenPrintedstill logs success, the server keeps offering the samejobs, and a restart prints the whole day again — the ten-to-fifteen-ticket
storm.
I checked the packaged build before noticing: the ledger is in
main, theacknowledgement check is not.
Tests
7 new. The one that matters asserts every
changesItemslist carries thenote, not a specific one — the bug was one place being right and three silently
not, so a test naming one would have passed while the kitchen still got nothing.
Two notes for whoever writes the next test here: my first finder matched
item_quantity: qtyand swept up ordinary sale-item constructions with it, andmy first search for the note mapping used an 8,000-character slice when the
mapping sits 450 lines into the function. Both are anchored properly now.
API suite: 10,625 passing.