Home Services Work About Blog Contact Let's Talk
BlogFlutter Apps
Flutter Apps

Paper Dockets Were Causing 12 Errors a Week. Barcode Scanning Fixed That.

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:

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.

BEFORE: Paper docket workflow
Part / Item Barcode label Worker Writes Order No. by Hand Paper Dockets Collected End of Shift Admin Re-enters Into ERP Next Morning ! ! ! Machine-readable info exists Manual transcription error introduced here Overnight delay in data 12 errors/week 8.1 hrs/day wasted Every error at the ERP entry stage cost ~£140 to investigate and correct

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:

  1. 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.
  2. 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.
  3. Confirm Screen — shows the decoded production order number, part reference, and batch ID. Worker confirms or discards. One tap, not a form.
  4. 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.

Why mobile_scanner over camera package?

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.

Flutter — mobile_scanner implementation
// 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).

Manual fallback for damaged labels

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:

  1. Flutter app calls the SharePoint REST API: POST /_api/web/lists/getbytitle('ProductionScans')/items
  2. The request body contains the order reference, line number, UTC timestamp, worker email, and a boolean for whether it was a manual entry
  3. MSAL handles the OAuth 2.0 token — no separate auth service needed
  4. The new item appears instantly in the ProductionScans SharePoint List
  5. A Power Automate flow triggers on new items in that list
  6. The flow calls the ERP's webhook endpoint to update the production order status
  7. 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."

8.1 hrs → 0
Daily data re-entry time
12/wk → 1/mo
Transcription errors
47
Workers scanning on day one
£140
Average cost per corrected error
AFTER: Flutter barcode scan flow
Part / Item Phone Camera Scans Barcode Flutter App Confirms + Queues SharePoint List Updated Instantly Power Automate Updates ERP Barcode exists No handwriting Instant confirmation Real-time visibility No re-entry step No custom backend. No new software licences. No overnight delay.

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

What barcode formats does the Flutter mobile_scanner package support?
The mobile_scanner package supports QR codes, Code 128, Code 39, EAN-13, EAN-8, UPC-A, UPC-E, Data Matrix, PDF-417, and Aztec. For manufacturing environments with existing barcodes (typically Code 128 or QR), mobile_scanner handles these natively on both Android and iOS without any hardware barcode reader required.
Can a Flutter app scan barcodes on a factory floor with poor lighting?
Yes. mobile_scanner uses the device camera's auto-focus and exposure capabilities. For very dark environments, you can enable the torch programmatically. In our manufacturing deployments, we also let workers tap to focus on the barcode before scanning, which handles partially damaged or poorly lit labels reliably.
How does the Flutter app sync with SharePoint without a custom backend?
We use the SharePoint REST API directly from the Flutter app, authenticated via MSAL (Microsoft Authentication Library). Scanned production order data writes to a SharePoint List. Power Automate watches the list for new entries and triggers downstream updates — to the ERP, to the manager dashboard, or to notify quality control. No custom backend server needed.
What happens if a barcode is damaged or unreadable?
The app includes a manual entry fallback. If the camera cannot read the barcode after 3 seconds, a "Type manually" button appears. The worker can type the production order number. We also log manual entries separately so the operations team can identify which labels need reprinting — turning a workaround into a quality improvement signal.
AT

Akshara Technologies

Flutter & Business Automation Specialists

We build Flutter apps that eliminate manual processes in manufacturing, logistics, and field service — all connected to Microsoft 365 and SharePoint. No custom backend, no extra software licences.

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.

Talk to Our Team View Flutter Services

Related Articles