Conversation
The cart passes its payments and change legs as live Vue arrays. dbBridge.addPendingInvoice and addPendingPurchase wrote them to IndexedDB (or sent them over IPC) as-is, and structured clone throws DataCloneError on a Proxy, so a cash sale made offline failed with "Failed to save invoice offline". Run both records through sanitizeForIdb first, which idbService already used for everything else. It moves to its own module so dbBridge can use it without pulling in Dexie.
An offline sale in the browser was queued and the cart cleared, but nothing printed: the offline branches of the payment dialog never called a print function, the server's /printview is unreachable offline, and the receipt layout was only cached in Electron. - Cache the receipt layout for offline-mode profiles in the browser too, when a shift opens or is resumed. - Keep a receipt snapshot with each queued invoice, beside the invoice data so it is never sent to the server. - Complete offline sales through useOfflineSale: queue, print from the snapshot and cached layout with a hidden iframe (OFFLINE-<id> until it syncs), then clear the cart. A failed print does not lose the sale; a failed save keeps the cart.
- printHtml prints from a hidden iframe and cleans up after printing. - printReceiptOffline uses the snapshot and cached layout, makes no network call, and explains when no layout is cached. - completeOfflineSale queues with the receipt, prints only when asked, keeps the cart when saving fails. - The receipt is stored beside the invoice and never synced. - The layout cache is filled for offline-mode profiles only, and not while offline.
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.
What
Prints the receipt for a sale completed offline in the browser POS, from local data, when the cashier chooses Save & Print.
Why
In the browser, both offline branches of
PaymentDialog.submitPayment(the!isOnline()branch and the network-error fallback) queue the invoice and clear the cart, but never print, even for Save & Print. Online printing opens/printview, which isn't reachable offline. The receipt layout (get_receipt_context) was cached only in Electron, and the receipt snapshot was kept only by the Electron path. A till that loses its connection can take payment but can't hand the customer a receipt.Changes
frontend/src/stores/posStore.ts:refreshReceiptContextalso caches the receipt layout in the browser for profiles withuse_offline_mode, when a shift is opened or resumed (never while offline).offlineStore.saveOfflineanddbBridge.addPendingInvoicestore areceiptsnapshot next todata(new optionalPendingInvoice.receipt). Sync still sends onlydatatocreate_invoice.frontend/src/composables/usePrintInvoice.ts:printReceiptOffline(snapshot): builds the receipt withbuildReceiptHtmland the cached layout, and makes no network call. If no layout is cached, it shows a clear message instead.printHtml(html): prints from a hidden iframe, which popup blockers don't catch after anawait, then removes the iframe.frontend/src/composables/useOfflineSale.ts:completeOfflineSalequeues the invoice with its snapshot, prints it asOFFLINE-<id>when asked, records that number as the last invoice, and clears the cart. A failed print doesn't lose the sale; a failed save keeps the cart.frontend/src/components/dialogs/PaymentDialog.vue: both offline branches callcompleteOfflineSale.offlinePrint.spec.ts: the iframe printing, snapshot and layout, no network calls, and the missing-layout message.offlineSale.spec.ts: queueing and printing order, Save without print, Print Last, and the failure cases.offlineReceiptStorage.spec.ts: the receipt stored but never synced, and the layout cached only for offline-mode profiles and not while offline.dbBridge.spec.ts: the receipt stored beside the invoice data.