2
0
mirror of https://github.com/inventree/inventree-app.git synced 2025-04-27 21:16:48 +00:00
inventree-app/lib/barcode/handler.dart
Oliver 524c5469f1
[refactor] Scan improvements (#577)
* Handle error on unexpected barcode response

* Add ManufacturerPart detail view

* Support barcode scanning for manufacturer part

* Refactoring for null checks

* Ignore selected errors in sentry

* Fix API implementation for ManufacturerPart

* Update release notes

* More error handling

* Decode quantity betterer

* Refactoring

* Add option to confirm checkin details

* Improve response handlign

* Cleanup

* Remove unused imports

* Fix async function

* Fix for assigning custom barcode

* Handle barcode scan result for company

* Fix

* Adjust scan priority

* Refactoring MODEL_TYPE

- Use instead of duplicated const strings

* @override fix
2024-12-14 15:24:23 +11:00

137 lines
3.7 KiB
Dart

import "package:flutter/material.dart";
import "package:flutter_tabler_icons/flutter_tabler_icons.dart";
import "package:inventree/api.dart";
import "package:inventree/helpers.dart";
import "package:inventree/l10.dart";
import "package:inventree/barcode/tones.dart";
import "package:inventree/inventree/sentry.dart";
import "package:inventree/widget/dialogs.dart";
import "package:inventree/widget/snacks.dart";
/* Generic class which "handles" a barcode, by communicating with the InvenTree server,
* and handling match / unknown / error cases.
*
* Override functionality of this class to perform custom actions,
* based on the response returned from the InvenTree server
*/
class BarcodeHandler {
BarcodeHandler();
// Return the text to display on the barcode overlay
// Note: Will be overridden by child classes
String getOverlayText(BuildContext context) => "Barcode Overlay";
// Called when the server "matches" a barcode
Future<void> onBarcodeMatched(Map<String, dynamic> data) async {
// Override this function
}
// Called when the server does not know about a barcode
Future<void> onBarcodeUnknown(Map<String, dynamic> data) async {
// Override this function
barcodeFailureTone();
showSnackIcon(
(data["error"] ?? L10().barcodeNoMatch) as String,
success: false,
icon: Icons.qr_code,
);
}
// Called when the server returns an unhandled response
Future<void> onBarcodeUnhandled(Map<String, dynamic> data) async {
barcodeFailureTone();
showServerError("barcode/", L10().responseUnknown, data.toString());
}
/*
* Base function to capture and process barcode data.
*
* Returns true only if the barcode scanner should remain open
*/
Future<void> processBarcode(String barcode,
{String url = "barcode/",
Map<String, dynamic> extra_data = const {}}) async {
debug("Scanned barcode data: '${barcode}'");
barcode = barcode.trim();
// Empty barcode is invalid
if (barcode.isEmpty) {
barcodeFailureTone();
showSnackIcon(
L10().barcodeError,
icon: TablerIcons.exclamation_circle,
success: false
);
return;
}
APIResponse? response;
try {
response = await InvenTreeAPI().post(
url,
body: {
"barcode": barcode,
...extra_data,
},
expectedStatusCode: null, // Do not show an error on "unexpected code"
);
} catch (error, stackTrace) {
sentryReportError("Barcode.processBarcode", error, stackTrace);
response = null;
}
if (response == null) {
barcodeFailureTone();
showSnackIcon(L10().barcodeError, success: false);
return;
}
debug("Barcode scan response" + response.data.toString());
Map<String, dynamic> data = response.asMap();
// Handle strange response from the server
if (!response.isValid() || !response.isMap()) {
await onBarcodeUnknown({});
showSnackIcon(L10().serverError, success: false);
// We want to know about this one!
await sentryReportMessage(
"BarcodeHandler.processBarcode returned unexpected value",
context: {
"data": response.data?.toString() ?? "null",
"barcode": barcode,
"url": url,
"statusCode": response.statusCode.toString(),
"valid": response.isValid().toString(),
"error": response.error,
"errorDetail": response.errorDetail,
"className": "${this}",
}
);
} else if (data.containsKey("success")) {
await onBarcodeMatched(data);
} else if ((response.statusCode >= 400) || data.containsKey("error")) {
await onBarcodeUnknown(data);
} else {
await onBarcodeUnhandled(data);
}
}
}