From 3757010599ddf1082f5545d184139921ab13f739 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Wed, 10 Feb 2021 23:54:00 +1100 Subject: [PATCH] Refactor stock adjustment actions - Handle timeout - Handle error --- lib/inventree/stock.dart | 91 ++++++++++++++++++++++++------------ lib/l10n | 2 +- lib/widget/stock_detail.dart | 36 +++++++------- 3 files changed, 81 insertions(+), 48 deletions(-) diff --git a/lib/inventree/stock.dart b/lib/inventree/stock.dart index 022d0642..0d3aaab6 100644 --- a/lib/inventree/stock.dart +++ b/lib/inventree/stock.dart @@ -1,4 +1,5 @@ import 'package:InvenTree/inventree/part.dart'; +import 'package:InvenTree/widget/dialogs.dart'; import 'package:flutter/cupertino.dart'; import 'package:http/http.dart' as http; import 'model.dart'; @@ -391,51 +392,81 @@ class InvenTreeStockItem extends InvenTreeModel { return item; } - Future countStock(double quan, {String notes}) async { + /* + * Perform stocktake action: + * + * - Add + * - Remove + * - Count + */ + Future adjustStock(BuildContext context, String endpoint, double q, {String notes}) async { - // Cannot 'count' a serialized StockItem + // Serialized stock cannot be adjusted if (isSerialized()) { - return null; + return false; } - // Cannot count negative stock - if (quan < 0) { - return null; + // Cannot handle negative stock + if (q < 0) { + return false; } - return api.post("/stock/count/", body: { - "item": { - "pk": "${pk}", - "quantity": "${quan}", - }, - "notes": notes ?? '', + var response = await api.post( + endpoint, + body: { + "item": { + "pk": "${pk}", + "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 addStock(double quan, {String notes}) async { + Future 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: { - "item": { - "pk": "${pk}", - "quantity": "${quan}", - }, - "notes": notes ?? '', - }); + return result; } - Future removeStock(double quan, {String notes}) async { + Future 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: { - "item": { - "pk": "${pk}", - "quantity": "${quan}", - }, - "notes": notes ?? '', - }); + return result; + } + + Future removeStock(BuildContext context, double q, {String notes}) async { + + final bool result = await adjustStock(context, "/stock/remove/", q, notes: notes); + + return result; } Future transferStock(int location, {double quantity, String notes}) async { diff --git a/lib/l10n b/lib/l10n index 249e4964..ed3bd59b 160000 --- a/lib/l10n +++ b/lib/l10n @@ -1 +1 @@ -Subproject commit 249e4964a08b79e53df7e1ea18b051de0d307905 +Subproject commit ed3bd59b15b2c69b9a21649a0e0507efd811c1a1 diff --git a/lib/widget/stock_detail.dart b/lib/widget/stock_detail.dart index 2acca4c7..7b173410 100644 --- a/lib/widget/stock_detail.dart +++ b/lib/widget/stock_detail.dart @@ -70,13 +70,11 @@ class _StockItemDisplayState extends RefreshableState { double quantity = double.parse(_quantityController.text); _quantityController.clear(); - // Await response to prevent the button from being pressed multiple times - var response = await item.addStock(quantity, notes: _notesController.text); + final bool result = await item.addStock(context, quantity, notes: _notesController.text); _notesController.clear(); - _stockUpdateMessage(response); + _stockUpdateMessage(result); - // TODO - Handle error cases refresh(); } @@ -111,20 +109,27 @@ class _StockItemDisplayState extends RefreshableState { ); } + void _stockUpdateMessage(bool result) { + + showSnackIcon( + refreshableKey, + result ? "Stock item updated" : "Stock item updated failed", + success: result + ); + } + void _removeStock() async { Navigator.of(context).pop(); double quantity = double.parse(_quantityController.text); _quantityController.clear(); - var response = await item.removeStock(quantity, notes: _notesController.text); - _notesController.clear(); + final bool result = await item.removeStock(context, quantity, notes: _notesController.text); - // TODO - Handle error cases + _stockUpdateMessage(result); refresh(); - // TODO - Display a snackbar here indicating the action was successful (or otherwise) } void _removeStockDialog() { @@ -166,19 +171,16 @@ class _StockItemDisplayState extends RefreshableState { double quantity = double.parse(_quantityController.text); _quantityController.clear(); - var response = await item.countStock(quantity, notes: _notesController.text); - _notesController.clear(); + final bool result = await item.countStock(context, quantity, notes: _notesController.text); - // TODO - Handle error cases, timeout, etc + _stockUpdateMessage(result); refresh(); - - // TODO - Display a snackbar here indicating the action was successful (or otherwise) } void _countStockDialog() async { - _quantityController.text = item.quantity.toString(); + _quantityController.text = item.quantityString; _notesController.clear(); showFormDialog(context, I18N.of(context).countStock, @@ -194,7 +196,7 @@ class _StockItemDisplayState extends RefreshableState { fields: [ QuantityField( label: I18N.of(context).countStock, - hint: "${item.quantity}", + hint: "${item.quantityString}", controller: _quantityController, ), TextFormField( @@ -233,7 +235,7 @@ class _StockItemDisplayState extends RefreshableState { InvenTreeStockLocation selectedLocation; - _quantityController.text = "${item.quantity}"; + _quantityController.text = "${item.quantityString}"; showFormDialog(context, I18N.of(context).transferStock, key: _moveStockKey, @@ -385,7 +387,7 @@ class _StockItemDisplayState extends RefreshableState { ListTile( title: Text(I18N.of(context).quantity), leading: FaIcon(FontAwesomeIcons.cubes), - trailing: Text("${item.quantity}"), + trailing: Text("${item.quantityString}"), ) ); }