mirror of
https://github.com/inventree/inventree-app.git
synced 2025-06-12 10:15:32 +00:00
Po barcode scan (#458)
* Refactor existing barcode scan endpoint - Break out into new file just for purchase orders * Handle scanning of salesorder * Add new handler for adding items to PO via barcode * Allocate with barcode * Add new string
This commit is contained in:
@ -2,12 +2,13 @@ import "package:flutter/material.dart";
|
||||
|
||||
import "package:flutter_speed_dial/flutter_speed_dial.dart";
|
||||
import "package:font_awesome_flutter/font_awesome_flutter.dart";
|
||||
import "package:inventree/inventree/sales_order.dart";
|
||||
import "package:inventree/preferences.dart";
|
||||
import "package:inventree/widget/order/sales_order_detail.dart";
|
||||
import "package:one_context/one_context.dart";
|
||||
|
||||
|
||||
import "package:inventree/api.dart";
|
||||
import "package:inventree/api_form.dart";
|
||||
import "package:inventree/helpers.dart";
|
||||
import "package:inventree/l10.dart";
|
||||
|
||||
@ -166,6 +167,16 @@ class BarcodeScanHandler extends BarcodeHandler {
|
||||
}
|
||||
}
|
||||
|
||||
// Response when a SalesOrder instance is scanned
|
||||
Future<void> handleSalesOrder(int pk) async {
|
||||
var order = await InvenTreeSalesOrder().get(pk);
|
||||
|
||||
if (order is InvenTreeSalesOrder) {
|
||||
OneContext().pop();
|
||||
OneContext().push(MaterialPageRoute(
|
||||
builder: (context) => SalesOrderDetailWidget(order)));
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> onBarcodeMatched(Map<String, dynamic> data) async {
|
||||
@ -184,6 +195,7 @@ class BarcodeScanHandler extends BarcodeHandler {
|
||||
|
||||
if (InvenTreeAPI().supportsOrderBarcodes) {
|
||||
validModels.add("purchaseorder");
|
||||
validModels.add("salesorder");
|
||||
}
|
||||
|
||||
for (var key in validModels) {
|
||||
@ -219,6 +231,10 @@ class BarcodeScanHandler extends BarcodeHandler {
|
||||
case "purchaseorder":
|
||||
await handlePurchaseOrder(pk);
|
||||
return;
|
||||
case "salesorder":
|
||||
await handleSalesOrder(pk);
|
||||
return;
|
||||
// TODO: Handle manufacturer part
|
||||
default:
|
||||
// Fall through to failure state
|
||||
break;
|
||||
@ -478,116 +494,6 @@ class ScanParentLocationHandler extends BarcodeScanStockLocationHandler {
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Barcode handler class for scanning a supplier barcode to receive a part
|
||||
*
|
||||
* - The class can be initialized by optionally passing a valid, placed PurchaseOrder object
|
||||
* - Expects to scan supplier barcode, possibly containing order_number and quantity
|
||||
* - If location or quantity information wasn't provided, show a form to fill it in
|
||||
*/
|
||||
class POReceiveBarcodeHandler extends BarcodeHandler {
|
||||
|
||||
POReceiveBarcodeHandler({this.purchaseOrder, this.location});
|
||||
|
||||
InvenTreePurchaseOrder? purchaseOrder;
|
||||
InvenTreeStockLocation? location;
|
||||
|
||||
@override
|
||||
String getOverlayText(BuildContext context) => L10().barcodeReceivePart;
|
||||
|
||||
@override
|
||||
Future<void> processBarcode(String barcode,
|
||||
{String url = "barcode/po-receive/",
|
||||
Map<String, dynamic> extra_data = const {}}) {
|
||||
|
||||
final po_extra_data = {
|
||||
"purchase_order": purchaseOrder?.pk,
|
||||
"location": location?.pk,
|
||||
...extra_data,
|
||||
};
|
||||
|
||||
return super.processBarcode(barcode, url: url, extra_data: po_extra_data);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> onBarcodeMatched(Map<String, dynamic> data) async {
|
||||
if (!data.containsKey("lineitem")) {
|
||||
return onBarcodeUnknown(data);
|
||||
}
|
||||
|
||||
barcodeSuccessTone();
|
||||
showSnackIcon(L10().receivedItem, success: true);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> onBarcodeUnhandled(Map<String, dynamic> data) async {
|
||||
if (!data.containsKey("action_required") || !data.containsKey("lineitem")) {
|
||||
return super.onBarcodeUnhandled(data);
|
||||
}
|
||||
|
||||
final lineItemData = data["lineitem"] as Map<String, dynamic>;
|
||||
if (!lineItemData.containsKey("pk") || !lineItemData.containsKey("purchase_order")) {
|
||||
barcodeFailureTone();
|
||||
showSnackIcon(L10().missingData, success: false);
|
||||
}
|
||||
|
||||
// Construct fields to receive
|
||||
Map<String, dynamic> fields = {
|
||||
"line_item": {
|
||||
"parent": "items",
|
||||
"nested": true,
|
||||
"hidden": true,
|
||||
"value": lineItemData["pk"] as int,
|
||||
},
|
||||
"quantity": {
|
||||
"parent": "items",
|
||||
"nested": true,
|
||||
"value": lineItemData["quantity"] as double?,
|
||||
},
|
||||
"status": {
|
||||
"parent": "items",
|
||||
"nested": true,
|
||||
},
|
||||
"location": {
|
||||
"value": lineItemData["location"] as int?,
|
||||
},
|
||||
"barcode": {
|
||||
"parent": "items",
|
||||
"nested": true,
|
||||
"hidden": true,
|
||||
"type": "barcode",
|
||||
"value": data["barcode_data"] as String,
|
||||
}
|
||||
};
|
||||
|
||||
final context = OneContext().context!;
|
||||
final purchase_order_pk = lineItemData["purchase_order"];
|
||||
final receive_url = "${InvenTreePurchaseOrder().URL}${purchase_order_pk}/receive/";
|
||||
|
||||
launchApiForm(
|
||||
context,
|
||||
L10().receiveItem,
|
||||
receive_url,
|
||||
fields,
|
||||
method: "POST",
|
||||
icon: FontAwesomeIcons.rightToBracket,
|
||||
onSuccess: (data) async {
|
||||
showSnackIcon(L10().receivedItem, success: true);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> onBarcodeUnknown(Map<String, dynamic> data) async {
|
||||
barcodeFailureTone();
|
||||
showSnackIcon(
|
||||
data["error"] as String? ?? L10().barcodeError,
|
||||
success: false
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Barcode handler for finding a "unique" barcode (one that does not match an item in the database)
|
||||
*/
|
||||
|
Reference in New Issue
Block a user