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

Allow user to manually remove (delete) a StockItem

This commit is contained in:
Oliver Walters 2022-03-26 18:33:02 +11:00
parent 6c3b83c05b
commit ea724fcf5f
4 changed files with 101 additions and 7 deletions

View File

@ -918,7 +918,7 @@ class InvenTreeAPI {
/* /*
* Complete an API request, and return an APIResponse object * Complete an API request, and return an APIResponse object
*/ */
Future<APIResponse> completeRequest(HttpClientRequest request, {String? data, int? statusCode}) async { Future<APIResponse> completeRequest(HttpClientRequest request, {String? data, int? statusCode, bool ignoreResponse = false}) async {
if (data != null && data.isNotEmpty) { if (data != null && data.isNotEmpty) {
@ -954,8 +954,13 @@ class InvenTreeAPI {
} }
); );
} else {
if (ignoreResponse) {
response.data = {};
} else { } else {
response.data = await responseToJson(_response) ?? {}; response.data = await responseToJson(_response) ?? {};
}
if (statusCode != null) { if (statusCode != null) {
@ -1042,6 +1047,31 @@ class InvenTreeAPI {
return completeRequest(request); return completeRequest(request);
} }
/*
* Perform a HTTP DELETE request
*/
Future<APIResponse> delete(String url) async {
HttpClientRequest? request = await apiRequest(
url,
"DELETE",
);
if (request == null) {
// Return an "invalid" APIResponse object
return APIResponse(
url: url,
method: "DELETE",
error: "HttpClientRequest is null",
);
}
return completeRequest(
request,
ignoreResponse: true,
);
}
// Return a list of request headers // Return a list of request headers
Map<String, String> defaultHeaders() { Map<String, String> defaultHeaders() {
Map<String, String> headers = {}; Map<String, String> headers = {};

View File

@ -222,6 +222,38 @@ class InvenTreeModel {
return {}; return {};
} }
/// Delete the instance on the remote server
/// Returns true if the operation was successful, else false
Future<bool> delete() async {
var response = await api.delete(url);
if (!response.isValid() || response.data == null || (response.data is! Map)) {
if (response.statusCode > 0) {
await sentryReportMessage(
"InvenTreeModel.delete() returned invalid response",
context: {
"url": url,
"statusCode": response.statusCode.toString(),
"data": response.data?.toString() ?? "null",
"error": response.error,
"errorDetail": response.errorDetail,
}
);
}
showServerError(
L10().serverError,
L10().errorDelete,
);
return false;
}
// Status code should be 204 for "record deleted"
return response.statusCode == 204;
}
/* /*
* Reload this object, by requesting data from the server * Reload this object, by requesting data from the server
*/ */
@ -242,7 +274,7 @@ class InvenTreeModel {
"valid": response.isValid().toString(), "valid": response.isValid().toString(),
"error": response.error, "error": response.error,
"errorDetail": response.errorDetail, "errorDetail": response.errorDetail,
} },
); );
} }
@ -466,8 +498,6 @@ class InvenTreeModel {
// Provide a listing of objects at the endpoint // Provide a listing of objects at the endpoint
// TODO - Static function which returns a list of objects (of this class) // TODO - Static function which returns a list of objects (of this class)
// TODO - Define a "delete" function
// TODO - Define a "save" / "update" function // TODO - Define a "save" / "update" function
// Override this function for each sub-class // Override this function for each sub-class

View File

@ -8,7 +8,7 @@ import "package:font_awesome_flutter/font_awesome_flutter.dart";
import "package:inventree/l10.dart"; import "package:inventree/l10.dart";
import "package:one_context/one_context.dart"; import "package:one_context/one_context.dart";
Future<void> confirmationDialog(String title, String text, {String? acceptText, String? rejectText, Function? onAccept, Function? onReject}) async { Future<void> confirmationDialog(String title, String text, {IconData icon = FontAwesomeIcons.questionCircle, String? acceptText, String? rejectText, Function? onAccept, Function? onReject}) async {
String _accept = acceptText ?? L10().ok; String _accept = acceptText ?? L10().ok;
String _reject = rejectText ?? L10().cancel; String _reject = rejectText ?? L10().cancel;
@ -18,7 +18,7 @@ Future<void> confirmationDialog(String title, String text, {String? acceptText,
return AlertDialog( return AlertDialog(
title: ListTile( title: ListTile(
title: Text(title), title: Text(title),
leading: FaIcon(FontAwesomeIcons.questionCircle), leading: FaIcon(icon),
), ),
content: Text(text), content: Text(text),
actions: [ actions: [

View File

@ -157,6 +157,27 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> {
}); });
} }
/// Delete the stock item from the database
Future<void> _deleteItem(BuildContext context) async {
confirmationDialog(
L10().stockItemDelete,
L10().stockItemDeleteConfirm,
icon: FontAwesomeIcons.trashAlt,
onAccept: () async {
final bool result = await item.delete();
if (result) {
Navigator.of(context).pop();
showSnackIcon(L10().stockItemDeleteSuccess, success: true);
} else {
showSnackIcon(L10().stockItemDeleteFailure, success: false);
}
},
);
}
/// Opens a popup dialog allowing user to select a label for printing /// Opens a popup dialog allowing user to select a label for printing
Future <void> _printLabel(BuildContext context) async { Future <void> _printLabel(BuildContext context) async {
@ -1003,6 +1024,19 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> {
); );
} }
// If the user has permission to delete this stock item
if (InvenTreeAPI().checkPermission("stock", "delete")) {
tiles.add(
ListTile(
title: Text("Delete Stock Item"),
leading: FaIcon(FontAwesomeIcons.trashAlt, color: COLOR_DANGER),
onTap: () {
_deleteItem(context);
},
)
);
}
return tiles; return tiles;
} }