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:
parent
c8c056f96d
commit
3757010599
@ -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
@ -1 +1 @@
|
|||||||
Subproject commit 249e4964a08b79e53df7e1ea18b051de0d307905
|
Subproject commit ed3bd59b15b2c69b9a21649a0e0507efd811c1a1
|
@ -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}"),
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user