Layaway
Hyvä POS is in closed beta
Hyvä POS is currently in a closed beta (pilot phase) with a small group of merchants. It is not yet generally available: the App Store release follows the pilot, and features and configuration may still change, possibly in backwards-incompatible ways, before the general release. Want to take part? Sign up at hyva.io/pos.
A customer wants the item held: they pay a deposit now and the balance later. Layaway records that as a Magento order, with a payment schedule, stock reservation, and drawer reconciliation.
How a Layaway Works
At checkout the cashier places the sale as a layaway and takes a deposit: any amount at or above the configured minimum percentage. From there:
- The order books in Magento immediately, for the full cart, in a pending-payment state. The goods are reserved: Magento's inventory reservation holds the stock until the layaway settles or is cancelled.
- Each payment (the deposit, any top-up, the final balance) is taken at the register like any tender and prints its own receipt showing the amount captured, the running total paid, the balance owed, and the expiry date.
- When the balance reaches zero the layaway flips to ready to settle: the goods hand over, and the order continues through Magento's normal invoice and fulfillment flow.
Because sharing happens through Magento, any register at the location can take the next payment or settle the balance; the customer is not tied to the counter where they started. Every payment lands in the register report for the day it was taken, on its own layaway payments line: the money joins the cash and card totals (so the drawer reconciles), while the day's sales figure stays untouched, because the revenue was already booked when the layaway was placed.
How It Books in Magento
The order places under a dedicated pos_layaway payment method: under a stock offline method Magento would auto-capture the full total at placement. Alongside the order, placement creates a full invoice in the open state, so accounting integrations that drive on Magento invoices book the revenue and VAT at placement, matching the signed POS receipt, and the open invoice shows the outstanding balance as a real receivable in the admin. (Advance payments make VAT chargeable when received; invoicing at placement declares it once, on the conservative side, instead of per payment, which Magento's item-based invoices could not represent anyway.)
Each payment then updates the order's own paid and due totals and adds an order comment recording the amount, the tender the customer used, and the payment reference (the terminal transaction id for card payments, the POS receipt number for cash): a per-payment audit trail the register and the back office both read. That reference also makes retries safe: if a register resends a payment after a dropped connection, Magento recognises it and books nothing twice. The running numbers (deposit, balance owed, expiry, status) live as pos_layaway_* attributes on the order itself; there is no separate layaway table to reconcile.
When the balance reaches zero, the invoice is marked paid: by the register's final payment, or from the admin: Capture Offline on the open invoice is the admin-side settlement action for a bank-transferred balance, and it flips the layaway to ready to settle in the register's list without anyone at the counter touching it. Settlement then ships the goods through Magento's normal fulfillment flow.
Statuses and Expiry
A layaway carries its own status, independent of the Magento order state:
- Open: balance outstanding, payments being taken.
- Ready to settle: fully paid, awaiting handover.
- Stale: the expiry date passed before the customer settled. A scheduled job checks hourly and flags overdue layaways, adding a comment to the order; the register's Stale filter lists them so staff can chase or cancel. Nothing is cancelled automatically.
- Cancelled: closed by staff, deposit handled per your rules (below).
Each layaway gets an expiry date at placement, from the configured expiry period (default 30 days).
Cancelling a Layaway
Cancelling from the layaway detail asks for an optional reason and shows the money math before confirming:
- A cancellation fee is retained: the configured percentage of what the customer has paid so far, money and store credit or gift card together (default 0). Reward points that applied as a discount are part of the price, not of the deposit: the fee is charged on the rest, and the points come back through the vendor module when the order is cancelled. The cashier can adjust the percentage per cancellation. For an abandoned layaway the merchant's policy might set it to 100%: deposit forfeited, nothing handed back.
- Magento issues a credit memo for what was paid, money and credit together, less the retained fee. The memo carries no goods, since none were handed over: the open placement invoice is cancelled, so the never-delivered items leave the books with their VAT, and the order is cancelled, which releases the reserved stock. Credit the deposit spent goes back to the customer's balance through the memo; the money part is what the register hands back. The fee and refund breakdown land in the order's comment history.
- The remainder is refunded from the cash drawer: a cash refund is paid out of the drawer and logged (the drawer count and the Z report's cash-refunds line both see it), a card deposit is reversed on the terminal by the cashier. A cancellation receipt prints either way, with the refunded amount, the fee retained and the credit memo reference, fiscally signed where signing applies.
Note that the VAT on the retained fee is for the merchant's accountant to decide: EU case law generally treats a genuine cancellation fee as compensation outside VAT scope, but a "fee" that equals essentially the full price is treated as taxable consideration. The credit memo gives the accountant a document to adjust from, whichever way they rule.
A fully paid layaway cannot be cancelled this way; once it is ready to settle, use the normal returns flow instead.
Where the Data Lives
A layaway is a Magento order, not a parallel record:
- The order sits in
sales_orderlike any sale, with the layaway specifics stored as extra columns on the order: deposit amount, balance owed, expiry date, status, and the tender used for the deposit (which is how the refund on cancellation knows where the money should go back to). - The amounts paid and due use the order's own paid/due totals, so the admin order view, accounting exports and ERP integrations see standard Magento numbers, with no side ledger to reconcile.
- Every payment produces a receipt on the device, marked as deposit, top-up or settlement; with receipt sync those receipts mirror to Magento with the layaway amounts on them. Top-up and settlement receipts are titled Payment Receipt rather than Customer Receipt, carry no VAT rows, and say so: the full order's VAT sits on the deposit receipt, printed when the layaway was placed. Reprinting the VAT on every payment would declare the same tax twice.
Configuration
The limits are Magento settings under Stores → Configuration → Hyvä POS → Terminal Defaults → Layaway Defaults:
| Setting | Default | What it does |
|---|---|---|
| Minimum Deposit (%) | 25 | Smallest deposit a cashier may take when placing a sale as layaway. |
| Expiry (days) | 30 | Days until an unsettled layaway is flagged stale. |
| Cancellation Fee (%) | 0 | Percentage of the captured payments retained on cancellation. |
Each location can override these, and the values sync to the registers automatically, and the deposit sheet validates against them at the register. There is no per-device version of these numbers; the register enforces what Magento says.
Layaway is currently experimental: enable it per device under Settings → Advanced before Place as Layaway appears at checkout. The scheduled stale-flagging job runs on Magento's default cron, so it needs cron to be running.
What the Cashier Sees
- At checkout, Place as Layaway opens the deposit sheet: cart total, the minimum deposit, the resulting balance, and the expiry date the layaway will get. The deposit is then paid with a normal tender.
- The Layaways tab lists every layaway with filter pills for Open, Stale, Ready and All.
- The detail pane shows total, paid so far, balance owed and days until expiry, lists every payment taken so far (the deposit and each top-up, with tender and payment reference), links straight to the full order and the customer record, and offers cancellation with the fee and refund amounts spelled out before anything happens.
- Take payment asks how much (full balance in one tap, or 25% / 50% chips for a quick top-up) and then opens the register: the customer pays by cash, with change calculated, or by card on the terminal, like any sale. The receipt prints through the configured printer, lands in the Receipts tab for reprints, and the payment shows up in the day's register report.
- The order detail shows the same information: a layaway order carries a Layaway card with the status, the balance, and the payment trail, and payments taken on that register open their receipt with a tap. Open in Layaways jumps to that layaway to take the next payment.
Offline
Placing a layaway works offline like any sale: the deposit is taken at the register and the order joins the offline queue. Taking further payments and cancelling need the connection, because the balance lives on the Magento order. The register says so rather than guess at a balance it cannot verify.
If the connection drops mid-payment (money taken, but Magento unreachable before the balance updated), the receipt and register totals are already recorded on the device, and the payment queues on the Layaways tab with a retry button. Retrying is safe even when the original request did land; Magento recognises the payment reference and books nothing twice.