AcaciaHBC ยท Internal Document
Product Overview

Inventory System
PWA Brief

A full-featured Progressive Web App for field merchandisers to conduct inventory counts and damage reporting โ€” fully capable without an internet connection.

Prepared for Stakeholder Review  ยท  March 2026
PWA Offline-First Mobile XLSX Export
4+
App Screens
2
Report Sheets
20
Day Auto-Clear Cycle
100%
Offline Capable

What the app does

The AcaciaHBC Inventory System is a mobile-optimised PWA that guides merchandisers through a structured three-step count workflow โ€” from session setup through to a formatted Excel export.

๐Ÿ‘ค
Guided Session Setup
Merchandiser name, store location (from a managed list), and count period are captured before counting begins. Date & time auto-populate in real time.
๐Ÿ”
Live Product Search
Products are searchable by name, SKU, or category across a loaded product catalogue. Results are grouped by category in a scrollable dropdown.
๐Ÿ”ข
Quantity Stepper
Tap +/โˆ’ buttons or type directly to set counts. Validates for whole numbers โ‰ฅ 1. Prevents duplicate SKU entries within a single session.
๐Ÿ“Š
System Count Comparison
Where a system count JSON file is loaded, the ERP/system on-hand quantity is displayed alongside the physical count for instant discrepancy visibility.
โš ๏ธ
Damage Reporting
A dedicated Damages tab lets merchandisers log damaged SKUs with quantity and a required description note. Damage records are kept separate from regular inventory.
๐Ÿ“‹
Session Summary View
Before exporting, merchandisers see a full summary: total SKUs counted, total units, merchandiser name, location, period, and damage totals.
๐Ÿ“
Formatted Excel Export
Generates a multi-sheet .xlsx file with an Inventory Count sheet and a Damages Report sheet โ€” both with bold headers, totals rows, and column widths set automatically.
๐Ÿ“ค
Native File Sharing
On supported devices, the Web Share API allows the exported XLSX to be sent directly via Messenger, email, or any installed share target โ€” no cables or desktop required.
โฑ๏ธ
Unsaved Change Guards
When a product is selected but not yet added, navigating away triggers a confirmation prompt โ€” preventing accidental loss of in-progress entries.
๐Ÿ”„
Auto-Clear on Cycle
Inventory and damage data are automatically purged 20 days after the last successful export, keeping the device ready for the next count cycle with no manual cleanup required.
๐Ÿ“
Location-Aware Counts
Store locations are loaded from a managed JSON file. Changing the store during a session refreshes system-count comparisons to reflect the correct store's data.
๐Ÿ“ฑ
PWA Installable
Includes a web manifest and service worker registration, enabling Add to Home Screen on Android and iOS. Behaves like a native app once installed โ€” full-screen, no browser chrome.

Security measures

As a client-side PWA, the application's security model is scoped to the device. The following measures are in place.

Measure Status Detail
Data Storage localStorage All session data (inventory, damages, settings) is stored exclusively in the device's localStorage. Nothing is transmitted to a server. Data stays on-device at all times.
No Authentication By Design The app has no login. Access is controlled by who has the PWA installed. This is appropriate for single-user field devices. If multi-user access is required, authentication should be added.
Input Validation โœ“ Active All user inputs are validated client-side. Quantities must be positive whole integers. Damage notes are required fields. Empty or invalid inputs are rejected with toast notifications before any data is written.
XSS Surface โœ“ Low Risk Product and location data is loaded from controlled JSON files (not user-supplied URLs). Dynamic HTML uses textContent for user-supplied strings, limiting injection vectors. Search/display relies on template literals for catalogue data only.
External Dependencies 2 Libraries SheetJS (xlsx 0.18.5) and ExcelJS (4.3.0) are loaded from Cloudflare CDN via HTTPS. These are well-maintained, widely-used libraries. Pinning to specific versions reduces supply-chain risk.
Data Lifecycle โœ“ Auto-Cleared Count data is automatically deleted 20 days after the last export. The timer resets on each successful XLSX export. This limits the window of exposure for stale data persisting on a lost or shared device.
No Cloud Sync By Design There is no cloud database, API endpoint, or analytics tracker in the current build. All data egress is user-initiated (manual file download or share). No telemetry is collected.
Service Worker Scope Registered A service worker is registered for offline/PWA functionality (sw.js). The scope and caching strategy are defined in the separate sw.js file, not visible in the HTML alone. This should be audited separately.
File Export Safety โœ“ Local Blob XLSX files are generated in-memory as a Blob and downloaded via a temporary object URL, which is revoked after 5 seconds. No file is uploaded to any external server.
โš ๏ธ

Recommendation: HTTPS Deployment

Service workers and the Web Share API require a secure HTTPS origin. The app must be served over HTTPS in production for PWA features and sharing to function. Running over HTTP will silently disable these capabilities.

What gets produced

The app produces a structured Excel workbook delivered directly to the device โ€” no email, no server, no intermediary step required.

1
Sheet 1

Inventory Count Report

Lists every counted SKU with row number, location, category, barcode/SKU, product name, and quantity counted. Rows are sorted by category alphabetically. A bold totals row at the foot summarises total line items and total units counted. Report header rows include merchandiser name, store, count period, and export timestamp.

2
Sheet 2

Damages Report

A separate worksheet listing all damage entries: location, category, SKU, product name, quantity damaged, and the merchandiser's damage description. If no damages were recorded, the sheet notes this explicitly. Totals rows summarise the number of damage lines and total units damaged.

3
File Naming

Auto-Generated Filename

Each export is automatically named using the format IC_[Location]_[DD][Mon][YYYY]_[HHMM].xlsx โ€” for example, IC_CapeTown_26Mar2026_1430.xlsx. Special characters in location names are stripped to ensure cross-platform file system compatibility.

4
Delivery

Download + Native Share

The file is downloaded directly to the device's default downloads folder. On mobile browsers that support the Web Share API (iOS Safari, Android Chrome), an additional Share button appears, allowing the file to be sent immediately via Messenger, email, Teams, or any installed share target.

Works without connectivity

The app is built offline-first. Merchandisers working in stores with poor or no signal can complete a full count session and export a report without any network access.

โœ“ Offline

Full Count & Damage Entry

Adding products, logging quantities, recording damage notes โ€” the entire data-entry workflow functions without a network connection. All data writes to localStorage instantly.

โœ“ Offline

Persistent Data Between Sessions

Closing the browser or losing power does not lose data. localStorage persists across sessions on the same device, so a count can be resumed the next day without losing earlier entries.

โœ“ Offline

XLSX Export Generation

The Excel file is built entirely in-browser using client-side libraries. No network call is made during export. The file can be generated and downloaded while fully offline.

PWA Feature

Installable to Home Screen

Once installed as a PWA, the app shell can be cached by the service worker, allowing it to launch without a network connection, even on first open after installation.

โš  Requires Network

Product & Location Data Load

On first load, the app fetches products.json, locations.json, and system-count.json. If these are not cached by the service worker, an offline launch may result in an empty product list.

โš  Requires Network

Native Share to External Apps

Sharing the exported file via Messenger or email requires the receiving app to have network access. The file itself is available offline; delivering it to a recipient requires connectivity at time of share.

๐Ÿ’ก

Best Practice for Field Use

Instruct merchandisers to open the app once while connected to Wi-Fi before heading to a store. This ensures the service worker caches all JSON data and the app shell, making the session fully offline-capable.

๐Ÿ“ก

Service Worker Note

The PWA registers an external sw.js service worker. The caching strategy (Network-First, Cache-First, or Stale-While-Revalidate) is defined in that file and should be configured to pre-cache products.json, locations.json, and system-count.json for guaranteed offline access.