2
0
mirror of https://github.com/inventree/inventree-app.git synced 2025-04-28 13:36:50 +00:00

Add support for "modern" stock actions via the API

- In the future, will have to deprecate support for the old ways
- Probably v0.6.x?
This commit is contained in:
Oliver 2021-10-05 22:45:47 +11:00
parent 91ec55967d
commit ba41ebde73
3 changed files with 165 additions and 11 deletions

View File

@ -225,6 +225,8 @@ class InvenTreeAPI {
// API version of the connected server // API version of the connected server
int _apiVersion = 1; int _apiVersion = 1;
int get apiVersion => _apiVersion;
// Getter for server version information // Getter for server version information
String get version => _version; String get version => _version;
@ -244,10 +246,14 @@ class InvenTreeAPI {
// Ensure we only ever create a single instance of the API class // Ensure we only ever create a single instance of the API class
static final InvenTreeAPI _api = InvenTreeAPI._internal(); static final InvenTreeAPI _api = InvenTreeAPI._internal();
bool supportPoReceive() {
// API endpoint for receiving purchase order line items was introduced in v12 // API endpoint for receiving purchase order line items was introduced in v12
return _apiVersion >= 12; bool supportPoReceive() {
return apiVersion >= 12;
}
// "Modern" API transactions were implemented in API v14
bool supportModernStockTransactions() {
return apiVersion >= 14;
} }
/* /*

View File

@ -115,6 +115,16 @@ class InvenTreeStockItem extends InvenTreeModel {
@override @override
String get URL => "stock/"; String get URL => "stock/";
// URLs for performing stock actions
static String transferStockUrl() => "stock/transfer/";
static String countStockUrl() => "stock/count/";
static String addStockUrl() => "stock/add/";
static String removeStockUrl() => "stock/remove/";
@override @override
String get WEB_URL => "stock/item/"; String get WEB_URL => "stock/item/";
@ -474,7 +484,7 @@ class InvenTreeStockItem extends InvenTreeModel {
return response.isValid(); return response.isValid();
} }
// TODO: Refactor this once the server supports API metadata for this action // TODO: Remove this function when we deprecate support for the old API
Future<bool> countStock(BuildContext context, double q, {String? notes}) async { Future<bool> countStock(BuildContext context, double q, {String? notes}) async {
final bool result = await adjustStock(context, "/stock/count/", q, notes: notes); final bool result = await adjustStock(context, "/stock/count/", q, notes: notes);
@ -482,7 +492,7 @@ class InvenTreeStockItem extends InvenTreeModel {
return result; return result;
} }
// TODO: Refactor this once the server supports API metadata for this action // TODO: Remove this function when we deprecate support for the old API
Future<bool> addStock(BuildContext context, double q, {String? notes}) async { Future<bool> addStock(BuildContext context, double q, {String? notes}) async {
final bool result = await adjustStock(context, "/stock/add/", q, notes: notes); final bool result = await adjustStock(context, "/stock/add/", q, notes: notes);
@ -490,7 +500,7 @@ class InvenTreeStockItem extends InvenTreeModel {
return result; return result;
} }
// TODO: Refactor this once the server supports API metadata for this action // TODO: Remove this function when we deprecate support for the old API
Future<bool> removeStock(BuildContext context, double q, {String? notes}) async { Future<bool> removeStock(BuildContext context, double q, {String? notes}) async {
final bool result = await adjustStock(context, "/stock/remove/", q, notes: notes); final bool result = await adjustStock(context, "/stock/remove/", q, notes: notes);
@ -498,7 +508,7 @@ class InvenTreeStockItem extends InvenTreeModel {
return result; return result;
} }
// TODO: Refactor this once the server supports API metadata for this action // TODO: Remove this function when we deprecate support for the old API
Future<bool> transferStock(int location, {double? quantity, String? notes}) async { Future<bool> transferStock(int location, {double? quantity, String? notes}) async {
if ((quantity == null) || (quantity < 0) || (quantity > this.quantity)) { if ((quantity == null) || (quantity < 0) || (quantity > this.quantity)) {
quantity = this.quantity; quantity = this.quantity;

View File

@ -1,3 +1,9 @@
import "package:flutter/cupertino.dart";
import "package:flutter/material.dart";
import "package:dropdown_search/dropdown_search.dart";
import "package:font_awesome_flutter/font_awesome_flutter.dart";
import "package:inventree/app_colors.dart"; import "package:inventree/app_colors.dart";
import "package:inventree/barcode.dart"; import "package:inventree/barcode.dart";
import "package:inventree/inventree/model.dart"; import "package:inventree/inventree/model.dart";
@ -12,15 +18,11 @@ import "package:inventree/widget/refreshable_state.dart";
import "package:inventree/widget/snacks.dart"; import "package:inventree/widget/snacks.dart";
import "package:inventree/widget/stock_item_test_results.dart"; import "package:inventree/widget/stock_item_test_results.dart";
import "package:inventree/widget/stock_notes.dart"; import "package:inventree/widget/stock_notes.dart";
import "package:flutter/cupertino.dart";
import "package:flutter/material.dart";
import "package:inventree/l10.dart"; import "package:inventree/l10.dart";
import "package:inventree/helpers.dart"; import "package:inventree/helpers.dart";
import "package:inventree/api.dart"; import "package:inventree/api.dart";
import "package:inventree/api_form.dart";
import "package:dropdown_search/dropdown_search.dart";
import "package:font_awesome_flutter/font_awesome_flutter.dart";
class StockDetailWidget extends StatefulWidget { class StockDetailWidget extends StatefulWidget {
@ -140,6 +142,39 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> {
Future <void> _addStockDialog() async { Future <void> _addStockDialog() async {
// TODO: In future, deprecate support for older API
if (InvenTreeAPI().supportModernStockTransactions()) {
Map<String, dynamic> fields = {
"pk": {
"parent": "items",
"nested": true,
"hidden": true,
"value": item.pk,
},
"quantity": {
"parent": "items",
"nested": true,
"value": 0,
},
"notes": {},
};
launchApiForm(
context,
L10().addStock,
InvenTreeStockItem.addStockUrl(),
fields,
method: "POST",
icon: FontAwesomeIcons.plusCircle,
onSuccess: (data) async {
refresh();
}
);
return;
}
_quantityController.clear(); _quantityController.clear();
_notesController.clear(); _notesController.clear();
@ -186,6 +221,38 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> {
void _removeStockDialog() { void _removeStockDialog() {
// TODO: In future, deprecate support for the older API
if (InvenTreeAPI().supportModernStockTransactions()) {
Map<String, dynamic> fields = {
"pk": {
"parent": "items",
"nested": true,
"hidden": true,
"value": item.pk,
},
"quantity": {
"parent": "items",
"nested": true,
"value": 0,
},
"notes": {},
};
launchApiForm(
context,
L10().addStock,
InvenTreeStockItem.removeStockUrl(),
fields,
method: "POST",
icon: FontAwesomeIcons.minusCircle,
onSuccess: (data) async {
refresh();
}
);
return;
}
_quantityController.clear(); _quantityController.clear();
_notesController.clear(); _notesController.clear();
@ -225,6 +292,39 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> {
Future <void> _countStockDialog() async { Future <void> _countStockDialog() async {
// TODO: In future, deprecate support for older API
if (InvenTreeAPI().supportModernStockTransactions()) {
Map<String, dynamic> fields = {
"pk": {
"parent": "items",
"nested": true,
"hidden": true,
"value": item.pk,
},
"quantity": {
"parent": "items",
"nested": true,
"value": item.quantity,
},
"notes": {},
};
launchApiForm(
context,
L10().addStock,
InvenTreeStockItem.countStockUrl(),
fields,
method: "POST",
icon: FontAwesomeIcons.plusCircle,
onSuccess: (data) async {
refresh();
}
);
return;
}
_quantityController.text = item.quantity.toString(); _quantityController.text = item.quantity.toString();
_notesController.clear(); _notesController.clear();
@ -271,6 +371,7 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> {
} }
// TODO: Delete this function once support for old API is deprecated
Future <void> _transferStock(int locationId) async { Future <void> _transferStock(int locationId) async {
double quantity = double.tryParse(_quantityController.text) ?? item.quantity; double quantity = double.tryParse(_quantityController.text) ?? item.quantity;
@ -288,8 +389,45 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> {
} }
} }
/*
* Launches an API Form to transfer this stock item to a new location
*/
Future <void> _transferStockDialog(BuildContext context) async { Future <void> _transferStockDialog(BuildContext context) async {
// TODO: In future, deprecate support for older API
if (InvenTreeAPI().supportModernStockTransactions()) {
Map<String, dynamic> fields = {
"pk": {
"parent": "items",
"nested": true,
"hidden": true,
"value": item.pk,
},
"quantity": {
"parent": "items",
"nested": true,
"value": item.quantity,
},
"location": {},
"notes": {},
};
launchApiForm(
context,
L10().transferStock,
InvenTreeStockItem.transferStockUrl(),
fields,
method: "POST",
icon: FontAwesomeIcons.dolly,
onSuccess: (data) async {
refresh();
}
);
return;
}
int? location_pk; int? location_pk;
_quantityController.text = "${item.quantity}"; _quantityController.text = "${item.quantity}";