=== TillKit ===
Contributors: snwebapps, spyr05
Tags: woocommerce, pos, point of sale, mobile, barcode
Requires at least: 5.8
Tested up to: 7.1
Requires PHP: 7.4
Stable tag: 1.0.4
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

A free mobile POS terminal for WooCommerce. Sell from your phone with a PIN-protected app — no hardware required.

== Description ==

**TillKit** turns your WooCommerce store into a mobile point of sale. Open the app from any phone or tablet browser, log in with a PIN, and start selling.

= Free Features =

* **Mobile POS** — Full-screen product grid with category filter chips, search by name / SKU, and cart drawer
* **Till management** — Open and close a till with float tracking and variance report on close
* **Order history** — Browse today's orders with full item breakdown
* **Cash payments** — Take cash sales and track change
* **PWA / Add to Home Screen** — Install on Android (Chrome) or iOS (Safari) for a native app feel
* **2 staff members** with PIN login — Cashier and Manager roles
* **1 active cart** — Single cart per session
* **Offline mode** — Products cached; pending orders sync on reconnect

= Upgrade to Pro =

[TillKit Pro](https://snwebapps.com/tillkit/) adds:

* **Unlimited staff** and all roles (Supervisor, Scanner Only)
* **Up to 10 simultaneous carts**
* **Card and custom payment methods**
* **Full & partial refunds** from Order History
* **Receipt emails** sent to customers
* **Barcode Scanner** tab (Quagga2) with scan log
* **Size Exchange** with automatic stock adjustment on both sides
* **Reports** — Shifts & Till Summaries, Product Sales, Exchange Log
* **Email Designer** for branded receipts
* **Priority support**

== Installation ==

1. Upload `tillkit.zip` via **Plugins → Add New → Upload Plugin**
2. Activate the plugin
3. Navigate to **TillKit** in the WordPress admin menu
4. Open `yoursite.com/tillkit/` on a phone and log in with PIN `1234`

⚠️ Change the default Manager PIN immediately via **TillKit → Staff**.

== Frequently Asked Questions ==

= Does this replace WooCommerce orders? =
No. POS orders are stored in a separate table (`tillkit_pos_orders`) and do not create WooCommerce orders by default. This keeps your WooCommerce order list clean.

= Does it work offline? =
Products and categories are cached by the Service Worker. Completed sales are queued in `localStorage` and synced automatically when the device reconnects.

= What browsers are supported? =
Chrome and Safari on Android and iOS. A modern desktop browser can also be used for testing.

= Is HTTPS required? =
Yes. Camera access (Pro Scanner feature) and the Service Worker both require HTTPS. The plugin shows a warning if SSL is not detected.

= How do I add more staff or roles in Lite? =
Lite supports 2 staff members with Cashier and Manager roles. [Upgrade to Pro](https://snwebapps.com/tillkit/) for unlimited staff and all roles.

== Screenshots ==

1. PIN login screen
2. POS product grid with category chips
3. Cart drawer with totals
4. Till management — open and close shift
5. Order History tab

== PWA Shell Architecture ==

TillKit serves its point-of-sale interface as a **Progressive Web App (PWA)**. When a user visits the configured suite URL, the plugin intercepts the request via the `template_redirect` action hook, outputs a complete standalone HTML document, and calls `exit()`. WordPress never proceeds to `wp_head()` or `wp_footer()`, so the assets registered via `wp_enqueue_script()`/`wp_enqueue_style()` for this request have nothing to print into automatically — they're printed directly instead, as described below.

The scripts and styles for the PWA shell are registered and enqueued through the standard `wp_register_script()`/`wp_enqueue_script()` and `wp_register_style()`/`wp_enqueue_style()` APIs (see `tillkit_pwa_register_script()` and `tillkit_pwa_register_style()` in `tillkit-main.php`). Because `wp_head()`/`wp_footer()` never run for this request, the enqueued assets are printed directly via `wp_print_scripts()`/`wp_print_styles()` with an explicit handle array, rather than relying on those hooks. This only prints the exact handles this plugin registered — not a foreign theme's full head output — and runs safely after `init`, since registration happens on `template_redirect`. Dynamic values (the inline config block and theme-colour CSS override) are attached via `wp_add_inline_script()`/`wp_add_inline_style()`. All values are sanitized: URLs through `esc_url()`, version strings through `esc_attr()`, and inline JS values through `esc_js()`.

This is the same pattern used by any WordPress plugin that serves a full-page application (e.g. login pages, OAuth callbacks, app shells) via `template_redirect`. The relevant PHPCS rules are suppressed with `// phpcs:disable WordPress.WP.EnqueuedResources` at the function level with this explanation inline.

== WordPress Core File Usage ==

TillKit loads two sets of WordPress core admin helper files using `require_once`. These are standard WordPress patterns and are used as follows:

* `wp-admin/includes/upgrade.php` — loaded in `TillKit_Database` methods that call `dbDelta()` to create or update database tables. This is the [documented WordPress method](https://developer.wordpress.org/reference/functions/dbdelta/) for plugin schema management. The file is loaded immediately before `dbDelta()` is called.

* `wp-admin/includes/file.php`, `image.php`, `media.php` — loaded in the `upload_media` REST API endpoint when processing logo uploads. These files expose `wp_handle_upload()`, `wp_generate_attachment_metadata()`, and `media_handle_upload()`, which are called immediately after loading. The files are only loaded if the functions are not already available.

In all cases, `require_once` is used (not `require`), the files are WordPress core files (not third-party), and a function from each file is called immediately after loading — as recommended in the WordPress plugin guidelines.

== Third Party Libraries ==

TillKit includes two pre-built third-party libraries as minified bundles. Both are unmodified upstream releases. Source code, license, and build instructions are provided below.

**QuaggaJS v0.12.1**

* Files: `app/js/quagga.js`, `suite/js/quagga.js`
* Purpose: Camera-based barcode scanning (live video stream barcode decoding)
* License: MIT
* Original source: https://github.com/serratus/quaggaJS (archived)
* Actively maintained fork: https://github.com/ericblade/quagga2
* NPM package: https://www.npmjs.com/package/@ericblade/quagga2
* License text: https://github.com/serratus/quaggaJS/blob/master/LICENSE

The included `quagga.js` is the unmodified `dist/quagga.js` output from the
upstream `serratus/quaggaJS` build at tag v0.12.1. To reproduce it from source:

    git clone https://github.com/serratus/quaggaJS.git
    cd quaggaJS
    git checkout v0.12.1
    npm install
    npm run build
    # Output at: dist/quagga.js
    cp dist/quagga.js /path/to/plugin/app/js/quagga.js
    cp dist/quagga.js /path/to/plugin/suite/js/quagga.js

**Chart.js v4.5.1**

* File: `admin/js/chart.umd.js`
* Purpose: Admin analytics charts
* License: MIT
* Source: https://github.com/chartjs/Chart.js
* License file: https://github.com/chartjs/Chart.js/blob/master/LICENSE.md

The minified file is the unmodified output of the Chart.js build. To reproduce it:

    npm install chart.js@4.5.1
    # Copy node_modules/chart.js/dist/chart.umd.js to admin/js/chart.umd.js

Or download directly: https://github.com/chartjs/Chart.js/releases/tag/v4.5.1

== Source Code and Build Tools ==

= Plugin Source Files (no build step required) =

All TillKit JavaScript files are plain, unminified, human-readable source files included directly in the plugin package. No compiler, bundler, or transpiler is used for plugin code.

* `suite/js/app.js` — App bootstrap, authentication, navigation
* `suite/js/pos.js` — POS product grid, category chips, search
* `suite/js/cart.js` — Cart drawer, multi-cart management
* `suite/js/scanner.js` — Barcode scanner tab (Quagga2 wrapper)
* `suite/js/history.js` — Order history, refunds
* `suite/js/exchange.js` — Size exchange workflow
* `suite/js/store.js` — Store/product management tab
* `suite/js/sw.js` — Service Worker (offline cache, sync queue)
* `admin/js/tillkit-admin.js` — WordPress admin panel

To modify these files: edit them directly. No compilation step is needed. If you change `sw.js` or any file that may be cached, increment the `CACHE_VERSION` constant at the top of `sw.js` to bust the service worker cache.

= Third-Party Libraries =

Two third-party libraries are included as pre-built minified bundles. They are compiled by their own upstream build systems — not by this plugin. Instructions for reproducing each bundle from source are provided below.

**QuaggaJS v0.12.1** — `suite/js/quagga.js`, `app/js/quagga.js`

* Purpose: Barcode scanning via camera feed
* License: MIT
* Upstream source: https://github.com/serratus/quaggaJS
* NPM package: `quagga` (note: the actively maintained fork is `@ericblade/quagga2` at https://github.com/ericblade/quagga2)

To regenerate `quagga.js` from source:

    git clone https://github.com/serratus/quaggaJS.git
    cd quaggaJS
    npm install
    npm run build
    # Output: dist/quagga.js

Copy `dist/quagga.js` to both `suite/js/quagga.js` and `app/js/quagga.js`.

**Chart.js v4.5.1** — `admin/js/chart.umd.js`

* Purpose: Analytics charts on the admin Reports page
* License: MIT
* Upstream source: https://github.com/chartjs/Chart.js

To regenerate `chart.umd.js` from source:

    npm install chart.js@4.5.1
    # Output: node_modules/chart.js/dist/chart.umd.js

Copy `node_modules/chart.js/dist/chart.umd.js` to `admin/js/chart.umd.js`.

Alternatively, download the file directly from the Chart.js CDN or GitHub release:
https://github.com/chartjs/Chart.js/releases/tag/v4.5.1

= Summary =

No custom build pipeline exists for this plugin. Future developers only need a text editor to modify plugin source files. The two minified files above are unmodified upstream releases and can be updated by following the steps above.

== Changelog ==

= 1.0.4 =
* Bug fix: service worker's offline asset cache list pointed at the page URL instead of the actual plugin-folder URL where assets are served from, so `cache.addAll()` failed and offline mode never worked. Introduced `TILLKIT_ASSET_BASE` alongside the existing `TILLKIT_SUITE_PATH` to fix this independently of the 1.0.2 subdirectory-install fix.
* Bug fix: service worker precache list referenced a nonexistent `zxing.min.js`; corrected to the actual `quagga.js` scanner file.
* Security: removed a public, unauthenticated `debug.html` page that allowed testing PIN logins directly against the live API from outside wp-admin.
* Removed orphaned duplicate copies of the app shell left over from before the WordPress.org rename.
* Structural fix: activating TillKit while TillKit Pro is also active (or vice versa) caused a fatal error, since both plugins share identical class/function names by design. Split into a loader file and the main plugin file so the conflict is detected safely before it can fatal.

= 1.0.3 =
* Compliance: Removed Email Designer page and its AJAX handlers — email appearance settings remain available via Settings → Store Identity.
* Compliance: Removed Supervisor and Scanner Only roles; Lite supports Cashier and Manager only.
* Compliance: Removed refund feature entirely; order void remains available to Manager.
* Security: Order history endpoint now enforces ownership check when a shift_id is supplied — non-managers can no longer retrieve another staff member's orders.
* Bug fix: IP lockout remaining-time calculation was always returning 0 because the lock timestamp was never stored. Fixed by calling lock_ip_with_time() on lockout.

= 1.0.2 =
* Bug fix: Service worker registration used a hardcoded `/tillkit/sw.js` path, breaking all subdirectory WordPress installs (e.g. `/dog/tillkit/`). SW now registers using the runtime suite URL from `TILLKIT_CONFIG`.
* Bug fix: `STATIC_ASSETS` paths in `sw.js` were hardcoded as `/tillkit/...`, causing SW install to fail on subdirectory installs. Paths now use `TILLKIT_SUITE_PATH` injected by PHP.
* Bug fix: SW fetch handler `startsWith(a.replace('/tillkit',''))` collapsed to `startsWith('/')`, intercepting every GET request cache-first including API calls. Fixed to exact path matching.

= 1.0.1 =
* Bug fix: POS cart close button, clear cart, and checkout button unresponsive after adding a product. Root cause: `buildPOSShell()` crashed on `pos-scan-close` binding before event listeners for cart buttons were attached. Fixed in previous build but browser HTTP cache was serving the old JS. Version bump forces fresh asset download.
* Bug fix: POS category chips not displaying despite categories being selected in Settings. Same root cause — stale cached JS prevented `loadCategories()` from running correctly.

= 1.0.0 =
* Initial release of TillKit
* POS with single cart, cash payments, till management
* Order history with full item breakdown
* 2 staff members (Cashier / Manager roles)
* PWA / Add to Home Screen support
* Offline mode with sync queue

== Upgrade Notice ==

= 1.0.0 =
Initial release.
