mirror of
https://github.com/inventree/inventree-app.git
synced 2025-05-13 20:43:11 +00:00
Merge pull request #90 from inventree/stock-item-delete
Stock item delete
This commit is contained in:
commit
b8a5b0bd9c
@ -63,3 +63,7 @@ linter:
|
|||||||
always_specify_types: false
|
always_specify_types: false
|
||||||
|
|
||||||
avoid_unnecessary_containers: false
|
avoid_unnecessary_containers: false
|
||||||
|
|
||||||
|
require_trailing_commas: false
|
||||||
|
|
||||||
|
eol_at_end_of_file: false
|
@ -5,6 +5,7 @@
|
|||||||
---
|
---
|
||||||
|
|
||||||
- Enables printing of stock item labels
|
- Enables printing of stock item labels
|
||||||
|
- Allow users to manually delete stock items
|
||||||
|
|
||||||
### 0.5.6 - January 2022
|
### 0.5.6 - January 2022
|
||||||
---
|
---
|
||||||
|
34
lib/api.dart
34
lib/api.dart
@ -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) {
|
||||||
|
|
||||||
@ -955,7 +955,12 @@ class InvenTreeAPI {
|
|||||||
);
|
);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
response.data = await responseToJson(_response) ?? {};
|
|
||||||
|
if (ignoreResponse) {
|
||||||
|
response.data = {};
|
||||||
|
} else {
|
||||||
|
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 = {};
|
||||||
|
@ -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
|
||||||
|
@ -66,7 +66,7 @@ class _CategoryDisplayState extends RefreshableState<CategoryDisplayWidget> {
|
|||||||
context,
|
context,
|
||||||
L10().editCategory,
|
L10().editCategory,
|
||||||
onSuccess: (data) async {
|
onSuccess: (data) async {
|
||||||
refresh();
|
refresh(context);
|
||||||
showSnackIcon(L10().categoryUpdated, success: true);
|
showSnackIcon(L10().categoryUpdated, success: true);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -79,17 +79,21 @@ class _CategoryDisplayState extends RefreshableState<CategoryDisplayWidget> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> onBuild(BuildContext context) async {
|
Future<void> onBuild(BuildContext context) async {
|
||||||
refresh();
|
refresh(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> request() async {
|
Future<void> request(BuildContext context) async {
|
||||||
|
|
||||||
int pk = category?.pk ?? -1;
|
int pk = category?.pk ?? -1;
|
||||||
|
|
||||||
// Update the category
|
// Update the category
|
||||||
if (category != null) {
|
if (category != null) {
|
||||||
await category!.reload();
|
final bool result = await category?.reload() ?? false;
|
||||||
|
|
||||||
|
if (!result) {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Request a list of sub-categories under this one
|
// Request a list of sub-categories under this one
|
||||||
@ -234,7 +238,7 @@ class _CategoryDisplayState extends RefreshableState<CategoryDisplayWidget> {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
refresh();
|
refresh(context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -64,7 +64,7 @@ class _CompanyDetailState extends RefreshableState<CompanyDetailWidget> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> request() async {
|
Future<void> request(BuildContext context) async {
|
||||||
await company.reload();
|
await company.reload();
|
||||||
|
|
||||||
if (company.isSupplier) {
|
if (company.isSupplier) {
|
||||||
@ -78,7 +78,7 @@ class _CompanyDetailState extends RefreshableState<CompanyDetailWidget> {
|
|||||||
context,
|
context,
|
||||||
L10().companyEdit,
|
L10().companyEdit,
|
||||||
onSuccess: (data) async {
|
onSuccess: (data) async {
|
||||||
refresh();
|
refresh(context);
|
||||||
showSnackIcon(L10().companyUpdated, success: true);
|
showSnackIcon(L10().companyUpdated, success: true);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -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: [
|
||||||
|
@ -88,7 +88,7 @@ class _LocationDisplayState extends RefreshableState<LocationDisplayWidget> {
|
|||||||
context,
|
context,
|
||||||
L10().editLocation,
|
L10().editLocation,
|
||||||
onSuccess: (data) async {
|
onSuccess: (data) async {
|
||||||
refresh();
|
refresh(context);
|
||||||
showSnackIcon(L10().locationUpdated, success: true);
|
showSnackIcon(L10().locationUpdated, success: true);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -109,17 +109,21 @@ class _LocationDisplayState extends RefreshableState<LocationDisplayWidget> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> onBuild(BuildContext context) async {
|
Future<void> onBuild(BuildContext context) async {
|
||||||
refresh();
|
refresh(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> request() async {
|
Future<void> request(BuildContext context) async {
|
||||||
|
|
||||||
int pk = location?.pk ?? -1;
|
int pk = location?.pk ?? -1;
|
||||||
|
|
||||||
// Reload location information
|
// Reload location information
|
||||||
if (location != null) {
|
if (location != null) {
|
||||||
await location?.reload();
|
final bool result = await location?.reload() ?? false;
|
||||||
|
|
||||||
|
if (!result) {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Request a list of sub-locations under this one
|
// Request a list of sub-locations under this one
|
||||||
@ -385,8 +389,8 @@ List<Widget> detailTiles() {
|
|||||||
MaterialPageRoute(builder: (context) =>
|
MaterialPageRoute(builder: (context) =>
|
||||||
InvenTreeQRView(
|
InvenTreeQRView(
|
||||||
StockLocationScanInItemsHandler(_loc)))
|
StockLocationScanInItemsHandler(_loc)))
|
||||||
).then((context) {
|
).then((value) {
|
||||||
refresh();
|
refresh(context);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -72,11 +72,11 @@ class _PartAttachmentDisplayState extends RefreshableState<PartAttachmentsWidget
|
|||||||
showSnackIcon(L10().uploadFailed, success: false);
|
showSnackIcon(L10().uploadFailed, success: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
refresh();
|
refresh(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> request() async {
|
Future<void> request(BuildContext context) async {
|
||||||
|
|
||||||
await InvenTreePartAttachment().list(
|
await InvenTreePartAttachment().list(
|
||||||
filters: {
|
filters: {
|
||||||
|
@ -77,7 +77,7 @@ class _PartDisplayState extends RefreshableState<PartDetailWidget> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> onBuild(BuildContext context) async {
|
Future<void> onBuild(BuildContext context) async {
|
||||||
refresh();
|
refresh(context);
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
|
|
||||||
@ -85,8 +85,15 @@ class _PartDisplayState extends RefreshableState<PartDetailWidget> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> request() async {
|
Future<void> request(BuildContext context) async {
|
||||||
await part.reload();
|
|
||||||
|
final bool result = await part.reload();
|
||||||
|
|
||||||
|
if (!result || part.pk == -1) {
|
||||||
|
// Part could not be loaded, for some reason
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
}
|
||||||
|
|
||||||
await part.getTestTemplates();
|
await part.getTestTemplates();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,7 +101,7 @@ class _PartDisplayState extends RefreshableState<PartDetailWidget> {
|
|||||||
|
|
||||||
if (InvenTreeAPI().checkPermission("part", "view")) {
|
if (InvenTreeAPI().checkPermission("part", "view")) {
|
||||||
await part.update(values: {"starred": "${!part.starred}"});
|
await part.update(values: {"starred": "${!part.starred}"});
|
||||||
refresh();
|
refresh(context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,7 +111,7 @@ class _PartDisplayState extends RefreshableState<PartDetailWidget> {
|
|||||||
context,
|
context,
|
||||||
L10().editPart,
|
L10().editPart,
|
||||||
onSuccess: (data) async {
|
onSuccess: (data) async {
|
||||||
refresh();
|
refresh(context);
|
||||||
showSnackIcon(L10().partEdited, success: true);
|
showSnackIcon(L10().partEdited, success: true);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -130,7 +137,7 @@ class _PartDisplayState extends RefreshableState<PartDetailWidget> {
|
|||||||
builder: (context) => PartImageWidget(part)
|
builder: (context) => PartImageWidget(part)
|
||||||
)
|
)
|
||||||
).then((value) {
|
).then((value) {
|
||||||
refresh();
|
refresh(context);
|
||||||
});
|
});
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
|
@ -32,7 +32,7 @@ class _PartImageState extends RefreshableState<PartImageWidget> {
|
|||||||
final InvenTreePart part;
|
final InvenTreePart part;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> request() async {
|
Future<void> request(BuildContext context) async {
|
||||||
await part.reload();
|
await part.reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,7 +60,7 @@ class _PartImageState extends RefreshableState<PartImageWidget> {
|
|||||||
showSnackIcon(L10().uploadFailed, success: false);
|
showSnackIcon(L10().uploadFailed, success: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
refresh();
|
refresh(context);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ class _PartNotesState extends RefreshableState<PartNotesWidget> {
|
|||||||
final InvenTreePart part;
|
final InvenTreePart part;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> request() async {
|
Future<void> request(BuildContext context) async {
|
||||||
await part.reload();
|
await part.reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,7 +53,7 @@ class _PartNotesState extends RefreshableState<PartNotesWidget> {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
onSuccess: (data) async {
|
onSuccess: (data) async {
|
||||||
refresh();
|
refresh(context);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ class _PartSupplierState extends RefreshableState<PartSupplierWidget> {
|
|||||||
List<InvenTreeSupplierPart> _supplierParts = [];
|
List<InvenTreeSupplierPart> _supplierParts = [];
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> request() async {
|
Future<void> request(BuildContext context) async {
|
||||||
// TODO - Request list of suppliers for the part
|
// TODO - Request list of suppliers for the part
|
||||||
await part.reload();
|
await part.reload();
|
||||||
_supplierParts = await part.getSupplierParts();
|
_supplierParts = await part.getSupplierParts();
|
||||||
|
@ -61,7 +61,7 @@ class _PurchaseOrderDetailState extends RefreshableState<PurchaseOrderDetailWidg
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> request() async {
|
Future<void> request(BuildContext context) async {
|
||||||
await order.reload();
|
await order.reload();
|
||||||
|
|
||||||
lines = await order.getLineItems();
|
lines = await order.getLineItems();
|
||||||
@ -82,7 +82,7 @@ class _PurchaseOrderDetailState extends RefreshableState<PurchaseOrderDetailWidg
|
|||||||
context,
|
context,
|
||||||
L10().purchaseOrderEdit,
|
L10().purchaseOrderEdit,
|
||||||
onSuccess: (data) async {
|
onSuccess: (data) async {
|
||||||
refresh();
|
refresh(context);
|
||||||
showSnackIcon(L10().purchaseOrderUpdated, success: true);
|
showSnackIcon(L10().purchaseOrderUpdated, success: true);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -218,7 +218,7 @@ class _PurchaseOrderDetailState extends RefreshableState<PurchaseOrderDetailWidg
|
|||||||
icon: FontAwesomeIcons.signInAlt,
|
icon: FontAwesomeIcons.signInAlt,
|
||||||
onSuccess: (data) async {
|
onSuccess: (data) async {
|
||||||
showSnackIcon(L10().receivedItem, success: true);
|
showSnackIcon(L10().receivedItem, success: true);
|
||||||
refresh();
|
refresh(context);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -41,21 +41,21 @@ abstract class RefreshableState<T extends StatefulWidget> extends State<T> {
|
|||||||
|
|
||||||
// Function called after the widget is first build
|
// Function called after the widget is first build
|
||||||
Future<void> onBuild(BuildContext context) async {
|
Future<void> onBuild(BuildContext context) async {
|
||||||
refresh();
|
refresh(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function to request data for this page
|
// Function to request data for this page
|
||||||
Future<void> request() async {
|
Future<void> request(BuildContext context) async {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> refresh() async {
|
Future<void> refresh(BuildContext context) async {
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
loading = true;
|
loading = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
await request();
|
await request(context);
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
loading = false;
|
loading = false;
|
||||||
@ -100,7 +100,9 @@ abstract class RefreshableState<T extends StatefulWidget> extends State<T> {
|
|||||||
body: Builder(
|
body: Builder(
|
||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
return RefreshIndicator(
|
return RefreshIndicator(
|
||||||
onRefresh: refresh,
|
onRefresh: () async {
|
||||||
|
refresh(context);
|
||||||
|
},
|
||||||
child: getBody(context)
|
child: getBody(context)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ class _StarredPartState extends RefreshableState<StarredPartWidget> {
|
|||||||
String getAppBarTitle(BuildContext context) => L10().partsStarred;
|
String getAppBarTitle(BuildContext context) => L10().partsStarred;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> request() async {
|
Future<void> request(BuildContext context) async {
|
||||||
|
|
||||||
final parts = await InvenTreePart().list(filters: {"starred": "true"});
|
final parts = await InvenTreePart().list(filters: {"starred": "true"});
|
||||||
|
|
||||||
|
@ -96,13 +96,20 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> {
|
|||||||
|
|
||||||
// Load part data if not already loaded
|
// Load part data if not already loaded
|
||||||
if (part == null) {
|
if (part == null) {
|
||||||
refresh();
|
refresh(context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> request() async {
|
Future<void> request(BuildContext context) async {
|
||||||
await item.reload();
|
|
||||||
|
final bool result = await item.reload();
|
||||||
|
|
||||||
|
// Could not load this stock item for some reason
|
||||||
|
// Perhaps it has been depleted?
|
||||||
|
if (!result || item.pk == -1) {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
}
|
||||||
|
|
||||||
// Request part information
|
// Request part information
|
||||||
part = await InvenTreePart().get(item.partId) as InvenTreePart?;
|
part = await InvenTreePart().get(item.partId) as InvenTreePart?;
|
||||||
@ -149,6 +156,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 {
|
||||||
|
|
||||||
@ -244,7 +272,7 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> {
|
|||||||
L10().editItem,
|
L10().editItem,
|
||||||
fields: fields,
|
fields: fields,
|
||||||
onSuccess: (data) async {
|
onSuccess: (data) async {
|
||||||
refresh();
|
refresh(context);
|
||||||
showSnackIcon(L10().stockItemUpdated, success: true);
|
showSnackIcon(L10().stockItemUpdated, success: true);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -261,7 +289,7 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> {
|
|||||||
|
|
||||||
_stockUpdateMessage(result);
|
_stockUpdateMessage(result);
|
||||||
|
|
||||||
refresh();
|
refresh(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future <void> _addStockDialog() async {
|
Future <void> _addStockDialog() async {
|
||||||
@ -293,7 +321,7 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> {
|
|||||||
icon: FontAwesomeIcons.plusCircle,
|
icon: FontAwesomeIcons.plusCircle,
|
||||||
onSuccess: (data) async {
|
onSuccess: (data) async {
|
||||||
_stockUpdateMessage(true);
|
_stockUpdateMessage(true);
|
||||||
refresh();
|
refresh(context);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -340,7 +368,7 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> {
|
|||||||
|
|
||||||
_stockUpdateMessage(result);
|
_stockUpdateMessage(result);
|
||||||
|
|
||||||
refresh();
|
refresh(context);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -372,7 +400,7 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> {
|
|||||||
icon: FontAwesomeIcons.minusCircle,
|
icon: FontAwesomeIcons.minusCircle,
|
||||||
onSuccess: (data) async {
|
onSuccess: (data) async {
|
||||||
_stockUpdateMessage(true);
|
_stockUpdateMessage(true);
|
||||||
refresh();
|
refresh(context);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -413,7 +441,7 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> {
|
|||||||
|
|
||||||
_stockUpdateMessage(result);
|
_stockUpdateMessage(result);
|
||||||
|
|
||||||
refresh();
|
refresh(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future <void> _countStockDialog() async {
|
Future <void> _countStockDialog() async {
|
||||||
@ -445,7 +473,7 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> {
|
|||||||
icon: FontAwesomeIcons.clipboardCheck,
|
icon: FontAwesomeIcons.clipboardCheck,
|
||||||
onSuccess: (data) async {
|
onSuccess: (data) async {
|
||||||
_stockUpdateMessage(true);
|
_stockUpdateMessage(true);
|
||||||
refresh();
|
refresh(context);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -494,7 +522,7 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
refresh();
|
refresh(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -509,7 +537,7 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> {
|
|||||||
|
|
||||||
var result = await item.transferStock(context, locationId, quantity: quantity, notes: notes);
|
var result = await item.transferStock(context, locationId, quantity: quantity, notes: notes);
|
||||||
|
|
||||||
refresh();
|
refresh(context);
|
||||||
|
|
||||||
if (result) {
|
if (result) {
|
||||||
showSnackIcon(L10().stockItemTransferred, success: true);
|
showSnackIcon(L10().stockItemTransferred, success: true);
|
||||||
@ -549,7 +577,7 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> {
|
|||||||
icon: FontAwesomeIcons.dolly,
|
icon: FontAwesomeIcons.dolly,
|
||||||
onSuccess: (data) async {
|
onSuccess: (data) async {
|
||||||
_stockUpdateMessage(true);
|
_stockUpdateMessage(true);
|
||||||
refresh();
|
refresh(context);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -813,8 +841,8 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> {
|
|||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (context) => StockItemTestResultsWidget(item))
|
builder: (context) => StockItemTestResultsWidget(item))
|
||||||
).then((context) {
|
).then((ctx) {
|
||||||
refresh();
|
refresh(context);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -940,8 +968,8 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> {
|
|||||||
Navigator.push(
|
Navigator.push(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(builder: (context) => InvenTreeQRView(StockItemScanIntoLocationHandler(item)))
|
MaterialPageRoute(builder: (context) => InvenTreeQRView(StockItemScanIntoLocationHandler(item)))
|
||||||
).then((context) {
|
).then((ctx) {
|
||||||
refresh();
|
refresh(context);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -971,7 +999,7 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> {
|
|||||||
icon: Icons.qr_code,
|
icon: Icons.qr_code,
|
||||||
);
|
);
|
||||||
|
|
||||||
refresh();
|
refresh(context);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -1008,6 +1036,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ class _StockItemTestResultDisplayState extends RefreshableState<StockItemTestRes
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> request() async {
|
Future<void> request(BuildContext context) async {
|
||||||
await item.getTestTemplates();
|
await item.getTestTemplates();
|
||||||
await item.getTestResults();
|
await item.getTestResults();
|
||||||
}
|
}
|
||||||
@ -61,7 +61,7 @@ class _StockItemTestResultDisplayState extends RefreshableState<StockItemTestRes
|
|||||||
"test": "${name}",
|
"test": "${name}",
|
||||||
},
|
},
|
||||||
onSuccess: (data) {
|
onSuccess: (data) {
|
||||||
refresh();
|
refresh(context);
|
||||||
},
|
},
|
||||||
fileField: "attachment",
|
fileField: "attachment",
|
||||||
);
|
);
|
||||||
|
@ -31,7 +31,7 @@ class _StockNotesState extends RefreshableState<StockNotesWidget> {
|
|||||||
String getAppBarTitle(BuildContext context) => L10().stockItemNotes;
|
String getAppBarTitle(BuildContext context) => L10().stockItemNotes;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> request() async {
|
Future<void> request(BuildContext context) async {
|
||||||
await item.reload();
|
await item.reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,7 +54,7 @@ class _StockNotesState extends RefreshableState<StockNotesWidget> {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
onSuccess: (data) async {
|
onSuccess: (data) async {
|
||||||
refresh();
|
refresh(context);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user