2
0
mirror of https://github.com/inventree/inventree-app.git synced 2025-05-04 08:18:54 +00:00

Refactor stock adjustment actions

- Handle timeout
- Handle error
This commit is contained in:
Oliver Walters 2021-02-10 23:54:00 +11:00
parent c8c056f96d
commit 3757010599
3 changed files with 81 additions and 48 deletions

View File

@ -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 false;
}
// Cannot handle negative stock
if (q < 0) {
return false;
}
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; return null;
}
// Cannot count negative stock
if (quan < 0) {
return null;
}
return api.post("/stock/count/", body: {
"item": {
"pk": "${pk}",
"quantity": "${quan}",
},
"notes": notes ?? '',
}); });
if (response == null) return false;
if (response.statusCode != 200) {
showStatusCodeError(context, response.statusCode);
return false;
} }
Future<http.Response> addStock(double quan, {String notes}) async { // Stock adjustment succeeded!
return true;
if (isSerialized() || quan <= 0) return null;
return api.post("/stock/add/", body: {
"item": {
"pk": "${pk}",
"quantity": "${quan}",
},
"notes": notes ?? '',
});
} }
Future<http.Response> removeStock(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/remove/", body: { return result;
"item": { }
"pk": "${pk}",
"quantity": "${quan}", Future<bool> addStock(BuildContext context, double q, {String notes}) async {
},
"notes": notes ?? '', final bool result = await adjustStock(context, "/stock/add/", q, notes: notes);
});
return result;
}
Future<bool> removeStock(BuildContext context, double q, {String notes}) async {
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 {

@ -1 +1 @@
Subproject commit 249e4964a08b79e53df7e1ea18b051de0d307905 Subproject commit ed3bd59b15b2c69b9a21649a0e0507efd811c1a1

View File

@ -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}"),
) )
); );
} }