552
Devices in inventory
2,205
Esper devices synced
596
Scheduled Joe OS updates
279
Automated tests
In this case study
From dashboards to operations
The first version of this project was a device-intelligence pipeline: a multi-threaded Python sync pulled every device heartbeat from the Esper mobile device management API into a database, and a daily Slack summary reported fleet health each morning. It answered “which stores are on an old version” and “what went offline overnight” for a fleet of around 1,500 Android point-of-sale devices across more than 330 store groups.
Dashboards can show a problem, but they cannot ship a replacement terminal, print its label, schedule the OS update or track the return. Those jobs still lived in spreadsheets and Slack threads. In May 2026 the work moved into a single server-rendered application, and by August the app had absorbed the reporting and alert pipeline entirely, with its own Esper event log, fleet view and Slack reporting. Nothing else is needed alongside it any more.
Goal: one self-hosted system for everything that happens to a piece of Joe Coffee hardware, from receiving and labelling through deployment, OS updates, returns and damage, with role-based access for warehouse staff and no dependence on a cloud SaaS.
What the system does
Devices and accessories
Serial numbers, BNN and Esper identifiers, models, ownership, location, status, Brand New versus Preused condition, return dates, installation dates and damage records; accessories with stock levels, reorder thresholds, images and receiving.
Checkouts and deployments
A checkout bundles devices and accessory quantities for a store, with packing workflow, package photos, box numbers, notes, Shopify orders, carrier tracking, partner labels and returns.
Esper fleet integration
Device names, groups and console links, Joe OS version health, an Esper events log with remote-command results, and scheduled Joe OS updates driven from the inventory.
Logistics
Outbound deliveries and return shipments with live FedEx and USPS status, Shopify order sync, manual partner-paid returns, and share and copy-link controls for every shipment.
Reports and exports
Checkout history, deployed-hardware views, a returned-devices report, an Ops Digest, and CSV, XLSX, PDF and Google Drive exports.
People and audit
Google Workspace sign-in with Viewer, Warehouse and Admin roles, device and inventory logs, an audit trail of every change, and alert history. Installable as a PWA with phone camera capture.
Checkout records
A checkout is the unit of work that ties everything else together: it records which hardware left the warehouse, for whom, how it was packed, how it shipped, and whether it came back. Every device and accessory movement is anchored to one, so a serial number can always be traced to the shop it went to and the order that paid for it.
125
Checkouts on record
413
Devices and accessories checked out
71
Package photos attached
17
Full or partial returns
What one record holds
Who and where
Partner shop, company or order name; the checkout date; the operator who created it; links to the Shopify order and the CRM record; and free-form notes.
What went out
One line per device or accessory with its serial, BNN and quantity. Each device is assigned a real role for the shop: Barista, Customer Screen, Customer Payment Case, Single Screen Solution, OMS, Kiosk or Mobile. Deploying a device as Unknown is not allowed.
How it was packed
The box, chosen during packing readiness after the checkout is saved; package weight and dimensions; multiple package photos captured from a phone; and the Esper group the devices were moved into, with a timestamp.
How it shipped
Carrier, tracking number and the app-level delivery status, plus the carrier’s own status, detail, estimated and actual delivery times from FedEx or USPS, and the Shopify fulfillment and tracking data imported from the order.
Partner shipping requests
A tokenised request page lets the partner choose a shipping option and payment method. The app turns that into a Shopify draft order, sends the invoice, records when it was selected and by whom, and stores the resulting shipping label for printing.
What came back
Returns of the whole checkout or single items, with accessory quantities; delivery set manually when a package was handed over in person; and archiving with a reason once the record is closed.
The lifecycle
- CreateEnter the shop or order, links, carrier and notes; select warehouse devices and assign a role to each; add accessory quantities. Missing items can be added later from the detail page.
- PackPacking readiness checks the checkout before it ships: box selected, photos attached, Esper group set. Warehouse and partner labels print from the same screen.
- ShipMark the hardware sent. Devices move automatically to In Transit to Partner Shop, and the Shopify order supplies the tracking number when it exists.
- TrackOutbound Deliveries refreshes FedEx, USPS and Shopify on a schedule and shows the carrier’s latest word. Delivered moves the devices to Deployed to Partner Shop; cancelled and stuck shipments surface under Needs Attention.
- Return or archiveReturn All or return a single item and the hardware is back in warehouse inventory as Preused with its return date recorded. Closed checkouts are archived with a reason and stay in Checkout History.
One rule behind all of it: device status is derived from the checkout’s delivery state, never edited by hand. Of the checkouts on record today, 84 are Delivered, 17 were dropped off in person, 17 were returned, and a handful are still on the way or not yet shipped. Fixing a checkout means using the app, not the database.
Architecture
The application is deliberately small in moving parts: Gunicorn serving Flask behind an Nginx container, SQLite for the database, and a bind-mounted data directory for the database and uploads. A TLS reverse proxy in front terminates HTTPS. Everything external is an integration that can be unavailable without taking the inventory down.
Flask + Gunicorn
Server-rendered pages, route blueprints for printers, Esper and Joe OS, and startup code that initialises and incrementally upgrades the schema.
SQLite
Twenty tables in one file: devices, deployments, Esper mirrors, update schedules and batches, audit and alert events. Nightly backups upload to a Google Shared Drive through a service account.
Nginx
Internal reverse proxy with upload and timeout settings, published only on the host loopback and reached through the shared proxy network.
Integrations
Esper, Shopify, FedEx, USPS, Slack webhooks, Google Drive and a partner label-printer webhook, each optional and each configured through the environment.
Design rule
Page loads never trigger external syncs. Esper, Shopify and carrier calls run on explicit sync actions or on a schedule and write to persisted snapshots; ordinary dashboard loads read the snapshot. A carrier outage is never treated as loss of the underlying checkout record, and the inventory stays usable when Esper is unreachable.
The Joe OS update pipeline
Joe OS is the point-of-sale app on every terminal. Rolling a version out to hundreds of devices used to mean clicking through the Esper console and watching Slack for complaints. The app now owns the whole cycle.
- ScheduleOperators pick devices and a target version in Schedule Joe OS Update. Each run is a batch with a recorded reason, and an Announce to Slack button posts the window, device list with BNN, alias and Esper group, chunked under Slack’s block-size limit.
- PushWhen the window opens the app sends the install command through Esper. Sent means only that Esper accepted the command; nothing is reported as installed yet.
- ConfirmA fresh Esper sync must report the target version on the device before it counts as installed. Confirmed devices leave the active queue and move to Installed History with their confirmation time.
- EscalateDevices that have not reported the target version within a 15-minute confirmation window become Failed · Needs Attention, with a dedicated view and one-click retry.
- ReportOne Slack summary per batch shows schedule, push and completion times with installed, failed and total counts, instead of one message per device. Enterprise versus Google Play updates, cache clears and uninstalls are logged and alerted separately, duplicate-safe, without replaying history.
A Joe OS Versions page sorts versions semantically, newest first, and shows online, offline and combined device counts per version, which is the fleet-health view the earlier pipeline used to provide.
Logistics and carrier tracking
Delivery tracking started as a tab on the checkout page and grew into its own Logistics section with Outbound Deliveries and Return Shipments. Most of the engineering went into making carrier data trustworthy:
- Terminal states stay terminal. A cancelled FedEx shipment stays Canceled under Needs Attention; later transient carrier responses cannot flip it back to Delivered, and a checkout manually marked Delivered is never reset by an automatic refresh.
- Replacement labels get a clean slate. Stale carrier results are cleared whenever a checkout receives a different tracking number, so a cancelled label cannot affect its replacement.
- Returns that never move get noticed. A return label that passes ten days without an acceptance scan raises a once-per-return Slack alert, and FedEx Ready for pickup is classified as Needs Attention so staff know a package must be collected.
- No alert spam. Stale Shopify delivery notifications are suppressed when a backfilled tracking number was delivered more than a day before import, and USPS tracking backs off while the carrier is blocking the account instead of looping.
- Shareable without Slack noise. Every delivery and return has Share and Copy Link controls that open the device share sheet with arrival dates included, and never post automatically.
The warehouse floor
The people using this every day are warehouse staff with a phone in one hand. Several features exist only to make that shift shorter.
Warehouse Command Center
A role-aware dashboard panel of shortcuts for inventory, devices, checkout, tracking, receiving and reorder, with live filtering, / or Ctrl+K focus and a phone layout.
Label printing
Custom Brother labels with up to three text rows and a quantity, plus dedicated Label Printer and Shipping Label Printer pages. A small Windows print service, run as an NSSM service on the warehouse PC and reached over WireGuard, does the printing; jobs carry a print key and printing is geofenced to allowed networks. It replaced an earlier Slack-command label workflow.
Scannable QR codes
Warehouse label QR codes originally failed to scan. The generator now uses integer module sizes, keeps a real quiet zone, spans the full label height and compensates for printers whose horizontal and vertical DPI differ.
Damage photos from a phone
A QR code on the broken-device flow opens a phone uploader for damage photos, the same way package photos are captured at packing time.
Condition tracking
Devices are Brand New or Preused. A warehouse return automatically becomes Preused and records its latest return time, and historical returns were backfilled on startup.
Friendly model names
Checkout history shows Falcon 2 LTE, Falcon 2 WiFi, D3 Pro and A9 variants instead of Esper model codes, with fallback matching for older rows.
Running it unattended
The repository is written for a maintainer handoff, not just for the author. It carries a runbook, an operations guide, a data dictionary, a backup and restore procedure, a security hardening checklist, a production-readiness review and an incident log, plus a management handoff document.
- Automatic nightly database backups uploaded to a Google Shared Drive.
- A Settings section with System Status, Printing and Sync pages, where status is actionable for admins rather than read-only.
- Role-based access with Google Workspace sign-in restricted to the company domain; a local-admin bypass exists for development only.
- Two hundred and seventy-nine pytest integration and flow tests plus a browser smoke test, run in parallel.
- The schema, printer, Esper and Joe OS code split into their own modules and blueprints in August so the application file stopped being the whole application.
Lessons
Sent is not installed
Report what the device confirms, not what the API accepted. Early Joe OS alerts fired when Esper accepted a command. Real installs finish minutes later, or not at all. Splitting Sent from Installed, waiting for a sync to confirm the version, and escalating after a fixed window made the Slack summary something operators could trust.
Carrier data lies a little
Design for out-of-order and contradictory updates. Carriers resend old statuses, Shopify backfills tracking numbers, and cancelled labels keep answering. Terminal states, per-tracking-number resets and delivery-date suppression rules came one incident at a time.
Replace the pipeline from the inside
The operations app ate the reporting stack. Once the app recorded Esper events durably with retryable Slack delivery, the separate sync, dashboard and alert tooling had nothing left to do and was retired. Fewer moving parts, one login, one audit trail.
Richard Applegate