Skip to content

Add raw receipt printing#272

Open
lubshad wants to merge 5 commits into
BrainWise-DEV:developfrom
lubshad:feature/raw-printing-qz-tray
Open

Add raw receipt printing#272
lubshad wants to merge 5 commits into
BrainWise-DEV:developfrom
lubshad:feature/raw-printing-qz-tray

Conversation

@lubshad

@lubshad lubshad commented May 23, 2026

Copy link
Copy Markdown
Contributor

Added a new raw ESC/POS printing method using QZ Tray silent printing.

When the selected print format type is set to Raw, invoices are printed using direct ESC/POS commands instead of HTML-to-image rendering, improving compatibility and reliability on thermal printers.

Most of the thermal printers have issue when printing converted html image ... for thermal printers its better and fast if we do raw command printing ...

Also supports drawer opening and paper cutting through the commands..

Before
PHOTO-2026-05-23-13-19-15 2

After
PHOTO-2026-05-25-17-03-16

@MohamedAliSmk

Copy link
Copy Markdown
Collaborator

Critical — Should Fix Before Merge

1. Browser Print Path Routes Raw Formats to QZ Tray

File: POS/src/utils/printInvoice.js (lines ~342–345)

When silentPrint is off, printInvoice() still calls rawPrintInvoice() for raw formats. That sends output to QZ Tray instead of opening the browser print dialog.

Cashiers who disable silent print but assign an ESC/POS format on their POS Profile will get QZ errors (or silent printing) when they expect a normal browser popup.

Fix: Keep raw dispatch in the silent path only. In printInvoice(), either:

  • Fall back to the HTML default format for browser printing, or
  • Show a clear error (“ESC/POS requires silent print / QZ Tray”), or
  • Open a preview that cannot work for raw (not recommended).

2. Offline / Local-Only Invoices Never Use ESC/POS

Files: printInvoice.jssilentPrintInvoiceFromDoc(), printInvoiceCustom(), local branch of printWithSilentFallback()

Offline invoices (OFFLINE-*, pos_offline_*) always print via buildReceiptHTML() + qzPrintHTML(). They never use the ESC/POS template even when the POS Profile's print format is POS Next ESC/POS Receipt.

Stores that rely on raw thermal printing will get pixel-rendered HTML receipts for offline sales — different layout, slower, and potentially misaligned on thermal printers.

Fix: For offline docs with a raw profile format, either:

  • Build a client-side ESC/POS command string (heavy), or
  • Document that offline mode always uses HTML receipt, or
  • Queue raw print after sync (deferred).

At minimum, document the limitation and align offline fallback behavior with user expectations.


Medium Priority

3. Browser Fallback Uses Wrong Format Variable

File: POS/src/utils/printInvoice.js (lines ~541–544)

const fallbackFormat = (await isRawPrintFormat(resolvedPrintFormat))
    ? DEFAULT_PRINT_FORMAT
    : printFormat

When silent print fails and the format is not raw, fallback uses the original printFormat argument (often null) instead of resolvedPrintFormat. That can drop the POS Profile format on browser fallback.

Fix: Use resolvedPrintFormat (or re-resolve from profile) for the non-raw fallback case.


4. ESC/POS Template Missing Parity with HTML Receipt

File: pos_next_esc_pos_receipt.json

Compared to buildReceiptHTML() / POS Next Receipt, the ESC/POS template omits:

Feature HTML receipt ESC/POS template
Offline pending badge Yes No
Partial payment status Yes No
Additional discount % Yes Amount only
Custom header/footer from invoice Yes Hardcoded
quantity vs qty field Both handled qty only

Offline hydration maps quantity → items but ESC/POS Jinja uses item.qty — server-side synced invoices use qty, so this mainly affects edge cases.

Suggestion: Align templates or document intentional differences.


5. printInvoice() Does Not Resolve POS Profile Format

File: POS/src/utils/printInvoice.js

printInvoiceByName() resolves format from POS Profile; printInvoice(invoiceData) does not — it uses printFormat || DEFAULT_PRINT_FORMAT.

POSSale.vue calls printInvoice(invoiceData) when the invoice object includes items (typical post-checkout). ESC/POS will not activate unless the caller passes printFormat explicitly.

printWithSilentFallback() was fixed in commit 301991cd; browser path was not.

Suggestion: Resolve print settings inside printInvoice() when printFormat is null and invoiceData.pos_profile is set (same as printInvoiceByName).


6. Uninstall Does Not Remove New Print Format

File: pos_next/uninstall.py

remove_print_formats() only lists "POS Next Receipt". POS Next ESC/POS Receipt is left behind on uninstall, and POS Profiles pointing at it are not reset.

Fix: Add the new format name to the uninstall list (with the same POS Profile reset logic).


7. Name Heuristic for Raw Detection

File: printInvoice.jsisRawPrintFormat()

if (typeof printFormat === "string" && /esc[\s/-]*pos/i.test(printFormat)) {
    return true
}

Any custom format named e.g. "My ESC/POS Layout" is treated as raw without checking raw_printing in the database. Conversely, a raw format without "esc/pos" in the name relies on the API round-trip.

Suggestion: Prefer raw_printing from DB; use the name heuristic only as fallback when metadata fetch fails.


Low Priority / Nits

8. containsRawPrinterCommands() Escape-Byte Heuristic

Detecting /[\x1b\x1d]/ in HTML from get_html_and_style is a reasonable safety net for misconfigured formats, but could theoretically match unrelated binary content. Low risk for receipt HTML.


9. printFormatMetaCache Never Invalidates

If an admin toggles raw_printing on a format during an open POS session, cached metadata will be stale until page reload. Acceptable for most deployments; optional clearPrintFormatMetaCache() on settings refresh.


10. No Automated Tests

No unit tests for isRawPrintFormat, routing logic, or printRawCommands payload shape. Manual QZ Tray testing is required.


@lubshad

lubshad commented Jun 16, 2026

Copy link
Copy Markdown
Contributor Author

Fixed all reported issues ... please check

@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown

This pull request has been automatically marked as stale because it has not had recent activity for 21 days.

To keep this PR open, please:

  • Rebase on the latest develop branch
  • Address any pending review comments
  • Reply with an update on the PR status

If no further activity occurs within the next 14 days, this PR will be automatically closed.

@github-actions github-actions Bot added the stale label Jul 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants