Complete reference for CWPOS v1.0.0 — a self-hosted, browser-based point-of-sale system built for Caribbean retail, food service and hospitality.
CWPOS is a full point-of-sale system that runs entirely in a web browser. There is no app to install and no hardware lock-in — open it on a laptop, tablet or phone and start selling. All data is stored as flat JSON files; no database server is required.
| Version | 1.0.0 |
| PHP | 7.4 or higher |
| Database | None — flat-file JSON |
| License | Single-domain, one-time purchase (CWPOS-XXXX-XXXX-XXXX-XXXX) |
| Hosting | Any standard cPanel shared hosting with HTTPS |
json, curl, session and openssl extensionsdata/ directory — CWPOS stores all data hereAllowOverride All is set in your server config or contact your host to enable .htaccess processing./pos/).data/ directory writable: chmod 755 data//pos/, your URL will be https://yourdomain.com/pos/. CWPOS detects the base path automatically — no configuration needed.data/ directory is protected by a .htaccess deny rule automatically created at install. Verify this file exists after installation.After the install wizard completes, work through these steps before your first sale:
Go to Products → New Product. At minimum set a name and price. Enable Track stock level if you want stock deductions and low-stock alerts. Products appear on the terminal immediately once marked active.
CWPOS seeds 8 default categories (Food, Beverages, Grocery, Bakery, Retail, Electronics, Services, General) each with subcategories. Edit or delete them under Categories. You can add subcategories one level deep.
Go to Settings → Company. Caribbean currencies supported: JMD, TTD, BBD, XCD, GYD, BZD. International: USD, GBP, EUR, CAD, AUD, NGN, GHS, KES.
Under Settings → POS, set your receipt footer message (e.g. "Thank you for shopping with us!") and default tax rate. Enable Email receipt to customer if you have SMTP configured.
Go to Shift → Open Shift and enter your opening float (cash in drawer). This enables cash reconciliation at end of day.
The POS terminal is at /terminal. The left panel shows your product grid; the right panel is the cart. Use category tabs to filter products.
Click any product card to add it. Click again to add another unit. Use the + and − buttons in the cart to adjust quantities. The ✕ button removes a line item.
Top-level category tabs are shown by default. Clicking a parent tab with subcategories reveals a second row of subcategory tabs. Clicking a parent shows all products in that category and all its subcategories. Clicking a subcategory shows only that subcategory.
Type in the search box to filter by product name or SKU. The search filters within the currently selected category. Clear with the ✕ button.
Enter a number in the Disc % field. Applies to the entire order subtotal before tax.
Enter an amount in the Disc field (currency symbol). Capped at the subtotal. Takes priority over percentage if both are filled.
Type a code in the Discount code field and press Enter or click the tag icon. The code is validated live — expired, inactive or fully-used codes are rejected with an error. A valid code shows a confirmation toast and is applied to the total after the percentage/fixed discount. Remove it with the ✕ button.
If a customer is selected and they have enough points, a redemption row appears. Enter how many points to redeem, click Redeem, and the equivalent discount is applied. The minimum redemption threshold is set in Settings → Loyalty.
| Cash | Numpad entry for amount tendered. Change calculated automatically. Sale recorded instantly. |
| Card | Process on your card terminal. Confirm in CWPOS and click Complete — no integration with card machines required. |
| Transfer | Bank transfer, LYNK, WiPay peer-to-peer, Zelle, etc. Cashier confirms receipt then completes the sale. |
After a sale, click Receipt in the success modal. A print-optimised page opens automatically. Use your browser's print dialog — select your thermal receipt printer and set paper size to match your printer (typically 80mm or 58mm roll). No driver installation is needed.
Enable in Settings → POS → Email receipt to customer. Requires SMTP configured under Settings → Email / SMTP and the customer must have an email address on file. The HTML email contains all line items, discounts, total and your receipt footer.
Receipts show: business name and address, transaction number, date/time, cashier name, payment method, all items with quantity and price, discounts applied, tax, total, cash tendered/change (if cash), customer name (if attached), and the receipt footer message from Settings.
Park the current cart to serve another customer without losing the sale. Click the pause icon in the cart header to hold the sale. Enter an optional label (e.g. "Table 4" or "Phone order") and click Hold.
Click the layer icon to open the Held Sales panel. All parked sales are listed with cashier, time, and total. Click the play icon to recall any held sale back into the cart. Click the trash icon to discard it.
data/held_sales.json and survives page refreshes but not server restarts. Complete or discard held sales before closing the shift.Enable in Settings → POS → Allow open-price items. A Custom button appears in the search bar. Click it, enter an item name, price, and tax rate, and add it to the cart. Open items are not linked to any product in the catalogue — they appear in the receipt with the name you entered.
CWPOS supports standard USB and Bluetooth HID barcode scanners without any configuration. Scanners act as a keyboard — rapid keystrokes ending in Enter are intercepted by the terminal. The scanned value is matched against product SKU fields.
Enter the barcode value (EAN-13, Code 128, QR, etc.) in the SKU / Barcode field when creating or editing a product. The scanner will match against this value (case-insensitive).
The scanner is active whenever no input field is focused on the terminal page. When a barcode is scanned, CWPOS first searches the visible product cards, then falls back to the server search endpoint. On a match, the product is added to the cart and a toast notification appears.
| Field | Description |
|---|---|
| Name | Required. Shown on terminal cards and receipts. |
| SKU / Barcode | Optional. Used for barcode scanner lookup. |
| Category | Parent or subcategory for terminal filtering. |
| Selling Price | Required. The price charged at the terminal. |
| Cost Price | Optional. For margin tracking — not shown to customers. |
| Tax Rate (%) | Applied per line item. Defaults to the setting in Settings → POS. |
| Stock Quantity | Starting stock if tracking is enabled. |
| Track Stock | Enable to deduct stock on each sale and trigger low-stock alerts. |
| Image URL | Optional. Full URL to a product image shown on the terminal card. |
| Active | Inactive products are hidden from the terminal but kept in the system. |
Categories are one level deep — a parent category can have subcategories, but subcategories cannot have their own children. CWPOS seeds 8 parent categories on installation, each with multiple subcategories.
Use the Add Category form on the left. Set a name, colour (shown on product cards), and an optional emoji icon.
Use the Add Subcategory form. Choose the parent, enter the name and colour. The subcategory appears indented under its parent in the tree and in the terminal's second tab row.
Deleting a parent also deletes all its subcategories and moves all affected products to Uncategorised. Deleting a subcategory moves its products to the parent category.
The Stock page (Catalogue → Stock) shows all products with Track Stock enabled, sorted by stock level ascending.
Click Receive on any product row. Enter the quantity received and an optional note (e.g. "Invoice #1042"). Stock is added immediately and logged.
Click the sliders icon to set an absolute stock count with a reason (e.g. "Stocktake — 3 damaged"). Use this for write-offs or corrections.
Click the clock icon on any product to see all stock movements — sales, receives, adjustments, and void restorations.
Set the threshold in Settings → POS → Low Stock Alert Threshold (default: 5). When a product's stock drops to or below the threshold after a sale, an email is sent to the company email address. Alerts fire at most once per product per day.
The customer directory lets you attach a customer to each sale for purchase history, loyalty points, and receipt emails. Enable the customer field on the terminal under Settings → POS → Show customer selection on terminal.
Click the eye icon in the customer list to open the profile page. It shows lifetime spend, visit count, last visit, full purchase history, and loyalty points history.
Type in the customer search field. Results appear as a dropdown with name, phone, email, and points balance. Click to select. The loyalty row appears if the customer has enough points to redeem.
Configure the programme under Loyalty in the sidebar (admin only).
| Setting | Description |
|---|---|
| Points per $1 spent | How many points a customer earns per currency unit. E.g. 0.1 = 1 point per $10 spent. |
| $ value per point | Monetary discount per point. E.g. 0.01 = 100 points = $1 off. |
| Minimum to redeem | Points balance required before redemption is offered. Default: 100. |
Points are awarded automatically after every completed sale. The loyalty row appears on the terminal when a customer with enough points is selected. Admins can manually adjust points from the Loyalty page with a reason note.
Create and manage codes under Discounts in the sidebar (admin only). Cashiers enter codes at the terminal without needing access to this section.
| Field | Description |
|---|---|
| Code | 2–20 uppercase letters, numbers, hyphens and underscores. E.g. SUMMER20. |
| Type | Percentage (e.g. 20% off) or Fixed amount (e.g. $500 off). |
| Max Uses | 0 = unlimited. When the limit is reached, the code auto-deactivates. |
| Expiry Date | Optional. Code rejects after this date. |
Discount codes are applied on top of any percentage/fixed cart discount. They cannot reduce the total below zero.
Shifts let you track cash drawer reconciliation per cashier. Open a shift before the trading day and close it at the end.
Go to Shift → Open Shift (or click the banner on the dashboard). Count your cash drawer and enter the opening float. A shift is now active for your account.
View live revenue totals by payment method under Shift → Current Shift. The sidebar shows a shift indicator when a shift is open.
Go to Shift → Close Shift. Count the cash drawer, enter the actual amount, add a note, and submit. CWPOS calculates the variance (expected cash vs counted cash) and saves the shift report.
Shows opening float, cash sales, expected closing cash, actual counted cash, variance, card/transfer totals, and total revenue. Accessible in Shift History for any past shift.
Every completed sale is recorded as a transaction with a sequential number (e.g. TXN-2026-0042). The number prefix and pattern are configurable in Settings → POS.
Admin only. Opens the transaction, click Void and confirm. The transaction is marked voided, and stock levels for tracked products are restored automatically.
Admin only. Marks the transaction as refunded with a note. Does not automatically restore stock — use the Stock Adjustment if needed.
| Report | What it shows |
|---|---|
| Daily Sales | Revenue by day with bar chart, payment method breakdown, date-range filter. |
| Product Sales | Revenue and quantity per product, sortable by revenue, with share bars. |
| End-of-Day | Full day summary — KPIs, payment methods, cashier breakdown, shifts, top products. Printable. |
| Cashier Performance | Revenue, transaction count, items sold, tax collected, share, and busiest trading hour per cashier. |
All reports are filterable by date range. The End-of-Day report has a Print button that hides all UI chrome for a clean printout.
| Section | Contains |
|---|---|
| Company / Shop | Business name, address, phone, email, TRN, currency, country, brand colour. |
| POS Settings | Transaction number prefix/pattern, default tax rate, receipt footer, low stock threshold, receipt email, open items, customer field. |
| Email / SMTP | Host, port, username, password, encryption, from name and address. Test email button. |
| CWInvoice Integration | Webhook URL and secret for pushing sales to CWInvoice. |
| CWPay Integration | Webhook secret for receiving CWPay payment confirmations. |
| Change Password | Admin account password update. |
| License | Current key (masked) and field to enter a new key. |
The admin account (created at install) has full access. Additional cashier and supervisor accounts can be created under Staff in the sidebar.
Each user can be granted individual module access: Terminal, Products, Categories, Customers, Transactions, Reports. Unchecked modules are hidden from that user's sidebar.
Not currently implemented. CWInvoice integration is outbound only.
After each completed sale, CWPOS posts a signed webhook to your CWInvoice installation. CWInvoice creates an invoice record marked as paid. Configure in Settings → CWInvoice Integration: enter the webhook URL from your CWInvoice install (Settings → CWPay Integration → Webhook URL) and the matching secret.
When a CWPay payment link is paid, CWPay sends a signed webhook to CWPOS at /webhook/cwpay. CWPOS matches the transaction by the pos_txn_ref field and marks it completed. Configure the webhook URL in your CWPay installation under Settings → CWPOS Integration. The webhook URL for your CWPOS install is:
https://your-domain.com/cwpos-path/webhook/cwpay
The webhook secret must match in both systems.
Direct CWFMS integration is not built into CWPOS. Route sales through CWInvoice, which can post journal entries to CWFMS.
Every significant action is recorded: sales, voids, refunds, logins, logouts, stock movements, category and product changes, user management, and settings updates. The log is append-only and stores up to 2,000 entries (oldest pruned automatically).
Filter by entity type (transaction, product, user, etc.) or action (sale, voided, login, etc.) using the dropdowns at the top of the Audit Log page.
| Problem | Solution |
|---|---|
| 500 error on all pages | Check your PHP version is 7.4+. Verify .htaccess is uploaded and URL rewriting is enabled on your server. |
| 404 on all routes except homepage | mod_rewrite / LiteSpeed rewrite is not active. Contact your host to enable .htaccess processing or AllowOverride All. |
| Products not showing on terminal | Check products are marked Active on the Products page. |
| Stock not updating | Verify Track Stock Level is checked on the product. Check stock under Catalogue → Stock. |
| Receipt email not sending | Verify SMTP settings under Settings → Email. Use the Test Email button to confirm delivery. Check the customer has an email address. |
| License validation fails | Verify the key format: CWPOS-XXXX-XXXX-XXXX-XXXX. Check curl is enabled in PHP. Ensure cwfms.com is reachable from your server. |
| Barcode scanner not working | Ensure no input field is focused when scanning. Check the SKU field on the product matches the barcode exactly. |
| data/ directory error | Run chmod 755 data/ via SSH or file manager. The web server user must be able to write to this directory. |