A $10 request. A $15 basket. One race condition.
A cashier scans another item while the customer pays. The terminal approves the original amount, while the POS is now looking at a different basket.
This case was reported from a busy Windows store. The failure is at the boundary between an in-flight financial request and mutable checkout state. Moving that register to Linux does not, by itself, resolve the application-level race.
The engineering requirement
A payment needs a stable relationship to the checkout it was created for. The submitted amount, basket, discounts, tax treatment, and tender state must remain attributable to that transaction. New scanner input must not silently redefine a payment already in progress.
The current Core implementation uses a checkout identity, a basket fingerprint, pending-checkout assertions, and request-busy state. The checkout draft pairs its fingerprint with recorded tenders. Before another payment proceeds, the application compares the current basket against that draft; a mismatch requires reconciliation of the existing approval. The exact reported Windows sequence still needs a regression test against the installed build and a real terminal; the presence of guard code is not proof that every input path is covered.
Keep distinct events distinct.
Basket prepared
Items, quantities, prices, tax, and discounts define the amount due.
Tender submitted
A particular checkout sends a particular amount to a terminal.
Response recorded
Approval, decline, partial approval, cancellation, or uncertainty needs explicit treatment.
Sale completed
The invoice and its tender records account for the completed sale.
These stages describe the transaction lifecycle. An application timeout is not automatically a decline; a terminal approval is not automatically a fully recorded invoice; and printing is a separate output step after the transaction’s state is established.
A receive error needs investigation.
Payment development has dealt with USB/serial and TCP communication, cancellation, partial approvals, receive errors, and terminal activity that needs to be reconciled with POS history. The terminal bridge and the register UI each have their own lifecycle.
The interface includes terminal activity records and a PAX recheck action for eligible transactions. The recovery intent is to inspect the existing terminal result and reconnect an approval to the POS record, without issuing a fresh charge. Availability depends on the terminal’s stored transaction information and the specific integration.
Inspect screen | Condition | Required operational response |
|---|---|
| Customer cancels | Record the result and release the appropriate checkout state. Do not complete a paid invoice. |
| Terminal approves only part of the amount | Account for the approved tender and the remaining balance explicitly. |
| Terminal approves but POS response is uncertain | Inspect terminal activity and reconcile the original transaction before retrying. |
| Receipt does not print | Recover receipt output from the correct recorded transaction. Avoid treating printing failure as a reason to recharge. |
| Possible duplicate warning | Stop the automatic retry path and verify terminal history. |
Payment and terminal tests belong on the actual processor application and transport used in the store. A successful TCP test does not establish USB behavior, and a mocked SDK response does not validate the physical device.
Pricing rules are transaction data.
Vaya supports cash and card pricing, flat or percentage discounts, item tax settings, bulk pricing, and multiple tender types. Their interaction matters more than any one calculation in isolation.
For EBT Food, the current Core implementation calculates a tax adjustment against the eligible portion covered by that tender. Taxable and EBT-eligible are separate product attributes. An eligible food item should not be rejected solely because it ordinarily has a tax flag; the eligible EBT-covered amount and the rest of a mixed basket need separate treatment.
Store tax and eligibility configuration must match the merchant’s requirements. The implementation also has to account for discounts, partial EBT coverage, remaining tender, and the receipt breakdown. EBT Cash is a separate tender; the Food benefit’s rules should not be generalized to it.
A useful acceptance basket includes weighted goods, taxable non-food items, eligible food items, a discount, and mixed tender. The expected amounts should be known before the test is run.
Fast input must retain its meaning.
Keyboard-wedge scanners behave like rapid keyboard input; serial scanner/scale devices have a different event path. Both can collide with a changing screen, a login transition, a modal, or a payment request.
The scanner-login work rejects or withholds stale scans that belong to an earlier session or an ambiguous screen state. The operator is asked to review the ticket and rescan missing items. Silently attaching old input to a new cashier’s sale would be a different—and much harder to diagnose—failure.
Accuracy testing follows the input across the whole application: quick categories, barcode lookup, weighted products, price edits, holds, tender dialogs, and rapid consecutive scans. A disabled button alone cannot establish that all entry paths are safe.