This skill owns the operational POS contract: a fast sale entry surface whose customer, product, inventory, payment, permission, and accounting decisions are explicit, repeatable, and auditable.
Use When
- Building or reviewing a tenant-aware retail POS, field-agent POS, or manual sales-entry screen.
- Defining default-customer behaviour, product selection, stock validation, payment capture, or the relationship between products and finished stock.
- Auditing whether separate sales surfaces post to one canonical transaction boundary and produce consistent inventory/accounting outcomes.
- Designing a low-friction counter workflow where the operator needs speed, clear availability, and recoverable errors without sacrificing controls.
Do Not Use When
- The journey is consumer discovery, online checkout, delivery tracking, or
returns; use
ecommerce-and-checkout-ux. - The work is a generic form, table, modal, or validation pattern; use the
relevant
04-web-and-ui-designskill. - The work is a financial statement, ledger, or accounting-control design; use the finance/accounting doctrine alongside this skill.
- The workflow is bulk quotation, order acceptance, delivery, invoicing, and payment collection; specify it as an order-to-cash workflow, not as POS.
Required Inputs
| Artefact or context | Source | Required? | Why |
|---|---|---|---|
| Product-to-finished-stock map | Product and inventory owners | yes | Determines what may be sold and deducted |
| Manufacturing recipes and component rules | Manufacturing owner | yes when applicable | Ingredients are consumed at manufacture |
| Tenant, branch, store, and sales-agent permissions | Engineering and operations | yes | Prevents cross-tenant or cross-surface leakage |
| Customer and payment rules | Finance and sales owners | yes | Establishes default, credit, tender, and receipt behaviour |
| Supported devices and operator journeys | Research and operations | yes | Determines scan, search, list, card, and recovery treatment |
Workflow
1. Name the three operational surfaces
Keep these surfaces distinct in copy, permissions, telemetry, and code:
pos.php— the general shop or tenant point of sale.agent-pos.php— sales posted strictly on behalf of a sales agent.encode-sales.php— manual entry of a sale that has already occurred.
They may share presentation components and the canonical posting service, but they must not silently become interchangeable workflows. A separate bulk order-to-cash process owns quote, customer order, delivery, invoice, and payment collection.
2. Resolve the tenant default customer explicitly
Each tenant has one configured generic default customer, normally named “Walk-in”. It is selected in tenant/franchise settings. Super administrators, max administrators, and a tenant user granted the dedicated configuration permission may change it.
All three POS surfaces must resolve the same server-side tenant setting on load. They must not search for names containing “cash” or “walk”, choose the first active customer, or allow a sales-point default to replace the tenant default. A missing or inactive configuration is a visible configuration state, not permission to guess.
The operator may replace the default with a named customer before posting; the default is an initial state, not a hidden override of an intentional choice.
3. Keep product and stock identity separate
The operator sells a product. Each saleable product has one matching finished stock item (1:1). The product carries customer-facing name, image, category, price, and description; the stock item carries inventory identity, unit of measure, batches, cost, and balance. The UI must never present ingredients, packaging, or arbitrary raw stock items as sellable products.
Manufacturing consumes recipe ingredient stock items and produces the mapped finished stock item. Selling a product deducts its mapped finished stock item, not its recipe ingredients. Availability, FEFO/batch selection, costing, and the ledger must use that mapping at the service boundary.
4. Design the operator loop
The primary loop is: identify operator context → confirm customer → find a product → show price and available quantity → add or edit quantity → choose tender or credit → review total → post once → show receipt/reference.
Make the current branch/store/agent context visible. Make product name and finished-stock availability more prominent than internal codes. Keep the cart editable, totals stable, and errors attached to the affected line. Preserve a server-generated idempotency key across retries; never create duplicate sales because a payment modal or network response was slow.
5. Make the boundary canonical
All three surfaces call the same posting service or an explicit adapter into it. The transaction boundary must atomically validate tenant, permissions, customer, product mapping, batch/stock availability, price, invoice, payment, stock deduction, GL posting, and audit lineage. A UI “success” state is not evidence; verify the persisted invoice, payment, stock ledger, and journal.
6. Design the visual system for operations
Use a restrained, high-contrast operational hierarchy: one clear primary action, a persistent cart summary, visible context, and short recovery copy. Choose a deliberate typeface pairing rather than a default dashboard font; state the choice and test number legibility at the operator’s likely distance. Use color for state (available, warning, blocked, paid) with text or icons as the redundant cue. Apply the design doctrine, WCAG 2.2, and the host product’s tokens; do not invent a decorative POS skin disconnected from the product.
Decision Rules
| Condition | Action | Wrong-choice failure |
|---|---|---|
| Tenant default exists and active | Auto-load it in all three POS surfaces | Divergent customer attribution |
| Default missing or inactive | Show configuration warning and block unassigned posting | Silent sale to an arbitrary customer |
| Named customer deliberately selected | Preserve the selection through review and post | Resetting it on branch/product changes |
| Product has no active 1:1 finished-stock mapping | Hide/block it from POS and report the data defect | Selling ingredients or an unmapped phantom |
| Recipe ingredient stock is low | Stop manufacturing or warn manufacturing workflow | Deducting ingredients at sale |
| Finished stock is low | Block the sale or show the exact shortage | Allowing negative stock invisibly |
| Payment request times out | Retry the same idempotency key and reconcile status | Creating a duplicate invoice/payment |
| User has branch sales rights but no plant rights | Keep plant/job data out of POS and plant screens | Treating branch access as plant access |
Capability Contract
- Read schemas, services, routes, permissions, and representative screens before changing a POS contract.
- Use server-derived tenant context and prepared statements; never trust a tenant, branch, store, or customer ID from the browser without validation.
- Edit only with explicit authority. Keep design review read-only until a bounded implementation request is given.
- Verify with PHP lint, JavaScript syntax checks, focused contract tests, and a database-backed apply/rollback or dry-run/verify path where available.
Degraded Mode
- If the browser or database is unavailable, provide a screen/service contract and mark interaction, persistence, and accessibility checks unverified.
- If product-to-stock mappings are incomplete, do not invent mappings; return a defect register and block release of the affected products.
- If payment or GL fixtures are unavailable, verify the request shape and idempotency path only, and explicitly block production sign-off.
Anti-Patterns
- Name search for “cash”, “walk”, or “default” → resolve an explicit tenant setting.
- First-active-customer fallback → show a configuration defect and stop posting.
- Raw ingredient or packaging cards in POS → expose only products with mapped finished stock.
- Recipe deduction during sale → consume ingredients at manufacture and finished stock at sale.
- Separate fake writers per screen → use one canonical transaction boundary.
- Customer selection reset after a sales-point or product refresh → preserve operator intent.
- A green toast without persisted evidence → reconcile invoice, payment, stock, GL, and audit records.
Outputs
| Artefact | Consumer | Evidence and acceptance condition |
|---|---|---|
| POS surface contract | Product, design, and engineering | Three surfaces and the separate bulk workflow are named |
| Default-customer rule | Tenant administrators and QA | One server-resolved customer is shown in all three screens |
| Product-stock mapping contract | Inventory and manufacturing | Product sale and manufacturing deduction paths are distinct |
| Operator interaction spec | Design and frontend | Primary loop, states, recovery, and accessibility are testable |
| Posting verification record | Finance, audit, and engineering | Invoice/payment/stock/GL evidence reconciles with one idempotency key |
Examples
See examples/pos-and-retail-operations-worked.md for a Nile Harvest-style
multi-surface walkthrough covering a configured Walk-in customer, a mapped
finished product, manufacturing consumption, sale deduction, and retry-safe
payment.
References
doctrine/design-doctrine.mdgovernance/design-quality-gate.mdskills/06-sector-and-domain-ux/ecommerce-and-checkout-ux/SKILL.mdskills/00-cross-cutting-ops-qa-a11y/accessibility-wcag-2-2-compliance/SKILL.mdskills/04-web-and-ui-design/form-ux-design/SKILL.md