Skip to content

Release: promote develop to main (the printed bill and the kitchen ticket) - #855

Merged
sridharkalaibala merged 10 commits into
mainfrom
develop
Sep 17, 2026
Merged

sridharkalaibala merged 10 commits into
mainfrom
develop

Conversation

@sridharkalaibala

Copy link
Copy Markdown
Contributor

What

The three print PRs merged 26 seconds after release #854 had already taken develop to main, so main has the call date (#853) but none of the bill and kitchen-ticket work. This carries it:

Commits

  • A struck line costs what it draws
  • Two things a printed bill asked for
  • The shop's own words reach the bottom of its own bill

Verified on develop by content

lineBand in escpos-raster-text.js, pairAtColumn in escpos-receipt.js, footer_print in bill-payload.js: all present on develop, all absent on main

Merge with a merge commit, never squash (a squashed release makes the next one conflict on every file).

footer_print is a box on the printing settings screen. A restaurant had
"Thanking You / Visit Again" saved in it and handed every guest a bill
saying "Thank you, please visit again" - the generic line the renderer
falls back to.

Nothing had failed. escpos-receipt reads sale.footer and always has.
bill-payload never set it; the word "footer" did not appear in that file
at all. A setting written, stored, offered on a screen, and read by
nobody. The fourth of this shape found today.

Trimmed, empty lines dropped, and capped at four lines of sixty-four
characters: it is free text on a document a customer keeps, printed on a
roll that does not stop, so a paste accident should cost a line rather
than a roll of paper. CRLF from a Windows textarea is handled without
caring which arrived.

7 tests, and the last one is the one that matters: it reads every
sale.<field> out of the renderer and asks the payload for each. That
sweep is what would have caught this. It found six more the renderer
reads and nothing feeds - cashier, branch, payments, change, itemCount,
totalWeight - and they are NAMED in the test rather than quietly
allowed, because a named gap is the opposite of this bug. Two are
honestly conditional (a BILL is unpaid, so payments and change have
nothing to say); four are branches waiting for a caller. Shrink that
list, never grow it.
Both came off paper this evening rather than out of a test.

1. A CANCELLATION TAKES THE FAST PATH

Owner: "new order print is so so fast. very immediate but cancel order
took some time."

The routing read `!isCancellation && this.hardware`, so every
cancellation skipped the 124ms byte path and spun up a hidden
BrowserWindow to render HTML. Correct when written: ESC/POS cannot draw
a line THROUGH text and only the HTML ticket could.

The timestamps say the rest. The exclusion was written at 01:24. The
byte builder took strikeCancelled at 12:46 and escpos-raster-text drew
the stroke at 13:16. The capability landed eleven hours later and nobody
flipped the switch, so every cancellation since paid for a window it no
longer needed.

One line. A plain ticket is 294 bytes, a cancelled one 3,670 - under half
a second even on slow serial, against about a second for the window.

Verified on a real POS-80C: the ticket printed through the byte path
with the stroke on it, and a three-way comparison slip confirmed the dots
land through the words on that hardware. Three earlier attempts died on
that exact printer, so paper was the only way to know.

The three routing tests are INVERTED rather than deleted, and one more
added: the bytes must still be told to strike, or the fast path would
print a cancelled dish that looks live.

2. THE COUNT SITS UNDER THE COUNTS

Owner: "total quantity just make it same alignment of quantity column.
not to the last."

Right, and the reason is worth keeping: a count printed hard against the
right edge sits under AMOUNT, the one column on a bill where a number
must not be mistaken for money.

itemTable now records where the QTY column ends - the only place the
widths are known - and pairAtColumn aims at it, falling back to the
ordinary right-aligned pair when there is no table to aim at. Asserted by
column index, both at 40, with a test that also refuses it drifting back
under the money column.

2850 desktop tests pass.
A cancelled dish on a kitchen ticket is crossed out as a raster, because
this printer has no strike-through and every cheaper idea failed on the
paper. That raster was 1,736 bytes however short the dish: the whole
48-column, 24-row grid, blank cells priced the same as letters. With twenty
metres of cable to the kitchen printer the owner could see it: "new order
print is so so fast. very immediate but cancel order took some time."

Three cuts, each printed on his POS-80C, the last chosen by him off the
paper:

  only the cells with text are sent      pair() composes a struck line as
                                         NAME, two spaces, count, instead of
                                         padding the count to the right edge
  only the rows with ink are sent        measured from the characters on the
                                         line, so an accented capital still
                                         gets its top row and uppercase pays
                                         for 18 rows, not 24
  half the columns are sent              GS v 0 with m = 1, and the printer
                                         doubles them back; each pair of
                                         source columns is ORed so a one-dot
                                         stem survives

"SUNSET COOLER" goes from 1,736 bytes to 188. A cancellation ticket with
three struck dishes is 1,493 bytes, smaller than one struck line was.

The preview parser now carries m, so a preview that draws the raster knows
the printer doubles it. The tests pin the new geometry dot for dot against
the font table and refuse the old price.
…-path

Two things a printed bill asked for
The shop's own words reach the bottom of its own bill
@sridharkalaibala
sridharkalaibala merged commit 08cd65d into main Sep 17, 2026
21 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant