← Back to overview

Shipment Scan-First Verification App

Shipment Scan-First Verification App

Background & Problem

Shipment verification could only start after the ERP had finalized a per-box packing list (P/L). Physical checking and reconciliation were therefore strictly sequential, operators waited on data, and the state of an interrupted job lived in someone's memory or notes. The second problem was traceability: when a wrong item slipped into a box, there was no way to see when it was scanned, so root-cause analysis was slow. I restructured the workflow itself into 'scan first, reconcile against the P/L afterwards'.

Background & Problem

Key Features

Scanning: model number, lot ID and quantity (Qty) are accepted in any order into a buffer, and committed as one line item once all three are present. The type is auto-detected by regular expressions so operators never choose it. Bad reads trigger a red flash and an error sound, and an UNDO barcode removes the last entry. State: every delivery is tracked as scanning → awaiting → verified on a kanban home screen, and a job can be handed over by dragging its card onto another worker. Verification: the P/L and the scan results are shown side by side as a diff, distinguishing matches, shortages, overages and items that do not exist in the P/L at all. The confirm button stays disabled while any difference remains.

Key Features

A verification screen you can read

Results are rendered as a side-by-side table (P/L on the left, scans on the right, a status icon in the middle), with a dedicated badge for contaminating items. Clicking a contaminated row expands the scan timeline so you can see when it entered. In edit mode a wrong scan can be deleted in place and the diff is recomputed immediately; every deletion is recorded in an edit log.

A verification screen you can read

Technical Approach & Architecture

The target was existing Windows PCs with no extra server budget, so I chose Tauri v2 (Rust + WebView2): a single small installer, lighter than Electron. The frontend is plain HTML/CSS/vanilla JS with no framework or bundler. There are few screens and all state collapses into a per-delivery session, so having no build step was the better trade-off for maintainability. Only database access lives in Rust: odbc-api reads the P/L view and the frontend simply calls it through invoke. Using the native ODBC driver means existing DSN configuration is reused as-is, and local history files can be written — both impossible from a browser alone. Because scanning never touches the database, a slow or unavailable DB cannot stall the floor.

Engineering Highlights

Scanner input: scanners behave like a keyboard that types very fast and ends with Enter. A single capture-phase keydown listener discards the buffer after 55 ms of silence, which separates scanners from human typing. Input is ignored while a modal is open, and listeners and timers are released on every screen change. Connection safety and a change of direction: connection-string values are quoted only when they contain special characters. I originally wrapped every value in braces, but some driver managers then reported the DSN as 'not registered' on production PCs, so I changed the rule to quote only when necessary. Search keys are validated for length and character set and passed as parameters, preventing SQL injection. Credentials: DB credentials live outside the source, in a git-ignored config file or the saved Settings, with Settings taking priority. The app still starts if the file is absent. Still improving: minor defects found in code review have been fixed continuously, and handling of unusual input patterns is still being hardened in operation.

Engineering Highlights

Thai / Japanese and Dark Mode

Users are a mix of Thai-speaking floor staff and Japanese-speaking managers, so the UI is fully bilingual. The dictionary is key-based and is also used for dynamically built toasts, dialogs, diff labels and error messages, eliminating mixed-language screens. A dark theme keeps the scan flashes visible under varied warehouse lighting.

Thai / Japanese and Dark Mode

Outcome & Impact

Separating scanning from reconciliation lets inspection continue without waiting for the ERP to finalize the packing list. Because confirmation is blocked until the diff is zero, missed checks and contaminating items are prevented by the system rather than by procedure. Verified deliveries are stored as per-delivery JSON history files and can be exported as CSV (UTF-8 with BOM so Excel opens it cleanly). History is retained for three years to support handovers and later inquiries. Note: quantitative gains such as time saved have not been measured yet and are therefore not stated; measuring them after rollout is future work.

Outcome & Impact
← Back to overview