mirror of
				https://github.com/inventree/inventree-app.git
				synced 2025-10-31 13:25:40 +00:00 
			
		
		
		
	Refactor stock adjustment actions
- Handle timeout - Handle error
This commit is contained in:
		| @@ -1,4 +1,5 @@ | |||||||
| import 'package:InvenTree/inventree/part.dart'; | import 'package:InvenTree/inventree/part.dart'; | ||||||
|  | import 'package:InvenTree/widget/dialogs.dart'; | ||||||
| import 'package:flutter/cupertino.dart'; | import 'package:flutter/cupertino.dart'; | ||||||
| import 'package:http/http.dart' as http; | import 'package:http/http.dart' as http; | ||||||
| import 'model.dart'; | import 'model.dart'; | ||||||
| @@ -391,51 +392,81 @@ class InvenTreeStockItem extends InvenTreeModel { | |||||||
|     return item; |     return item; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   Future<http.Response> countStock(double quan, {String notes}) async { |   /* | ||||||
|  |    * Perform stocktake action: | ||||||
|  |    * | ||||||
|  |    * - Add | ||||||
|  |    * - Remove | ||||||
|  |    * - Count | ||||||
|  |    */ | ||||||
|  |   Future<bool> adjustStock(BuildContext context, String endpoint, double q, {String notes}) async { | ||||||
|  |  | ||||||
|     // Cannot 'count' a serialized StockItem |     // Serialized stock cannot be adjusted | ||||||
|     if (isSerialized()) { |     if (isSerialized()) { | ||||||
|       return null; |       return false; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Cannot count negative stock |     // Cannot handle negative stock | ||||||
|     if (quan < 0) { |     if (q < 0) { | ||||||
|       return null; |       return false; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return api.post("/stock/count/", body: { |     var response = await api.post( | ||||||
|       "item": { |       endpoint, | ||||||
|         "pk": "${pk}", |       body: { | ||||||
|         "quantity": "${quan}", |         "item": { | ||||||
|       }, |           "pk": "${pk}", | ||||||
|       "notes": notes ?? '', |           "quantity": "${q}", | ||||||
|  |         }, | ||||||
|  |         "notes": notes ?? '', | ||||||
|  |     }).timeout(Duration(seconds: 10)).catchError((error) { | ||||||
|  |       if (error is TimeoutException) { | ||||||
|  |         showTimeoutError(context); | ||||||
|  |       } else if (error is SocketException) { | ||||||
|  |         showServerError( | ||||||
|  |             context, | ||||||
|  |             I18N.of(context).connectionRefused, | ||||||
|  |             error.toString() | ||||||
|  |         ); | ||||||
|  |       } else { | ||||||
|  |         // Re-throw the error, let sentry handle it! | ||||||
|  |         throw error; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       // Null response if error | ||||||
|  |       return null; | ||||||
|     }); |     }); | ||||||
|  |  | ||||||
|  |     if (response == null) return false; | ||||||
|  |  | ||||||
|  |     if (response.statusCode != 200) { | ||||||
|  |       showStatusCodeError(context, response.statusCode); | ||||||
|  |       return false; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // Stock adjustment succeeded! | ||||||
|  |     return true; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   Future<http.Response> addStock(double quan, {String notes}) async { |   Future<bool> countStock(BuildContext context, double q, {String notes}) async { | ||||||
|  |  | ||||||
|     if (isSerialized() || quan <= 0) return null; |     final bool result = await adjustStock(context, "/stock/count", q, notes: notes); | ||||||
|  |  | ||||||
|     return api.post("/stock/add/", body: { |     return result; | ||||||
|       "item": { |  | ||||||
|         "pk": "${pk}", |  | ||||||
|         "quantity": "${quan}", |  | ||||||
|       }, |  | ||||||
|       "notes": notes ?? '', |  | ||||||
|     }); |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   Future<http.Response> removeStock(double quan, {String notes}) async { |   Future<bool> addStock(BuildContext context, double q, {String notes}) async { | ||||||
|  |  | ||||||
|     if (isSerialized() || quan <= 0) return null; |     final bool result = await adjustStock(context,  "/stock/add/", q, notes: notes); | ||||||
|  |  | ||||||
|     return api.post("/stock/remove/", body: { |     return result; | ||||||
|       "item": { |   } | ||||||
|         "pk": "${pk}", |  | ||||||
|         "quantity": "${quan}", |   Future<bool> removeStock(BuildContext context, double q, {String notes}) async { | ||||||
|       }, |  | ||||||
|       "notes": notes ?? '', |     final bool result = await adjustStock(context, "/stock/remove/", q, notes: notes); | ||||||
|     }); |  | ||||||
|  |     return result; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   Future<http.Response> transferStock(int location, {double quantity, String notes}) async { |   Future<http.Response> transferStock(int location, {double quantity, String notes}) async { | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								lib/l10n
									
									
									
									
									
								
							
							
								
								
								
								
								
							
						
						
									
										2
									
								
								lib/l10n
									
									
									
									
									
								
							 Submodule lib/l10n updated: 249e4964a0...ed3bd59b15
									
								
							| @@ -70,13 +70,11 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> { | |||||||
|     double quantity = double.parse(_quantityController.text); |     double quantity = double.parse(_quantityController.text); | ||||||
|     _quantityController.clear(); |     _quantityController.clear(); | ||||||
|  |  | ||||||
|     // Await response to prevent the button from being pressed multiple times |     final bool result = await item.addStock(context, quantity, notes: _notesController.text); | ||||||
|     var response = await item.addStock(quantity, notes: _notesController.text); |  | ||||||
|     _notesController.clear(); |     _notesController.clear(); | ||||||
|  |  | ||||||
|     _stockUpdateMessage(response); |     _stockUpdateMessage(result); | ||||||
|  |  | ||||||
|     // TODO - Handle error cases |  | ||||||
|     refresh(); |     refresh(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -111,20 +109,27 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> { | |||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   void _stockUpdateMessage(bool result) { | ||||||
|  |  | ||||||
|  |     showSnackIcon( | ||||||
|  |       refreshableKey, | ||||||
|  |       result ? "Stock item updated" : "Stock item updated failed", | ||||||
|  |       success: result | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   void _removeStock() async { |   void _removeStock() async { | ||||||
|     Navigator.of(context).pop(); |     Navigator.of(context).pop(); | ||||||
|  |  | ||||||
|     double quantity = double.parse(_quantityController.text); |     double quantity = double.parse(_quantityController.text); | ||||||
|     _quantityController.clear(); |     _quantityController.clear(); | ||||||
|  |  | ||||||
|     var response = await item.removeStock(quantity, notes: _notesController.text); |     final bool result = await item.removeStock(context, quantity, notes: _notesController.text); | ||||||
|     _notesController.clear(); |  | ||||||
|  |  | ||||||
|     // TODO - Handle error cases |     _stockUpdateMessage(result); | ||||||
|  |  | ||||||
|     refresh(); |     refresh(); | ||||||
|  |  | ||||||
|     // TODO - Display a snackbar here indicating the action was successful (or otherwise) |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   void _removeStockDialog() { |   void _removeStockDialog() { | ||||||
| @@ -166,19 +171,16 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> { | |||||||
|     double quantity = double.parse(_quantityController.text); |     double quantity = double.parse(_quantityController.text); | ||||||
|     _quantityController.clear(); |     _quantityController.clear(); | ||||||
|  |  | ||||||
|     var response = await item.countStock(quantity, notes: _notesController.text); |     final bool result = await item.countStock(context, quantity, notes: _notesController.text); | ||||||
|     _notesController.clear(); |  | ||||||
|  |  | ||||||
|     // TODO - Handle error cases, timeout, etc |     _stockUpdateMessage(result); | ||||||
|  |  | ||||||
|     refresh(); |     refresh(); | ||||||
|  |  | ||||||
|     // TODO - Display a snackbar here indicating the action was successful (or otherwise) |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   void _countStockDialog() async { |   void _countStockDialog() async { | ||||||
|  |  | ||||||
|     _quantityController.text = item.quantity.toString(); |     _quantityController.text = item.quantityString; | ||||||
|     _notesController.clear(); |     _notesController.clear(); | ||||||
|  |  | ||||||
|     showFormDialog(context, I18N.of(context).countStock, |     showFormDialog(context, I18N.of(context).countStock, | ||||||
| @@ -194,7 +196,7 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> { | |||||||
|       fields: <Widget> [ |       fields: <Widget> [ | ||||||
|         QuantityField( |         QuantityField( | ||||||
|           label: I18N.of(context).countStock, |           label: I18N.of(context).countStock, | ||||||
|           hint: "${item.quantity}", |           hint: "${item.quantityString}", | ||||||
|           controller: _quantityController, |           controller: _quantityController, | ||||||
|         ), |         ), | ||||||
|         TextFormField( |         TextFormField( | ||||||
| @@ -233,7 +235,7 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> { | |||||||
|  |  | ||||||
|     InvenTreeStockLocation selectedLocation; |     InvenTreeStockLocation selectedLocation; | ||||||
|  |  | ||||||
|     _quantityController.text = "${item.quantity}"; |     _quantityController.text = "${item.quantityString}"; | ||||||
|  |  | ||||||
|     showFormDialog(context, I18N.of(context).transferStock, |     showFormDialog(context, I18N.of(context).transferStock, | ||||||
|         key: _moveStockKey, |         key: _moveStockKey, | ||||||
| @@ -385,7 +387,7 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> { | |||||||
|           ListTile( |           ListTile( | ||||||
|             title: Text(I18N.of(context).quantity), |             title: Text(I18N.of(context).quantity), | ||||||
|             leading: FaIcon(FontAwesomeIcons.cubes), |             leading: FaIcon(FontAwesomeIcons.cubes), | ||||||
|             trailing: Text("${item.quantity}"), |             trailing: Text("${item.quantityString}"), | ||||||
|           ) |           ) | ||||||
|       ); |       ); | ||||||
|     } |     } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user