Paper gate passes sound like a trivial problem until you see the workflow they create at a textile facility. A bale leaves the production floor. A supervisor fills out a form by hand. That form goes to a gate officer, who cross-checks it against a physical ledger. If anything is unclear or a number doesn't match, the truck waits. On a busy dispatch day, this produced delays of 2-3 hours at one of the facilities we worked with.
The TexOps QR tracking module replaced that entire process. Here is specifically how it works.
We considered RFID briefly. The read range and automation potential are appealing. But RFID readers cost significantly more per station, and this particular client had six gate points across two facility locations. The upfront hardware cost was the deciding factor. Every mobile device already had a camera, and the mobile_scanner package in Flutter handles QR scanning reliably under the fluorescent lighting conditions in the warehouses.
QR labels print cheaply. The label printer integration was handled server-side; when a bale is logged in the system, a label is generated automatically. That was not our implementation, but the point is that the label infrastructure cost was near zero compared to RFID tags on every bale.
Each bale has a document in Firestore with a status field that moves through a defined set of states:
received -> quality_check -> cleared -> dispatch_staged -> gate_passed -> deliveredWhen a QR code is scanned at any station, the app performs a Firestore write that updates the bale's status and timestamps the transition:
Future<void> recordGatePass({
required String baleId,
required String operatorId,
}) async {
final docRef = FirebaseFirestore.instance.collection('bales').doc(baleId);
await docRef.update({
'status': 'gate_passed',
'gatePassTimestamp': FieldValue.serverTimestamp(),
'gateOfficerId': operatorId,
});
}That is the entire gate pass action. No paper. No cross-check against a separate ledger. The admin dashboard reflects the update within about 2 seconds because it is running a Firestore snapshot listener on the bales collection.
Different staff see different things. A gate officer sees a scan interface and a list of pending dispatches for their shift. A Lab Engineer sees quality check queues and test report upload forms. The factory supervisor's dashboard shows aggregate bale flow, current holds, and daily dispatch totals.
This was all handled through Firestore security rules and a role field on each user document. The app checks the current user's role at login and renders the appropriate navigation. There is no separate codebase per role, just conditional widget rendering based on a role string pulled from Firestore.
Honestly, this part was simpler than we expected. The harder design work was defining the role matrix with the client before writing any code. They had informal role distinctions that had never been written down, and surfacing those during the requirements phase prevented a lot of rework later.
The 2-3 hour dispatch delays dropped to under 20 minutes in practice. A gate officer scans a QR, the system confirms the bale is cleared for dispatch, and the truck moves. If a bale is on hold for quality reasons, the scan returns a hold notice immediately.
The other change the client mentioned was accountability. When a bale went missing in the old system, tracing it required going through paper records dating back weeks. Now every bale transition is timestamped with the officer's ID. Disputes about when a bale left the facility, or who authorized a release, stopped being disputes.
That kind of auditability was not in the original brief. It came out of the data being there rather than from anyone planning for it. And that is usually how it works when you move paper workflows into a real database.