mirror of
https://github.com/inventree/inventree-app.git
synced 2025-04-28 13:36:50 +00:00
Stock test actions (#345)
* Use FAB for stock item test result * Change long press to tap * Add setting to control display of stock tests results * Add question mark if no result recorded
This commit is contained in:
parent
49226a5fce
commit
383571707e
@ -4,6 +4,7 @@
|
|||||||
- Add support for Project Codes
|
- Add support for Project Codes
|
||||||
- Improve purchase order support
|
- Improve purchase order support
|
||||||
- Fix action button colors
|
- Fix action button colors
|
||||||
|
- Improvements for stock item test result display
|
||||||
- Added Norwegian translations
|
- Added Norwegian translations
|
||||||
- Fix serial number field when creating stock item
|
- Fix serial number field when creating stock item
|
||||||
|
|
||||||
|
@ -11,6 +11,9 @@ import "package:inventree/inventree/model.dart";
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class representing a test result for a single stock item
|
||||||
|
*/
|
||||||
class InvenTreeStockItemTestResult extends InvenTreeModel {
|
class InvenTreeStockItemTestResult extends InvenTreeModel {
|
||||||
|
|
||||||
InvenTreeStockItemTestResult() : super();
|
InvenTreeStockItemTestResult() : super();
|
||||||
|
@ -1208,6 +1208,9 @@
|
|||||||
"description": ""
|
"description": ""
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"testResultsDetail": "Display stock item test results",
|
||||||
|
"@testResultsDetail": {},
|
||||||
|
|
||||||
"testResultAdd": "Add Test Result",
|
"testResultAdd": "Add Test Result",
|
||||||
"@testResultAdd": {},
|
"@testResultAdd": {},
|
||||||
|
|
||||||
|
@ -24,6 +24,7 @@ const String INV_PART_SHOW_BOM = "partShowBom";
|
|||||||
|
|
||||||
// Stock settings
|
// Stock settings
|
||||||
const String INV_STOCK_SHOW_HISTORY = "stockShowHistory";
|
const String INV_STOCK_SHOW_HISTORY = "stockShowHistory";
|
||||||
|
const String INV_STOCK_SHOW_TESTS = "stockShowTests";
|
||||||
|
|
||||||
const String INV_REPORT_ERRORS = "reportErrors";
|
const String INV_REPORT_ERRORS = "reportErrors";
|
||||||
const String INV_STRICT_HTTPS = "strictHttps";
|
const String INV_STRICT_HTTPS = "strictHttps";
|
||||||
|
@ -18,6 +18,7 @@ class _InvenTreePartSettingsState extends State<InvenTreePartSettingsWidget> {
|
|||||||
bool partShowParameters = true;
|
bool partShowParameters = true;
|
||||||
bool partShowBom = true;
|
bool partShowBom = true;
|
||||||
bool stockShowHistory = false;
|
bool stockShowHistory = false;
|
||||||
|
bool stockShowTests = false;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@ -30,6 +31,7 @@ class _InvenTreePartSettingsState extends State<InvenTreePartSettingsWidget> {
|
|||||||
partShowParameters = await InvenTreeSettingsManager().getValue(INV_PART_SHOW_PARAMETERS, true) as bool;
|
partShowParameters = await InvenTreeSettingsManager().getValue(INV_PART_SHOW_PARAMETERS, true) as bool;
|
||||||
partShowBom = await InvenTreeSettingsManager().getValue(INV_PART_SHOW_BOM, true) as bool;
|
partShowBom = await InvenTreeSettingsManager().getValue(INV_PART_SHOW_BOM, true) as bool;
|
||||||
stockShowHistory = await InvenTreeSettingsManager().getValue(INV_STOCK_SHOW_HISTORY, false) as bool;
|
stockShowHistory = await InvenTreeSettingsManager().getValue(INV_STOCK_SHOW_HISTORY, false) as bool;
|
||||||
|
stockShowTests = await InvenTreeSettingsManager().getValue(INV_STOCK_SHOW_TESTS, true) as bool;
|
||||||
|
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
setState(() {
|
setState(() {
|
||||||
@ -86,6 +88,20 @@ class _InvenTreePartSettingsState extends State<InvenTreePartSettingsWidget> {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
ListTile(
|
||||||
|
title: Text(L10().testResults),
|
||||||
|
subtitle: Text(L10().testResultsDetail),
|
||||||
|
leading: FaIcon(FontAwesomeIcons.vial),
|
||||||
|
trailing: Switch(
|
||||||
|
value: stockShowTests,
|
||||||
|
onChanged: (bool value) {
|
||||||
|
InvenTreeSettingsManager().setValue(INV_STOCK_SHOW_TESTS, value);
|
||||||
|
setState(() {
|
||||||
|
stockShowTests = value;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -47,6 +47,7 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> {
|
|||||||
String getAppBarTitle() => L10().stockItem;
|
String getAppBarTitle() => L10().stockItem;
|
||||||
|
|
||||||
bool stockShowHistory = false;
|
bool stockShowHistory = false;
|
||||||
|
bool stockShowTests = true;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Widget> appBarActions(BuildContext context) {
|
List<Widget> appBarActions(BuildContext context) {
|
||||||
@ -214,6 +215,7 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> {
|
|||||||
await api.StockStatus.load();
|
await api.StockStatus.load();
|
||||||
|
|
||||||
stockShowHistory = await InvenTreeSettingsManager().getValue(INV_STOCK_SHOW_HISTORY, false) as bool;
|
stockShowHistory = await InvenTreeSettingsManager().getValue(INV_STOCK_SHOW_HISTORY, false) as bool;
|
||||||
|
stockShowTests = await InvenTreeSettingsManager().getValue(INV_STOCK_SHOW_TESTS, true) as bool;
|
||||||
|
|
||||||
final bool result = widget.item.pk > 0 && await widget.item.reload();
|
final bool result = widget.item.pk > 0 && await widget.item.reload();
|
||||||
|
|
||||||
@ -226,7 +228,10 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> {
|
|||||||
// Request part information
|
// Request part information
|
||||||
part = await InvenTreePart().get(widget.item.partId) as InvenTreePart?;
|
part = await InvenTreePart().get(widget.item.partId) as InvenTreePart?;
|
||||||
|
|
||||||
|
stockShowTests &= part?.isTrackable ?? false;
|
||||||
|
|
||||||
// Request test results (async)
|
// Request test results (async)
|
||||||
|
if (stockShowTests) {
|
||||||
widget.item.getTestResults().then((value) {
|
widget.item.getTestResults().then((value) {
|
||||||
|
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
@ -235,6 +240,7 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Request the number of attachments
|
// Request the number of attachments
|
||||||
InvenTreeStockItemAttachment().count(
|
InvenTreeStockItemAttachment().count(
|
||||||
@ -753,7 +759,7 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((widget.item.testResultCount > 0) || (part?.isTrackable ?? false)) {
|
if (stockShowTests || (widget.item.testResultCount > 0)) {
|
||||||
tiles.add(
|
tiles.add(
|
||||||
ListTile(
|
ListTile(
|
||||||
title: Text(L10().testResults),
|
title: Text(L10().testResults),
|
||||||
|
@ -1,15 +1,17 @@
|
|||||||
|
import "package:flutter/material.dart";
|
||||||
|
import "package:flutter_speed_dial/flutter_speed_dial.dart";
|
||||||
|
import "package:font_awesome_flutter/font_awesome_flutter.dart";
|
||||||
|
|
||||||
|
import "package:inventree/api.dart";
|
||||||
import "package:inventree/app_colors.dart";
|
import "package:inventree/app_colors.dart";
|
||||||
|
import "package:inventree/l10.dart";
|
||||||
|
|
||||||
import "package:inventree/inventree/part.dart";
|
import "package:inventree/inventree/part.dart";
|
||||||
import "package:inventree/inventree/stock.dart";
|
import "package:inventree/inventree/stock.dart";
|
||||||
import "package:inventree/inventree/model.dart";
|
import "package:inventree/inventree/model.dart";
|
||||||
import "package:inventree/api.dart";
|
|
||||||
import "package:inventree/widget/progress.dart";
|
import "package:inventree/widget/progress.dart";
|
||||||
|
|
||||||
import "package:inventree/l10.dart";
|
|
||||||
|
|
||||||
import "package:flutter/material.dart";
|
|
||||||
import "package:inventree/widget/refreshable_state.dart";
|
import "package:inventree/widget/refreshable_state.dart";
|
||||||
import "package:font_awesome_flutter/font_awesome_flutter.dart";
|
|
||||||
|
|
||||||
|
|
||||||
class StockItemTestResultsWidget extends StatefulWidget {
|
class StockItemTestResultsWidget extends StatefulWidget {
|
||||||
@ -31,15 +33,25 @@ class _StockItemTestResultDisplayState extends RefreshableState<StockItemTestRes
|
|||||||
String getAppBarTitle() => L10().testResults;
|
String getAppBarTitle() => L10().testResults;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Widget> appBarActions(BuildContext context) {
|
List<Widget> appBarActions(BuildContext context) => [];
|
||||||
return [
|
|
||||||
IconButton(
|
@override
|
||||||
icon: FaIcon(FontAwesomeIcons.circlePlus),
|
List<SpeedDialChild> actionButtons(BuildContext context) {
|
||||||
onPressed: () {
|
List<SpeedDialChild> actions = [];
|
||||||
|
|
||||||
|
if (InvenTreeStockItemTestResult().canCreate) {
|
||||||
|
actions.add(
|
||||||
|
SpeedDialChild(
|
||||||
|
child: FaIcon(FontAwesomeIcons.circlePlus),
|
||||||
|
label: L10().testResultAdd,
|
||||||
|
onTap: () {
|
||||||
addTestResult(context);
|
addTestResult(context);
|
||||||
}
|
}
|
||||||
),
|
)
|
||||||
];
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return actions;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -153,6 +165,7 @@ class _StockItemTestResultDisplayState extends RefreshableState<StockItemTestRes
|
|||||||
|
|
||||||
for (var item in results) {
|
for (var item in results) {
|
||||||
|
|
||||||
|
bool _hasResult = false;
|
||||||
bool _required = false;
|
bool _required = false;
|
||||||
String _test = "";
|
String _test = "";
|
||||||
bool _result = false;
|
bool _result = false;
|
||||||
@ -167,34 +180,37 @@ class _StockItemTestResultDisplayState extends RefreshableState<StockItemTestRes
|
|||||||
_result = item.passFailStatus();
|
_result = item.passFailStatus();
|
||||||
_test = item.testName;
|
_test = item.testName;
|
||||||
_required = item.required;
|
_required = item.required;
|
||||||
_value = item.latestResult()?.value ?? "";
|
_value = item.latestResult()?.value ?? L10().noResults;
|
||||||
_valueRequired = item.requiresValue;
|
_valueRequired = item.requiresValue;
|
||||||
_attachmentRequired = item.requiresAttachment;
|
_attachmentRequired = item.requiresAttachment;
|
||||||
_notes = item.latestResult()?.notes ?? "";
|
_notes = item.latestResult()?.notes ?? item.description;
|
||||||
|
_hasResult = item.latestResult() != null;
|
||||||
} else if (item is InvenTreeStockItemTestResult) {
|
} else if (item is InvenTreeStockItemTestResult) {
|
||||||
_result = item.result;
|
_result = item.result;
|
||||||
_test = item.testName;
|
_test = item.testName;
|
||||||
_required = false;
|
_required = false;
|
||||||
_value = item.value;
|
_value = item.value;
|
||||||
_notes = item.notes;
|
_notes = item.notes;
|
||||||
|
_hasResult = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_result == true) {
|
if (!_hasResult) {
|
||||||
_icon = FaIcon(FontAwesomeIcons.circleCheck,
|
_icon = FaIcon(FontAwesomeIcons.circleQuestion, color: Colors.blue);
|
||||||
color: COLOR_SUCCESS,
|
} else if (_result == true) {
|
||||||
);
|
_icon = FaIcon(FontAwesomeIcons.circleCheck, color: COLOR_SUCCESS);
|
||||||
} else if (_result == false) {
|
} else if (_result == false) {
|
||||||
_icon = FaIcon(FontAwesomeIcons.circleXmark,
|
_icon = FaIcon(FontAwesomeIcons.circleXmark, color: COLOR_DANGER);
|
||||||
color: COLOR_DANGER,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tiles.add(ListTile(
|
tiles.add(ListTile(
|
||||||
title: Text(_test, style: TextStyle(fontWeight: _required ? FontWeight.bold : FontWeight.normal)),
|
title: Text(_test, style: TextStyle(
|
||||||
|
fontWeight: _required ? FontWeight.bold : FontWeight.normal,
|
||||||
|
fontStyle: _hasResult ? FontStyle.normal : FontStyle.italic
|
||||||
|
)),
|
||||||
subtitle: Text(_notes),
|
subtitle: Text(_notes),
|
||||||
trailing: Text(_value),
|
trailing: Text(_value),
|
||||||
leading: _icon,
|
leading: _icon,
|
||||||
onLongPress: () {
|
onTap: () {
|
||||||
addTestResult(
|
addTestResult(
|
||||||
context,
|
context,
|
||||||
name: _test,
|
name: _test,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user