mirror of
				https://github.com/inventree/inventree-app.git
				synced 2025-10-31 05:15:42 +00:00 
			
		
		
		
	* 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
		
			
				
	
	
		
			198 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
			
		
		
	
	
			198 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
| import "package:flutter/material.dart";
 | |
| import "package:inventree/preferences.dart";
 | |
| import "package:one_context/one_context.dart";
 | |
| import "package:inventree/l10.dart";
 | |
| 
 | |
| import "package:inventree/barcode/barcode.dart";
 | |
| import "package:inventree/barcode/handler.dart";
 | |
| import "package:inventree/barcode/tones.dart";
 | |
| 
 | |
| import "package:inventree/inventree/purchase_order.dart";
 | |
| import "package:inventree/inventree/stock.dart";
 | |
| 
 | |
| import "package:inventree/widget/snacks.dart";
 | |
| 
 | |
| /*
 | |
|  * 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, this.lineItem});
 | |
| 
 | |
|   InvenTreePurchaseOrder? purchaseOrder;
 | |
|   InvenTreeStockLocation? location;
 | |
|   InvenTreePOLineItem? lineItem;
 | |
| 
 | |
|   @override
 | |
|   String getOverlayText(BuildContext context) => L10().barcodeReceivePart;
 | |
| 
 | |
|   @override
 | |
|   Future<void> processBarcode(String barcode,
 | |
|       {String url = "barcode/po-receive/",
 | |
|         Map<String, dynamic> extra_data = const {}}) async {
 | |
| 
 | |
|     final bool confirm = await InvenTreeSettingsManager().getBool(INV_PO_CONFIRM_SCAN, true);
 | |
| 
 | |
|     final po_extra_data = {
 | |
|       "purchase_order": purchaseOrder?.pk,
 | |
|       "location": location?.pk,
 | |
|       "line_item": lineItem?.pk,
 | |
|       "auto_allocate": !confirm,
 | |
|       ...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") || data.containsKey("success")) {
 | |
|       barcodeSuccess(L10().receivedItem);
 | |
|       return;
 | |
|     } else {
 | |
|       return onBarcodeUnknown(data);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   @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);
 | |
|     }
 | |
| 
 | |
|     // At minimum, we need the line item ID value
 | |
|     final int? lineItemId = lineItemData["pk"] as int?;
 | |
| 
 | |
|     if (lineItemId == null) {
 | |
|       barcodeFailureTone();
 | |
|       return;
 | |
|     }
 | |
| 
 | |
|     InvenTreePOLineItem? lineItem = await InvenTreePOLineItem().get(lineItemId) as InvenTreePOLineItem?;
 | |
| 
 | |
|     if (lineItem == null) {
 | |
|       barcodeFailureTone();
 | |
|       return;
 | |
|     }
 | |
| 
 | |
|     // Next, extract the "optional" fields
 | |
| 
 | |
|     // Extract information from the returned server response
 | |
|     double? quantity = double.tryParse((lineItemData["quantity"] ?? "0").toString());
 | |
|     int? destination = lineItemData["location"] as int?;
 | |
|     String? barcode = data["barcode_data"] as String?;
 | |
| 
 | |
|     // Discard the barcode scanner at this stage
 | |
|     if (OneContext.hasContext) {
 | |
|       OneContext().pop();
 | |
|     }
 | |
| 
 | |
|     await lineItem.receive(
 | |
|       OneContext().context!,
 | |
|       destination: destination,
 | |
|       quantity: quantity,
 | |
|       barcode: barcode,
 | |
|       onSuccess: () {
 | |
|         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 to add a line item to a purchase order
 | |
|  */
 | |
| class POAllocateBarcodeHandler extends BarcodeHandler {
 | |
| 
 | |
|   POAllocateBarcodeHandler({this.purchaseOrder});
 | |
| 
 | |
|   InvenTreePurchaseOrder? purchaseOrder;
 | |
| 
 | |
|   @override
 | |
|   String getOverlayText(BuildContext context) => L10().scanSupplierPart;
 | |
| 
 | |
|   @override
 | |
|   Future<void> processBarcode(String barcode, {
 | |
|     String url = "barcode/po-allocate/",
 | |
|     Map<String, dynamic> extra_data = const {}}
 | |
|   ) {
 | |
| 
 | |
|     final po_extra_data = {
 | |
|       "purchase_order": purchaseOrder?.pk,
 | |
|       ...extra_data,
 | |
|     };
 | |
| 
 | |
|     return super.processBarcode(
 | |
|       barcode,
 | |
|       url: url,
 | |
|       extra_data: po_extra_data,
 | |
|     );
 | |
|   }
 | |
| 
 | |
|   @override
 | |
|   Future<void> onBarcodeMatched(Map<String, dynamic> data) async {
 | |
|     // Server must respond with a suppliertpart instance
 | |
|     if (!data.containsKey("supplierpart")) {
 | |
|       return onBarcodeUnknown(data);
 | |
|     }
 | |
| 
 | |
|     dynamic supplier_part = data["supplierpart"];
 | |
| 
 | |
|     int supplier_part_pk = -1;
 | |
| 
 | |
|     if (supplier_part is Map<String, dynamic>) {
 | |
|       supplier_part_pk = (supplier_part["pk"] ?? -1) as int;
 | |
|     } else {
 | |
|       return onBarcodeUnknown(data);
 | |
|     }
 | |
| 
 | |
|     // Dispose of the barcode scanner
 | |
|     if (OneContext.hasContext) {
 | |
|       OneContext().pop();
 | |
|     }
 | |
| 
 | |
|     final context = OneContext().context!;
 | |
| 
 | |
|     var fields = InvenTreePOLineItem().formFields();
 | |
| 
 | |
|     fields["order"]?["value"] = purchaseOrder!.pk;
 | |
|     fields["part"]?["hidden"] = false;
 | |
|     fields["part"]?["value"] = supplier_part_pk;
 | |
| 
 | |
|     InvenTreePOLineItem().createForm(
 | |
|       context,
 | |
|       L10().lineItemAdd,
 | |
|       fields: fields,
 | |
|     );
 | |
|   }
 | |
| 
 | |
|   @override
 | |
|   Future<void> onBarcodeUnhandled(Map<String, dynamic> data) async {
 | |
| 
 | |
|     print("onBarcodeUnhandled:");
 | |
|     print(data.toString());
 | |
| 
 | |
|     super.onBarcodeUnhandled(data);
 | |
|   }
 | |
| } |