mirror of
https://github.com/inventree/inventree-app.git
synced 2025-04-28 05:26:47 +00:00
Adds "barcode" field handler for API forms
This commit is contained in:
parent
38e4735f77
commit
6288088a65
@ -7,6 +7,7 @@ import "package:date_field/date_field.dart";
|
|||||||
|
|
||||||
import "package:inventree/api.dart";
|
import "package:inventree/api.dart";
|
||||||
import "package:inventree/app_colors.dart";
|
import "package:inventree/app_colors.dart";
|
||||||
|
import 'package:inventree/barcode.dart';
|
||||||
import "package:inventree/helpers.dart";
|
import "package:inventree/helpers.dart";
|
||||||
import "package:inventree/inventree/part.dart";
|
import "package:inventree/inventree/part.dart";
|
||||||
import "package:inventree/inventree/sentry.dart";
|
import "package:inventree/inventree/sentry.dart";
|
||||||
@ -269,7 +270,7 @@ class APIFormField {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Construct a widget for this input
|
// Construct a widget for this input
|
||||||
Widget constructField() {
|
Widget constructField(BuildContext context) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case "string":
|
case "string":
|
||||||
case "url":
|
case "url":
|
||||||
@ -288,6 +289,8 @@ class APIFormField {
|
|||||||
return _constructFileField();
|
return _constructFileField();
|
||||||
case "date":
|
case "date":
|
||||||
return _constructDateField();
|
return _constructDateField();
|
||||||
|
case "barcode":
|
||||||
|
return _constructBarcodeField(context);
|
||||||
default:
|
default:
|
||||||
return ListTile(
|
return ListTile(
|
||||||
title: Text(
|
title: Text(
|
||||||
@ -300,6 +303,52 @@ class APIFormField {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Field for capturing a barcode
|
||||||
|
Widget _constructBarcodeField(BuildContext context) {
|
||||||
|
|
||||||
|
TextEditingController controller = TextEditingController();
|
||||||
|
|
||||||
|
String barcode = (value ?? "").toString();
|
||||||
|
|
||||||
|
if (barcode.isEmpty) {
|
||||||
|
barcode = L10().barcodeNotAssigned;
|
||||||
|
}
|
||||||
|
|
||||||
|
controller.text = barcode;
|
||||||
|
|
||||||
|
return InputDecorator(
|
||||||
|
decoration: InputDecoration(
|
||||||
|
labelText: required ? label + "*" : label,
|
||||||
|
labelStyle: _labelStyle(),
|
||||||
|
helperText: helpText,
|
||||||
|
helperStyle: _helperStyle(),
|
||||||
|
hintText: placeholderText,
|
||||||
|
),
|
||||||
|
child: ListTile(
|
||||||
|
title: TextField(
|
||||||
|
readOnly: true,
|
||||||
|
controller: controller,
|
||||||
|
),
|
||||||
|
trailing: IconButton(
|
||||||
|
icon: FaIcon(FontAwesomeIcons.qrcode),
|
||||||
|
onPressed: () async {
|
||||||
|
|
||||||
|
var handler = UniqueBarcodeHandler((String hash) {
|
||||||
|
print("Scanned barcode: " + hash);
|
||||||
|
});
|
||||||
|
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(builder: (context) => InvenTreeQRView(handler)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// Field for displaying and selecting dates
|
// Field for displaying and selecting dates
|
||||||
Widget _constructDateField() {
|
Widget _constructDateField() {
|
||||||
|
|
||||||
@ -937,7 +986,7 @@ class _APIFormWidgetState extends State<APIFormWidget> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
widgets.add(field.constructField());
|
widgets.add(field.constructField(context));
|
||||||
|
|
||||||
if (field.hasErrors()) {
|
if (field.hasErrors()) {
|
||||||
for (String error in field.errorMessages()) {
|
for (String error in field.errorMessages()) {
|
||||||
|
@ -305,7 +305,7 @@ class StockItemBarcodeAssignmentHandler extends BarcodeHandler {
|
|||||||
}
|
}
|
||||||
).then((result) {
|
).then((result) {
|
||||||
if (result) {
|
if (result) {
|
||||||
failureTone();
|
successTone();
|
||||||
|
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
|
|
||||||
@ -315,7 +315,7 @@ class StockItemBarcodeAssignmentHandler extends BarcodeHandler {
|
|||||||
icon: FontAwesomeIcons.qrcode
|
icon: FontAwesomeIcons.qrcode
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
successTone();
|
failureTone();
|
||||||
|
|
||||||
showSnackIcon(
|
showSnackIcon(
|
||||||
L10().barcodeNotAssigned,
|
L10().barcodeNotAssigned,
|
||||||
@ -464,6 +464,63 @@ class StockLocationScanInItemsHandler extends BarcodeHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class UniqueBarcodeHandler extends BarcodeHandler {
|
||||||
|
/*
|
||||||
|
* Barcode handler for finding a "unique" barcode (one that does not match an item in the database)
|
||||||
|
*/
|
||||||
|
|
||||||
|
UniqueBarcodeHandler(this.callback);
|
||||||
|
|
||||||
|
// Callback function when a "unique" barcode hash is found
|
||||||
|
final Function(String) callback;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String getOverlayText(BuildContext context) => L10().barcodeScanAssign;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> onBarcodeMatched(BuildContext context, Map<String, dynamic> data) async {
|
||||||
|
|
||||||
|
failureTone();
|
||||||
|
|
||||||
|
// If the barcode is known, we can"t assign it to the stock item!
|
||||||
|
showSnackIcon(
|
||||||
|
L10().barcodeInUse,
|
||||||
|
icon: FontAwesomeIcons.qrcode,
|
||||||
|
success: false
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> onBarcodeUnknown(BuildContext context, Map<String, dynamic> data) async {
|
||||||
|
// If the barcode is unknown, we *can* assign it to the stock item!
|
||||||
|
|
||||||
|
if (!data.containsKey("hash")) {
|
||||||
|
showServerError(
|
||||||
|
L10().missingData,
|
||||||
|
L10().barcodeMissingHash,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
String hash = (data["hash"] ?? "") as String;
|
||||||
|
|
||||||
|
if (hash.isEmpty) {
|
||||||
|
failureTone();
|
||||||
|
|
||||||
|
showSnackIcon(
|
||||||
|
L10().barcodeError,
|
||||||
|
success: false,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// Close the barcode scanner
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
|
||||||
|
callback(hash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class InvenTreeQRView extends StatefulWidget {
|
class InvenTreeQRView extends StatefulWidget {
|
||||||
|
|
||||||
const InvenTreeQRView(this._handler, {Key? key}) : super(key: key);
|
const InvenTreeQRView(this._handler, {Key? key}) : super(key: key);
|
||||||
|
2
lib/l10n
2
lib/l10n
@ -1 +1 @@
|
|||||||
Subproject commit 74d796f7f1174fc27d5c031e18f4adbe1e16e6a4
|
Subproject commit 5f30fef900ea027cd7fe90b2d87a6f02ced315c0
|
@ -195,6 +195,13 @@ class _PurchaseOrderDetailState extends RefreshableState<PurchaseOrderDetailWidg
|
|||||||
"nested": true,
|
"nested": true,
|
||||||
},
|
},
|
||||||
"location": {
|
"location": {
|
||||||
|
},
|
||||||
|
"barcode": {
|
||||||
|
"parent": "items",
|
||||||
|
"nested": true,
|
||||||
|
"type": "barcode",
|
||||||
|
"label": L10().barcodeAssign,
|
||||||
|
"required": false,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user