TL;DR
- An automotive parts subcontractor ran 3 production lines on paper dockets — workers handwrote order numbers, admin re-entered them next morning
- 3 people spent 2.7 hours each per day on data re-entry: 8.1 hours total, wasted every single day
- 12 transcription errors per week, each costing ~£140 to investigate and correct
- We built a Flutter app using mobile_scanner that scans barcodes on the production floor and writes directly to a SharePoint List
- Power Automate handles the ERP update — no custom backend, no new software licences
- Three months after go-live: zero daily re-entry hours, one error per month, 47 workers scanning without training issues
The Manufacturing Floor Problem No One Measured
When the operations manager at this automotive parts subcontractor first contacted us, he described the problem as "a bit of an admin bottleneck." That turned out to be a significant understatement.
The facility runs three production lines across two shifts, with 47 workers total. Every part that moves through the lines — whether it's a bracket, a stamped panel, or a sub-assembly — has a barcode label attached. That barcode carries the production order number, the part reference, and the batch ID. The barcode is there. It works. The information is machine-readable.
What happened next was the problem. Workers didn't scan the barcode. They couldn't — there was no scanner. Instead, they handwrote the production order number onto a paper docket that travelled with the parts through each stage of the line. By end of shift, a supervisor collected the stack of dockets from all three lines. The night admin team then typed every entry from those dockets into the company's ERP system the following morning.
No one had sat down and calculated what this was actually costing. The operations manager knew there were "a few errors a week" and that the admin team was "busy." He had no idea the true scale until we mapped the process properly — counting people, hours, and every error that triggered a rework investigation.
The barcode was already there on the part. The information existed in machine-readable form. They just had no way to capture it at the point of work. That's the gap we were asked to close.
The Real Cost: 8 Hours and 12 Mistakes Every Week
Before writing a single line of code, we spent two days on the floor documenting the current process. We timed every step. We counted errors by reviewing the ERP correction log for the previous three months. The numbers were worse than anyone expected.
The re-entry burden
Three members of the admin team handled ERP data entry from the paper dockets. Each person spent an average of 2 hours 42 minutes per day on this task alone — not on exception handling, not on analysis, just on typing numbers that already existed on barcodes. That's 8.1 hours of skilled admin time consumed every working day by a process that should not exist.
Multiply that across a 5-day week and you get 40.5 hours — effectively one full-time equivalent spent doing nothing but manual transcription. At a fully-loaded cost of roughly £18 per hour for that role, that's about £730 per week, or £38,000 per year, in labour alone.
The error rate
The ERP correction log told a stark story. Over the three months we reviewed, the average error count was 12 per week. The most common failure modes were:
- Transposed digits — order number 4817 entered as 4871, triggering a batch mismatch
- Illegible handwriting — a 6 written ambiguously, entered as 0 or 8 by the admin team
- Wrong quantity — the docket said 48 units completed, admin typed 84
- Missing dockets — a paper docket left on the floor, blown under a machine, never entered at all
Each error that reached the ERP required an investigation: someone had to go back to the paper docket, find the original record, determine the correct value, enter a correction, and notify quality control if the error had downstream implications. The operations manager estimated this took an average of about 45 minutes per error, split across two or three people. At fully-loaded costs, that works out to roughly £140 per corrected error.
Twelve errors a week at £140 each is £1,680 per week in correction overhead — on top of the £730 in re-entry labour. Total weekly cost of the paper docket process: just over £2,400. Nearly £125,000 annually. From a problem that no one had formally measured.
What We Built: Flutter + mobile_scanner + SharePoint
The solution needed to work in a factory environment, which meant a few hard constraints from day one. The app had to run on standard Android devices — the client wasn't buying specialist scanners. It needed to function even when the factory Wi-Fi dropped, which it did in certain parts of the floor near the heavy press equipment. It had to write data into the Microsoft 365 ecosystem the company already used. And it had to be something a 58-year-old line worker could pick up and use without a training session.
We chose Flutter for three reasons. First, a single codebase could target all the Android devices across both shifts without maintaining separate builds. Second, the mobile_scanner package gives Flutter apps direct, low-latency access to the device camera for barcode reading — no platform-specific code required. Third, we could build the entire app, connect it to SharePoint via the REST API, and ship it in under six weeks — which matched the client's urgency.
The app screens
The app has four screens, deliberately kept simple:
- Production Line Select — the worker taps which line they're on (1, 2, or 3). This sets the context for every scan in that session.
- Scan Screen — a full-screen camera view with a targeting reticle. Worker points at the barcode on the part. App beeps and vibrates on a successful read.
- Confirm Screen — shows the decoded production order number, part reference, and batch ID. Worker confirms or discards. One tap, not a form.
- Session Summary — shows how many parts scanned in the current shift, accessible with a swipe up from the scan screen.
There is no login screen. Authentication happens silently in the background via MSAL (Microsoft Authentication Library) using device-level credentials tied to the worker's Microsoft 365 account — which they were already signed into on their company device. From the worker's perspective, they open the app, pick their line, and start scanning. That's it.
Flutter's built-in camera package gives you raw camera frames but no barcode decoding. You'd need to add ML Kit or ZXing yourself and manage the decode loop manually. mobile_scanner wraps Google's ML Kit on Android and Apple's Vision framework on iOS, handles the decode loop internally, exposes a simple stream of barcode results, and supports QR, Code 128, Code 39, EAN-13, Data Matrix, and more — all natively. For a production environment where you need reliability over every barcode format your factory uses, mobile_scanner is the correct choice. The camera package is for building camera apps, not barcode scanners.
The Technical Implementation
The core scanning logic is simpler than most people expect. The complexity in a production barcode app isn't in the scan itself — it's in handling edge cases: duplicate scans, damaged labels, intermittent connectivity, and scan confirmation before data is committed.
// pubspec.yaml dependency // mobile_scanner: ^5.0.0 import 'package:mobile_scanner/mobile_scanner.dart'; import 'package:flutter/material.dart'; class BarcodeScanScreen extends StatefulWidget { const BarcodeScanScreen({super.key, required this.productionLine}); final int productionLine; @override State<BarcodeScanScreen> createState() => _BarcodeScanScreenState(); } class _BarcodeScanScreenState extends State<BarcodeScanScreen> { final MobileScannerController _controller = MobileScannerController( detectionSpeed: DetectionSpeed.noDuplicates, // prevent repeat fire returnImage: false, ); bool _isProcessing = false; void _onDetect(BarcodeCapture capture) async { if (_isProcessing) return; // guard against concurrent scans final barcode = capture.barcodes.firstOrNull; if (barcode?.rawValue == null) return; setState(() => _isProcessing = true); await _controller.stop(); // pause camera while confirming final orderRef = barcode!.rawValue!; // Haptic + audio feedback so worker knows scan landed HapticFeedback.mediumImpact(); final confirmed = await showConfirmSheet(context, orderRef); if (confirmed == true && context.mounted()) { await SharePointService.writeScan( orderRef: orderRef, line: widget.productionLine, scannedAt: DateTime.now().toUtc(), scannedBy: AuthService.currentUserEmail, ); } await _controller.start(); // resume camera for next scan setState(() => _isProcessing = false); } @override Widget build(BuildContext context) { return Scaffold( body: Stack(children: [ MobileScanner( controller: _controller, onDetect: _onDetect, ), ScannerOverlay(), // targeting reticle + line branding ManualEntryButton(), // fallback for damaged labels ]), ); } @override void dispose() { _controller.dispose(); super.dispose(); } }
A few implementation decisions worth noting:
DetectionSpeed.noDuplicates is critical in a factory environment. Without it, holding the camera on a barcode fires the detection callback dozens of times per second. With noDuplicates, the scanner only fires once per unique barcode value per session — so the same part can't accidentally be scanned twice in rapid succession.
Stopping the camera during confirmation prevents a worker from inadvertently scanning the next part while still looking at the confirm dialog for the previous one. The camera resumes the moment they dismiss the sheet.
Haptic feedback matters more than you'd expect on a noisy factory floor. An audio beep gets lost in ambient noise. A phone vibration is unambiguous — the worker feels the confirmation in their hand. We use HapticFeedback.mediumImpact() on success and HapticFeedback.heavyImpact() if the manual entry fallback is triggered, so there's a tactile difference between the two states.
Offline handling with SQLite
The heavy press equipment on Line 2 consistently knocked out Wi-Fi for 2–3 minutes at a time. We built a local SQLite write-through cache using the sqflite package. Every confirmed scan writes to the local database first — the SharePoint sync happens in a background isolate. If the network is down, the scan queue sits in SQLite and drains to SharePoint the moment connectivity returns. From the worker's perspective, scanning always works. The sync status is shown as a small indicator in the app header — green tick when synced, amber dot when queued, red if sync has failed for more than 5 minutes (which triggers a notification to the supervisor's device).
Factory barcodes get damaged — grease smears, partial tears, labels printed at the wrong density. If the camera fails to decode a barcode within 3 seconds of the worker centering it in the reticle, a "Type manually" button appears. The worker can type the order number directly. Critically, manual entries are flagged separately in the SharePoint List with a ManualEntry: true column and a FailedLabelId field. The operations team gets a weekly Power Automate report of all manual entries, which tells them exactly which labels need reprinting. The workaround becomes a quality improvement signal rather than a silent data gap.
SharePoint as the Backbone — No Custom Backend
One of the most common reactions we get when describing this architecture is surprise that there's no backend server. No Node.js API, no Azure Functions middleware, no database hosted anywhere. The Flutter app writes directly to SharePoint, and Power Automate handles everything downstream.
Here's the full data flow after a successful scan:
- Flutter app calls the SharePoint REST API:
POST /_api/web/lists/getbytitle('ProductionScans')/items - The request body contains the order reference, line number, UTC timestamp, worker email, and a boolean for whether it was a manual entry
- MSAL handles the OAuth 2.0 token — no separate auth service needed
- The new item appears instantly in the
ProductionScansSharePoint List - A Power Automate flow triggers on new items in that list
- The flow calls the ERP's webhook endpoint to update the production order status
- A second branch of the flow sends a Teams notification to the quality control channel if the scanned batch matches any open quality holds
The ERP integration is the part that usually worries clients. "Can Power Automate really talk to our ERP?" In this case, yes — the ERP had an HTTP webhook endpoint that accepted JSON payloads for production order updates. Power Automate's HTTP action handled the call cleanly. For ERPs without a webhook (which is common), you can use Power Automate's SAP, Dynamics, or database connectors depending on what the system is.
The SharePoint List is also the management dashboard. The operations manager has a SharePoint page with a List view filtered to today's date, grouped by production line. He can see in real time which orders are progressing through which lines, without asking anyone or waiting for morning re-entry. That visibility was, in his words, "a bigger win than eliminating the errors."
Three Months After Launch
We did a structured review call with the operations manager 90 days after go-live. He'd been keeping informal notes and had pulled the ERP correction log to compare against the pre-project baseline.
The numbers
Daily re-entry time: effectively zero. The three admin team members who previously spent 2.7 hours each on ERP transcription now spend that time on exception handling, supplier queries, and planning work — tasks that actually require human judgment. No one was made redundant; they were redeployed into higher-value work on day one.
Errors: one in the first month, zero in months two and three. The single month-one error was a Power Automate configuration issue on the ERP webhook call — a field mapping that sent the wrong status code for a specific order type. We fixed it in about 20 minutes once identified. Every error since launch has been zero from the scanning and transcription side.
Adoption: all 47 workers were scanning on the first day. The go-live session was 25 minutes: we gathered both shifts before changeover, showed them the three-tap flow (open app, pick line, scan), answered six questions, and that was it. The most common question was "what do I do if the barcode won't scan?" — which was already handled by the manual entry fallback.
The unexpected benefit
The operations manager flagged something we hadn't specifically designed for. Because every scan is timestamped and attributed to a worker and a line, the company now has granular cycle time data for the first time. They can see how long parts spend at each stage, identify which shifts move faster, and spot bottlenecks in real time. Before the app, this analysis would have required a separate time-and-motion study. Now it comes free from the scan log.
He's using that data to make the case for a second project: integrating the scan timestamps with the planning system to produce live production completion forecasts. That one's in scoping now.
Key Takeaways
Eliminate the re-entry step entirely. If information already exists as a barcode, any process that involves a human copying it by hand is a waste — and a source of errors. The fix isn't "be more careful." It's removing the manual step completely with a scanning app.
Barcode scanning accuracy vs manual transcription is not comparable. A camera reading a Code 128 barcode is effectively zero-error. Human transcription of 6–8 digit strings across a noisy, busy floor averages around 1–3% error rate. For a facility processing hundreds of production orders per week, that gap is enormous.
SharePoint as the data target removes the need for a custom backend. If your organisation is already on Microsoft 365, you have a governed, authenticated, auditable data store available immediately. Writing to a SharePoint List via the REST API is production-ready for this class of use case — no custom server to host, secure, or maintain.
Power Automate handles the ERP integration without custom code. Most ERP systems have either a REST API, a database connector, or an SFTP-based import. Power Automate has native connectors or an HTTP action that covers all three. You don't need a custom integration layer for the majority of manufacturing ERP update scenarios.
The manual entry fallback is a quality improvement signal, not just a workaround. Logging which barcodes triggered manual entry tells you exactly which labels need reprinting. Surfacing that list in a weekly Power Automate report turns an edge case into a continuous label quality programme. Don't hide the fallback — make it visible to ops.
Frequently Asked Questions
Got paper dockets that should be digital?
We build Flutter barcode scanning apps for manufacturing and logistics teams — integrated with SharePoint, Power Automate, and your existing Microsoft 365 stack.