POS Screen Design
Every part of the retail POS screen is setup-driven. Nothing is hardcoded — the button strip, the color theme, whether the bottom status bar shows, and how refunds settle back are all per-terminal or per-store toggles you can change without touching code.
- /POS/POSTerminal — terminal-level settings (button strip, manager-auth flags, color theme, dual display, shift/float toggles).
- /POS/StoreCard — store-level settings (return window in days, refund-to-same-tender flag, receipt header / footer).
Require manager approval per button
Any button in the strip can be gated behind a manager-auth prompt (card swipe or Manager ID + PIN). Tick the Mgr column in the Action Strip designer, save, and the next time a cashier taps that button they'll see the manager auth modal first. Cashiers who already hold the underlying POS permission (for example POS.VOID) skip the prompt.
Common patterns:
- Void Line & Void Txn — on by default.
- % Invoice Disc. — on if you don't want cashiers giving away bill-level discounts unsupervised.
- Refund — recommended on for stores where cashiers should not process returns without a manager.
Refund back to same tender
Set at /POS/StoreCard under the store's operational block:
- ON (default) — when a refund is posted, the cashier taps PAY and the refund is auto-settled to the same tenders that were used on the original bill, in the same proportions. If the original bill was ₹500 UPI + ₹500 Cash, a ₹200 partial refund posts ₹100 back on UPI and ₹100 back in Cash. No cashier choice.
- OFF — after tapping PAY the tender picker opens and the cashier chooses which tender to refund to. Use this if you always refund in cash or want operator control.
Stored as Store.RefundSameTender BIT.
Refund workflow — step by step
- Cashier taps the Refund button in the right strip.
- The right context panel switches to Refund — pick a receipt. It lists returnable receipts from the last N days (N =
Store.ReturnWindowDays, default 30). - Cashier can scan the receipt barcode (Code128 printed on every receipt), type the receipt number in the search box, or tap a row.
- The panel switches to a line picker showing every returnable line with a checkbox, a − / + quantity stepper, and a live −₹ refund total.
- Cashier ticks the lines to refund and adjusts the quantity (defaults to full available qty).
- Cashier taps Refund →. The negative-quantity lines appear on the left cart with red minus signs. Nothing is settled yet.
- Cashier taps PAY.
- If Refund to same tender = ON → auto-settled to the original tenders, receipt prints. Done.
- If Refund to same tender = OFF → the tender picker opens for the cashier to choose Cash / UPI / Card etc.
The refund receipt is a separate row in POSTransaction with TransactionType = 'Return' and a receipt number like RTN-STOREXX-000001. Line quantities and amounts are negative. Inventory (ILE) and cost ledger (VLE) reversals post automatically.
Color theme — light-green & others
Terminal-level setting: POSTerminal.ColorTheme. Set via the theme swatches on /POS/POSTerminal. Available palettes:
- light-green (default) — white body, green accents, orange PAY button.
- light — white body, blue accents.
- dark-navy — dark navy, blue accents (classic POS look).
- midnight-purple — dark purple.
- forest-green — dark green.
- rose-gold — dark rose.
- slate-blue — dark slate.
- high-contrast — accessibility.
Cashiers can override the terminal theme on their own device (stored in browser localStorage.mspos-theme-manual). Clearing that flag restores the terminal default.
Layout mode — Retail vs Hospitality
MenuProfile.LayoutMode switches between the two big layouts:
- RetailClean — 3-bucket layout: cart on the left, action buttons in the middle strip, context panel on the right (Today's Offers by default, item picker / customer picker / refund picker on demand). No numpad. This is what a retail POS wants.
- HospitalityTiles — tile grid on the right for menu-item ordering (dining, QSR, cafe). The tile grid is driven by
MenuButtonrows against the terminal'sMenuProfileID.
The POS also auto-picks based on POSTerminal.TerminalType (Retail vs Hospitality) if LayoutMode is left blank.
Show / hide the bottom bar
MenuProfile.ShowBottomBar. ON (default) shows a slim footer with the date, time, store, terminal, and app-name chips. Turn OFF for kiosk / customer-facing terminals where you want a completely stripped screen.
Dual customer display
Terminal-level setting: Enable Dual Customer Display under the terminal edit page. When ON the cashier can open /POS/CustomerDisplay?terminalID=N on a second monitor / tablet — it streams the cart and Today's Offers to the shopper via BroadcastChannel (same-origin window-to-window, no server round-trip).
At payment time the UPI QR renders on the customer display, not on the cashier's screen. The cashier's screen just shows a "waiting for UPI confirmation" prompt.
Idle timeout (seconds) — seconds without cart activity before flipping to the idle content playlist. Default 30.
Idle content playlist (JSON) — array of {url, type: image|video, durationSec} to rotate when the till is idle. Leave empty for a plain branded fallback.
Ask Saathi to do it
You can ask the Saathi assistant to walk you through or make any of the changes above. Examples:
- “How do I move the PAY button to the top of the action strip?”
- “Make Void Line require manager approval on TERM-01.”
- “Change our POS to the light-green theme.”
- “Turn off refund-to-same-tender for the Bengaluru store.”
- “Hide the bottom bar on the kiosk terminal.”
- “How does refund work?”
Saathi answers instructional questions from this manual directly (no LLM burn). For change actions Saathi presents a preview and asks you to confirm before writing to POSStripButton / POSTerminal / Store.
Troubleshooting
- My new buttons don't show up. Hard-refresh the POS tab (Ctrl+Shift+R). The action strip is rebuilt on every Init — the cashier needs to re-open the POS page or re-authenticate the PIN.
- PAY button is missing after I edited the strip. Make sure at least one row has PAY ticked — that flag renders it as the sticky orange bottom button. If no row is flagged, the PAY button is absent (by design).
- Refund lines don't appear in the cart. Check the server error toast — usually a schema mismatch. Confirm migration 411 (Store.RefundSameTender) and 412 (POSStripButton) are applied.
- Colors look wrong. Clear the browser's
mspos-theme-manuallocalStorage key — a cashier may have manually overridden the theme. Then the terminal'sColorThemetakes effect. - Refund goes to the wrong tender. Check
Store.RefundSameTenderand the original bill'sPOSTransactionPaymentrows — the auto-settlement is proportional to what the customer actually paid.