Files
foh-updates/eea-foh.json
T
ee-extensions release bot bc7893dd5a release eea-foh 0.23.8
2026-06-27 02:13:15 +00:00

32 lines
21 KiB
JSON

{
"name": "Front of House for Event Espresso",
"slug": "eea-foh",
"version": "0.23.8",
"download_url": "https://gitea.mulligan.casa/ee-extensions/foh-updates/raw/branch/main/eea-foh/eea-foh-0.23.8.zip",
"homepage": "https://gitea.mulligan.casa/ee-extensions/eea-foh",
"requires": "6.4",
"tested": "7.0",
"requires_php": "8.1",
"last_updated": "2026-06-27 02:13:14",
"icons": {
"1x": "https://gitea.mulligan.casa/ee-extensions/foh-updates/raw/branch/main/eea-foh/icon-128x128.png",
"2x": "https://gitea.mulligan.casa/ee-extensions/foh-updates/raw/branch/main/eea-foh/icon-256x256.png"
},
"author": "Mike Mulligan",
"author_homepage": "https://gitea.mulligan.casa/mmulligan",
"tags": [
"event espresso",
"point of sale",
"box office",
"front of house",
"ticketing",
"registration"
],
"sections": {
"description": "<p><strong>Front of House for Event Espresso</strong> runs the box office of a live event from a tablet. Each device is trusted by an administrator, every action is attributed to the clerk who took it, and the whole shift is captured in an append-only audit trail. It is an Event Espresso add-on — it reads and writes through Event Espresso's own models, so a sale, a payment, or a return at the door is the same real transaction it would be in wp-admin.</p>\n<p>The station runs as an installable PWA with no WordPress chrome: a clerk signs in with a badge, the tablet shows a fast registration search or a sales grid, and the door keeps moving.</p>\n<p><strong>What a station can do</strong></p>\n<ul>\n<li><strong>Check-in.</strong> Ranked name/email search, camera or hardware-wedge barcode scanning, cascade check-in across an event's datetimes, check-out, undo, and a manager-authorized force check-in for non-approved registrations. A segmented filter (All / Needs check-in / Needs payment) narrows the line to exactly who needs attention.</li>\n<li><strong>Sell / POS.</strong> A category-tabbed item grid with per-ticket variations and quantity steppers, a persistent running-total cart, registrant questions, then a real Event Espresso transaction with automatic tax and full rollback if anything fails — no orphaned rows.</li>\n<li><strong>In-person payments.</strong> Cash (with amount-tendered entry and live change-due), check, and card-present through a pluggable provider add-on. A shared transaction screen carries a role-governed payment gate so only permitted clerks can take money.</li>\n<li><strong>Returns, exchanges, and customer credit.</strong> Returns and exchanges settle as real Event Espresso transactions — replacement items are genuine ticket purchases, returned goods are a typed return payment, and the server computes the net. Overpayments resolve to a cash refund (role- and event-gated), a forfeit, or store credit parked on the customer's account (via a companion credit plugin).</li>\n<li><strong>Bluetooth thermal receipts.</strong> Print itemized receipts straight from the tablet to a 58mm thermal printer over Web Bluetooth — templated header and footer with token substitution, money-aligned line items, and a configurable tear feed. On-device test buttons prove the printer without ringing up a sale.</li>\n<li><strong>Clerk badges + scan-to-login.</strong> Print a badge per clerk carrying a CODE128 barcode and a QR; a clerk signs in by scanning that badge with the device camera or a hardware wedge scanner, or by typing a code.</li>\n<li><strong>Manager assist.</strong> A permitted manager can log in <em>over</em> an active clerk for a single task — a stacked, temporary session that preserves the base clerk's session and resumes it on exit.</li>\n<li><strong>Per-device themes.</strong> Four CSS themes (a system-following default plus dark, light, and high-contrast variants), chosen per device by a manager.</li>\n</ul>\n<p><strong>Built for the front desk</strong></p>\n<ul>\n<li><strong>Device trust.</strong> A device enrolls from an enrollment link, an admin approves it with a nickname and station, and the device then operates on a one-time-delivered secret — the operating credential, not a shared token.</li>\n<li><strong>Clerks, not WP users.</strong> Clerks are lightweight badge/PIN identities with configurable roles, idle and focus-loss timeouts, multi-login policy, and station scoping — volunteers never touch the WordPress user table or wp-admin.</li>\n<li><strong>Generic and reusable.</strong> Core stays event-agnostic and ticket-native. Filters let companion plugins layer on ticket categories, row enrichment, payment providers, and customer credit without forking the core.</li>\n<li><strong>Multisite-ready.</strong> Activate per site on a multisite network.</li>\n</ul>\n<p>Full documentation and architecture notes live in the bundled <strong>README.md</strong>.</p>",
"installation": "<ol>\n<li>Install and activate <strong>Event Espresso 5</strong> on the site first — this plugin is an Event Espresso add-on and does nothing without it.</li>\n<li>Upload the plugin to <code>wp-content/plugins/</code> and activate it (activate per site on multisite).</li>\n<li>Open the <strong>Front of House</strong> admin menu and set up your <strong>Access Profiles</strong>, <strong>Clerk Roles</strong>, <strong>Clerks</strong>, and <strong>Settings</strong> (including receipt header/footer).</li>\n<li>Create an <strong>Enrollment Link</strong>, open it on a tablet, install the PWA, and approve the device under <strong>Devices</strong>.</li>\n<li>The site should be served over <strong>HTTPS</strong> — the camera scanner and Bluetooth receipt printing require a secure context.</li>\n</ol>",
"faq": "<p><strong>Does this require Event Espresso?</strong></p>\n<p>Yes. It is an Event Espresso add-on and is tested against Event Espresso 5. Sales, payments, check-ins, and returns are written through Event Espresso's own models, so they are identical to what wp-admin would produce.</p>\n<p><strong>Why does it need HTTPS?</strong></p>\n<p>The camera-based barcode/QR scanner (camera access) and Bluetooth thermal printing (Web Bluetooth) only work in a secure browser context. Serve the site over HTTPS and the station works on tablets and phones.</p>\n<p><strong>How do clerks log in?</strong></p>\n<p>A clerk signs in to a station with a badge — scanned by the device camera, read by a hardware wedge scanner, or typed in as a code. Clerks are not WordPress users; they are managed under <strong>Front of House → Clerks</strong> and governed by configurable roles. Treat a printed badge as a physical login key.</p>\n<p><strong>What happens when the network drops?</strong></p>\n<p>The station distinguishes a genuine network failure (an offline banner) from a server-side response such as a too-short search or an out-of-scope result (shown inline). When the card-present path charges but recording the payment fails, the station does not swallow it: it retries, prints a manager error slip, records an audit incident, and shows a blocking manager modal.</p>\n<p><strong>Can I add card payments or store credit?</strong></p>\n<p>Yes. Cash and check are built in. Card-present payments come from a pluggable provider add-on, and store credit / pay-with-credit come from a companion customer-credit plugin. When those companions are absent, the station hides the affordances entirely.</p>\n<p><strong>Does it work on multisite?</strong></p>\n<p>Yes. Activate it per site on a multisite network.</p>",
"changelog": "<p><strong>0.23.8</strong><br />\n* Card now records — the last blocker. After the bump-back and Stripe verification worked, recording failed with \"No active payment method resolves for 'card'.\" The card records against the merchant's Stripe Onsite gateway, but the resolver required that gateway active in the admin scope, while a Stripe gateway is normally frontend/cart-scoped only. Scope isn't a recording precondition: the payment is recorded already-approved (no gateway charge runs — the card was charged on-device and verified), and EE's own record path only requires the method's payment type, not its scope. The card resolver no longer requires admin scope; it accepts the gateway if it exists with a usable type, without touching the merchant's live gateway config. Cash/check are unchanged. No prod config change needed.</p>\n<p><strong>0.23.7</strong><br />\n* Card return now records. With the bump-back working, the on-device diagnostic captured Collect's real return for the first time: <code>status=succeeded&amp;customerId=…&amp;paymentIntentId=pi_…</code>. The old mapping (<code>result=success</code>/<code>chargeId</code>) never matched, so every real charge read as declined. The return handler now uses the live contract; the authoritative fix ships in the Collect add-on 0.3.3 (which also makes the Stripe verifier retrieve the PaymentIntent <code>pi_</code>, not a charge <code>ch_</code>). Update eea-foh-collect to 0.3.3 alongside this.<br />\n* Error logging. A new server endpoint records device-side events to the PHP error log (and an audit row for errors). The station now logs every card return — success or failure, with the parsed status/ref and the raw return — so the flow is inspectable on the server instead of via on-screen diagnostics.</p>\n<p><strong>0.23.6</strong><br />\n* Card return parsing. With 0.23.5 the card finally bumps back, so the return handler ran against a real Collect return for the first time — and reported \"Card payment declined.\" It now reads the provider's params from the URL query OR fragment (an Android intent re-entry can deliver them after <code>#</code> instead of <code>?</code>, leaving the query empty and the status read as null → false decline), and records the amount we launched Collect with (full-remaining balance + surcharge, in cents) instead of the provider's dollar-formatted echo. A temporary diagnostic appends the raw return string to any decline message so the exact return shape is visible on-device; removed once locked.</p>\n<p><strong>0.23.5</strong><br />\n* Card return — the real bump-back blocker. 0.23.4 made the card launch a tapped anchor (correct), but a real card sale still ran standalone while the diagnostic bumped back. The cause was the launch description: the card sent <code>Txn #&lt;id&gt; — &lt;title&gt;</code>, and Collect's deep-link handler decodes the whole query string once before re-parsing, so the <code>#</code> (valid as <code>%23</code> in the link) decodes to a literal <code>#</code>, starts a URL fragment, and swallows the trailing <code>&amp;callback=…</code>. With no callback Collect runs standalone and never returns. The description is now sanitized to plain ASCII (no <code>#</code>, em dash, or punctuation). A second temporary Diagnostics probe (\"# in description\") deliberately reproduces the failure to confirm the cause; both diagnostics are removed once the live card flow is confirmed.</p>\n<p><strong>0.23.4</strong><br />\n* Card bump-back fix: the \"Pay with card\" action now launches the card-present provider (Collect) via a real tapped <code>&lt;a href&gt;</code> instead of a programmatic <code>window.location.assign</code>. From an installed Android WebAPK only a user-tapped anchor hands the launchApp deep link to the provider as an Android intent, so the provider runs integrated and returns to our <code>/foh/payment-result</code> callback (auto-bumps back into the app); a programmatic navigation made it run standalone and return to its own home. The temporary Diagnostics test link stays for one more cycle. Manifest unchanged — no reinstall; reopen the app after updating.</p>\n<p><strong>0.23.3</strong><br />\n* TEMPORARY diagnostic: a \"Test: $1 Collect charge\" link under Settings (hamburger) ▸ Diagnostics. It launches Collect via a real tapped <code>&lt;a href&gt;</code> (the way the proven probe did) instead of the app's programmatic <code>window.location.assign</code>, to isolate why the card return doesn't bump back into the app. Manifest unchanged — no reinstall needed, just reopen the app after updating. Remove once diagnosed.</p>\n<p><strong>0.23.2</strong><br />\n* Revert the 0.23.1 manifest link-capture keys. On Android the installed WebAPK already captures in-scope https returns purely from <code>scope</code> (the proven, working mechanism — Collect's redirect to an in-scope <code>/foh/</code> URL re-enters the app). <code>handle_links</code>/<code>launch_handler</code> are desktop-only no-ops there, and the explicit <code>id</code> risked changing WebAPK identity (treated as a different app without <code>legacy_ids</code>). Manifest is back to the minimal scope-only form. <strong>Reinstall the PWA</strong> (uninstall + Chrome \"Install app\") so the WebAPK re-mints its <code>/foh/</code> intent filters.</p>\n<p><strong>0.23.1</strong><br />\n* PWA link capture: the station manifest now declares <code>handle_links: preferred</code> + <code>launch_handler: navigate-existing</code> (and an explicit <code>id</code>) so an installed station can capture an in-scope return navigation — e.g. a card-present provider redirecting back to <code>/foh/payment-result</code> after a charge — into the existing app window instead of a browser tab. Requires reinstalling the PWA to pick up the new manifest.</p>\n<p><strong>0.23.0</strong><br />\n* Registrations now keep their contact questions on a Purchase sale. A ticket flagged by a companion (via the new <code>eea_foh_ticket_collects_contact</code> filter) — e.g. an \"attendee\"-class registration — keeps its contact/personal questions even on an anonymous Purchase, so the attendee's details are still captured. Anonymous merch/meal tickets are unchanged (contact still suppressed for a one-tap counter sale).<br />\n* Fix: corrected the card-present return fallback to match Collect's actual callback (<code>result=success</code>). Pair with eea-foh-collect 0.3.2.</p>\n<p><strong>0.22.3</strong><br />\n* Screenshots tab now uses the gallery pipeline (captions paired with screenshot-N images); with no images committed yet, the captions-only tab is dropped. No functional change.</p>\n<p><strong>0.22.2</strong><br />\n* Update-details sections now come from readme.txt (WP-native); base/config renamed to .mu-manifest.yaml + .mu-release.yaml. No functional change.</p>\n<p><strong>0.22.1</strong><br />\n* Release now flows through the shared manifest pipeline; the \"View details\" modal carries a description, changelog, and tags. No functional change to the plugin.</p>\n<p><strong>0.22.0</strong><br />\n* Added a color-coded plugin icon (delivered through the update channel) and declared WordPress 7.0 compatibility. No functional change.</p>\n<p>The full history is in <strong>CHANGELOG.md</strong> bundled with the plugin.</p>\n<p><strong>0.21.2</strong><br />\n* Updates are now handled by the Manifest Updater plugin (via the standard \"Update URI\" header) instead of a bundled updater. No change to how Front of House works; this lets it run on a single site instead of network-wide. Requires the Manifest Updater plugin to be network-activated to receive update notifications.</p>\n<p><strong>0.21.1</strong><br />\n* Fixed for real (multisite): the \"payment method Return/Settlement was automatically deactivated\" admin notice that kept coming back. Root cause was that Front of House auto-activated its internal Return/Settlement methods on every site in the network and then kept reactivating them, which Event Espresso re-deactivated in a loop. Those methods are now created only on the site that actually records a return/settlement (the desk site), and the stale notice is cleared in every admin context. No effect on how returns/settlements work.</p>\n<p><strong>0.21.0</strong><br />\n* Per-method payment options. Settings ▸ Payment Methods now lets you set, per method, a custom button label, whether a check number is required, and (for card) a surcharge. A card surcharge is added to the sale as a real fee line item — it raises the total, prints on the receipt, and is recorded in Event Espresso — so the customer is actually charged it. Card payments include the surcharge in the amount charged on the reader.<br />\n* Card is now provided through the Collect for Stripe add-on's registration with Front of House, and Front of House owns enabling/disabling and labelling every method (including card) in one place. Update the Collect add-on to 0.2.0 alongside this release.<br />\n* The old \"Allow cash refunds\" setting is carried forward into the new Payment Methods section automatically; no reconfiguration needed.</p>\n<p><strong>0.20.1</strong><br />\n* Fixed a \"payment method was automatically deactivated\" admin notice that kept reappearing for the Return and Settlement payment methods. The methods themselves were working; the stale warning is now cleared properly (the previous fix was being undone by Event Espresso's own notice save).</p>\n<p><strong>0.20.0</strong><br />\n* Per-device payment hardware. Each device now has a \"Hardware\" block (card reader, cash drawer); unchecking one hides that payment method on that station's point of sale — card needs a card reader, cash needs a cash drawer. Visibility only: it never changes who may take payment, and nothing changes on existing devices (every device is treated as fully equipped until you say otherwise).</p>\n<p><strong>0.19.0</strong><br />\n* A single home for payment methods. A new \"Payment Methods\" settings section turns cash, check, and card on or off and sets cash-refund policy in one place; an access profile can restrict which methods a given station offers. Nothing changes on an existing install — every method stays enabled exactly as before until you adjust it. Under the hood the method set is now data-driven (a registry) so future methods can plug in cleanly.</p>\n<p><strong>0.18.1</strong><br />\n* Check payments at the desk (activates Event Espresso's Check method in the admin scope). Server-side event-scope enforcement on every payment/return endpoint (a clerk can only act on their own event's transactions). Clerk/manager codes widened to 10 digits with a per-device brute-force lockout, plus a remote \"Clear lockout\" admin action.</p>\n<p><strong>0.18.0</strong><br />\n* Card-present payments are verified against Stripe before approval (no more trusting the return URL). Every first-touch money write (sales, exchanges, cash, credit, settlements) is now idempotent against a lost-response retry. Audit-log failures are no longer silent.</p>\n<p><strong>0.17.2</strong><br />\n* The Return and Settlement payment methods now reactivate themselves automatically after a plugin update — no manual step on the Payment Methods screen, ever.</p>\n<p><strong>0.17.1</strong><br />\n* Walk-up Return (card-less return/exchange). Sales and returns now verify the transaction's true status in Event Espresso before completing — no more false \"Sale Complete\" on an unpaid exit.</p>\n<p><strong>0.17.0</strong><br />\n* Admin-configurable branding (receipt logo, app icon, splash, background) and Bluetooth badge printing in wp-admin (one badge at a time, tear between).</p>\n<p><strong>0.16.2</strong><br />\n* Service worker REST namespace fix (eea-checkin/v1 -&gt; eea-foh/v1); no behavior change.</p>\n<p><strong>0.16.1</strong><br />\n* Update channel + repository URLs moved to the ee-extensions org. Removed a hard-coded external domain from the receipt printer's barcode/QR test page.</p>\n<p><strong>0.16.0</strong><br />\n* Taking payment is now a lookup filter (All / Needs check-in / Needs payment), not a separate mode. Sell remains its own mode. No schema or server change.</p>\n<p><strong>0.15.0</strong><br />\n* Printable clerk badges plus camera and hardware-wedge scan-to-login, with per-device camera configuration.</p>\n<p><strong>0.14.x</strong><br />\n* Bluetooth thermal receipt printing with templated header/footer, itemized line items, and configurable tear feed; a dedicated receipt-printer configuration modal with on-device test buttons; loud \"charged but unrecorded\" incident handling for the card-present path.</p>\n<p><strong>0.13.0</strong><br />\n* Returns, exchanges, refunds, and customer credit settled as real Event Espresso transactions, with cash-refund/forfeit/store-credit settlement and exchange tax suppression.</p>\n<p><strong>0.12.0</strong><br />\n* Card-present payments via a pluggable, provider-agnostic descriptor model; cash tender with change; on-demand emailed receipts.</p>\n<p><strong>0.11.0</strong><br />\n* Sell / POS mode — front-desk sales through a category grid and persistent cart, building real Event Espresso transactions with automatic tax and full rollback.</p>\n<p><strong>0.9.0 - 0.10.0</strong><br />\n* Station modes, pluggable in-person payments, the corrected visibility-vs-action check-in model, assistive (stacked) manager login, per-device themes, and a Q&amp;A + payments details modal.</p>\n<p><strong>0.5.0 - 0.7.x</strong><br />\n* Device-secret authentication and nonce-sealed enrollment, first-class enrollment links, configurable clerk roles and stateful sessions, clerk-to-station scoping, linked-registration reverse lookup, and a role-gated registration details modal.</p>\n<p><strong>0.1.0 - 0.4.0</strong><br />\n* Foundation: profiles/devices/clerks/audit data model, REST layer, ranked search, check-in over Event Espresso models, the device approval handshake, and the station PWA.</p>"
}
}