mirror of
				https://github.com/inventree/inventree-app.git
				synced 2025-10-31 21:35:42 +00:00 
			
		
		
		
	Add part to sales order via barcode scan (#461)
* Add part to sales order via barcode scan * Update release notes * Remove unused imports
This commit is contained in:
		| @@ -7,6 +7,8 @@ | |||||||
| - Fixes bug when removing entire quantity of a stock item | - Fixes bug when removing entire quantity of a stock item | ||||||
| - Add line items to purchase orders directly from the app | - Add line items to purchase orders directly from the app | ||||||
| - Add line items to purchase order using barcode scanner | - Add line items to purchase order using barcode scanner | ||||||
|  | - Add line items to sales orders directly from the app | ||||||
|  | - Add line items to sales order using barcode scanner | ||||||
|  |  | ||||||
|  |  | ||||||
| ### 0.13.0 - October 2023 | ### 0.13.0 - October 2023 | ||||||
|   | |||||||
| @@ -188,7 +188,6 @@ class POAllocateBarcodeHandler extends BarcodeHandler { | |||||||
|       context, |       context, | ||||||
|       L10().lineItemAdd, |       L10().lineItemAdd, | ||||||
|       fields: fields, |       fields: fields, | ||||||
|       onSuccess: (data) async {}, |  | ||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										81
									
								
								lib/barcode/sales_order.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								lib/barcode/sales_order.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,81 @@ | |||||||
|  | import "package:flutter/material.dart"; | ||||||
|  |  | ||||||
|  | import "package:inventree/inventree/part.dart"; | ||||||
|  | import "package:inventree/inventree/sales_order.dart"; | ||||||
|  | import "package:one_context/one_context.dart"; | ||||||
|  |  | ||||||
|  | import "package:inventree/l10.dart"; | ||||||
|  |  | ||||||
|  | import "package:inventree/barcode/handler.dart"; | ||||||
|  | import "package:inventree/barcode/tones.dart"; | ||||||
|  |  | ||||||
|  | import "package:inventree/widget/snacks.dart"; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Barcode handler class for scanning a new part into a SalesOrder | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | class SOAddItemBarcodeHandler extends BarcodeHandler { | ||||||
|  |  | ||||||
|  |   SOAddItemBarcodeHandler({this.salesOrder}); | ||||||
|  |  | ||||||
|  |   InvenTreeSalesOrder? salesOrder; | ||||||
|  |  | ||||||
|  |   @override | ||||||
|  |   String getOverlayText(BuildContext context) => L10().barcodeScanPart; | ||||||
|  |  | ||||||
|  |   @override | ||||||
|  |   Future<void> onBarcodeMatched(Map<String, dynamic> data) async { | ||||||
|  |  | ||||||
|  |     // Extract the part ID from the returned data | ||||||
|  |     int part_id = -1; | ||||||
|  |  | ||||||
|  |     if (data.containsKey("part")) { | ||||||
|  |       part_id = (data["part"] ?? {} as Map<String, dynamic>)["pk"] as int; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (part_id <= 0) { | ||||||
|  |       return onBarcodeUnknown(data); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // Request the part from the server | ||||||
|  |     var part = await InvenTreePart().get(part_id); | ||||||
|  |  | ||||||
|  |     if (part is InvenTreePart) { | ||||||
|  |  | ||||||
|  |       if (part.isSalable) { | ||||||
|  |         // Dispose of the barcode scanner | ||||||
|  |         if (OneContext.hasContext) { | ||||||
|  |           OneContext().pop(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         final context = OneContext().context!; | ||||||
|  |  | ||||||
|  |         var fields = InvenTreeSOLineItem().formFields(); | ||||||
|  |  | ||||||
|  |         fields["order"]?["value"] = salesOrder!.pk; | ||||||
|  |         fields["order"]?["hidden"] = true; | ||||||
|  |  | ||||||
|  |         fields["part"]?["value"] = part.pk; | ||||||
|  |         fields["part"]?["hidden"] = false; | ||||||
|  |  | ||||||
|  |         InvenTreeSOLineItem().createForm( | ||||||
|  |           context, | ||||||
|  |           L10().lineItemAdd, | ||||||
|  |           fields: fields, | ||||||
|  |         ); | ||||||
|  |  | ||||||
|  |       } else { | ||||||
|  |         barcodeFailureTone(); | ||||||
|  |         showSnackIcon(L10().partNotSalable, success: false); | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |     } else { | ||||||
|  |       // Failed to fetch part | ||||||
|  |       return onBarcodeUnknown(data); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |   } | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -118,7 +118,11 @@ class InvenTreeSOLineItem extends InvenTreeOrderLine { | |||||||
|       "order": { |       "order": { | ||||||
|         "hidden": true, |         "hidden": true, | ||||||
|       }, |       }, | ||||||
|       "part": {}, |       "part": { | ||||||
|  |         "filters": { | ||||||
|  |           "salable": true, | ||||||
|  |         } | ||||||
|  |       }, | ||||||
|       "quantity": {}, |       "quantity": {}, | ||||||
|       "reference": {}, |       "reference": {}, | ||||||
|       "notes": {}, |       "notes": {}, | ||||||
|   | |||||||
| @@ -112,6 +112,9 @@ | |||||||
|   "barcodeNotAssigned": "Barcode not assigned", |   "barcodeNotAssigned": "Barcode not assigned", | ||||||
|   "@barcodeNotAssigned": {}, |   "@barcodeNotAssigned": {}, | ||||||
|  |  | ||||||
|  |   "barcodeScanPart": "Scan part barcode", | ||||||
|  |   "@barcodeScanPart": {}, | ||||||
|  |  | ||||||
|   "barcodeReceivePart": "Scan barcode to receive part", |   "barcodeReceivePart": "Scan barcode to receive part", | ||||||
|   "@barcodeReceivePart": {}, |   "@barcodeReceivePart": {}, | ||||||
|  |  | ||||||
| @@ -766,6 +769,9 @@ | |||||||
|     "description": "Part (multiple)" |     "description": "Part (multiple)" | ||||||
|   }, |   }, | ||||||
|  |  | ||||||
|  |   "partNotSalable": "Part not marked as salable", | ||||||
|  |   "@partNotSalable": {}, | ||||||
|  |  | ||||||
|   "partsNone": "No Parts", |   "partsNone": "No Parts", | ||||||
|   "@partsNone": {}, |   "@partsNone": {}, | ||||||
|  |  | ||||||
|   | |||||||
| @@ -2,6 +2,8 @@ | |||||||
| import "package:flutter/material.dart"; | import "package:flutter/material.dart"; | ||||||
| import "package:flutter_speed_dial/flutter_speed_dial.dart"; | import "package:flutter_speed_dial/flutter_speed_dial.dart"; | ||||||
| import "package:font_awesome_flutter/font_awesome_flutter.dart"; | import "package:font_awesome_flutter/font_awesome_flutter.dart"; | ||||||
|  | import "package:inventree/barcode/barcode.dart"; | ||||||
|  | import "package:inventree/barcode/sales_order.dart"; | ||||||
| import "package:inventree/inventree/company.dart"; | import "package:inventree/inventree/company.dart"; | ||||||
| import "package:inventree/inventree/sales_order.dart"; | import "package:inventree/inventree/sales_order.dart"; | ||||||
| import "package:inventree/widget/order/so_line_list.dart"; | import "package:inventree/widget/order/so_line_list.dart"; | ||||||
| @@ -101,7 +103,20 @@ class _SalesOrderDetailState extends RefreshableState<SalesOrderDetailWidget> { | |||||||
|   List<SpeedDialChild> barcodeButtons(BuildContext context) { |   List<SpeedDialChild> barcodeButtons(BuildContext context) { | ||||||
|     List<SpeedDialChild> actions = []; |     List<SpeedDialChild> actions = []; | ||||||
|  |  | ||||||
|     // TODO |     if (widget.order.isOpen && InvenTreeSOLineItem().canCreate) { | ||||||
|  |       actions.add( | ||||||
|  |         SpeedDialChild( | ||||||
|  |           child: Icon(Icons.barcode_reader), | ||||||
|  |           label: L10().lineItemAdd, | ||||||
|  |           onTap: () async { | ||||||
|  |             scanBarcode( | ||||||
|  |               context, | ||||||
|  |               handler: SOAddItemBarcodeHandler(salesOrder: widget.order), | ||||||
|  |             ); | ||||||
|  |           } | ||||||
|  |         ) | ||||||
|  |       ); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     return actions; |     return actions; | ||||||
|   } |   } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user