mirror of
https://github.com/inventree/inventree-app.git
synced 2025-04-28 13:36:50 +00:00
commit
884a6850f6
@ -18,6 +18,7 @@ const String INV_SOUNDS_SERVER = "serverSounds";
|
||||
const String INV_PART_SUBCATEGORY = "partSubcategory";
|
||||
|
||||
const String INV_STOCK_SUBLOCATION = "stockSublocation";
|
||||
const String INV_STOCK_SHOW_HISTORY = "stockShowHistory";
|
||||
|
||||
const String INV_REPORT_ERRORS = "reportErrors";
|
||||
|
||||
|
@ -56,6 +56,67 @@ class InvenTreeStockItemTestResult extends InvenTreeModel {
|
||||
}
|
||||
|
||||
|
||||
class InvenTreeStockItemHistory extends InvenTreeModel {
|
||||
|
||||
InvenTreeStockItemHistory() : super();
|
||||
|
||||
InvenTreeStockItemHistory.fromJson(Map<String, dynamic> json) : super.fromJson(json);
|
||||
|
||||
@override
|
||||
InvenTreeModel createFromJson(Map<String, dynamic> json) {
|
||||
return InvenTreeStockItemHistory.fromJson(json);
|
||||
}
|
||||
|
||||
@override
|
||||
String get URL => "stock/track/";
|
||||
|
||||
@override
|
||||
Map<String, String> defaultListFilters() {
|
||||
|
||||
// By default, order by decreasing date
|
||||
return {
|
||||
"ordering": "-date",
|
||||
};
|
||||
}
|
||||
|
||||
DateTime? get date {
|
||||
if (jsondata.containsKey("date")) {
|
||||
return DateTime.tryParse((jsondata["date"] ?? "") as String);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
String get dateString {
|
||||
var d = date;
|
||||
|
||||
if (d == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return DateFormat("yyyy-MM-dd").format(d);
|
||||
}
|
||||
|
||||
String get label => (jsondata["label"] ?? "") as String;
|
||||
|
||||
String get quantityString {
|
||||
Map<String, dynamic> deltas = (jsondata["deltas"] ?? {}) as Map<String, dynamic>;
|
||||
|
||||
// Serial number takes priority here
|
||||
if (deltas.containsKey("serial")) {
|
||||
var serial = (deltas["serial"] ?? "") as String;
|
||||
return "# ${serial}";
|
||||
} else if (deltas.containsKey("quantity")) {
|
||||
double q = (deltas["quantity"] ?? 0) as double;
|
||||
|
||||
return simpleNumberString(q);
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class InvenTreeStockItem extends InvenTreeModel {
|
||||
|
||||
InvenTreeStockItem() : super();
|
||||
|
2
lib/l10n
2
lib/l10n
@ -1 +1 @@
|
||||
Subproject commit a66dab998bc92b3cceed70aaffc92ffa8b5da836
|
||||
Subproject commit 10ae8c64e0754206e21b06531186375e247c796d
|
@ -28,6 +28,7 @@ class _InvenTreeAppSettingsState extends State<InvenTreeAppSettingsWidget> {
|
||||
|
||||
// Stock settings
|
||||
bool stockSublocation = false;
|
||||
bool stockShowHistory = false;
|
||||
|
||||
bool reportErrors = true;
|
||||
|
||||
@ -48,6 +49,7 @@ class _InvenTreeAppSettingsState extends State<InvenTreeAppSettingsWidget> {
|
||||
partSubcategory = await InvenTreeSettingsManager().getValue(INV_PART_SUBCATEGORY, true) as bool;
|
||||
|
||||
stockSublocation = await InvenTreeSettingsManager().getValue(INV_STOCK_SUBLOCATION, true) as bool;
|
||||
stockShowHistory = await InvenTreeSettingsManager().getValue(INV_STOCK_SHOW_HISTORY, false) as bool;
|
||||
|
||||
reportErrors = await InvenTreeSettingsManager().getValue(INV_REPORT_ERRORS, true) as bool;
|
||||
|
||||
@ -109,6 +111,20 @@ class _InvenTreeAppSettingsState extends State<InvenTreeAppSettingsWidget> {
|
||||
},
|
||||
),
|
||||
),
|
||||
ListTile(
|
||||
title: Text(L10().stockItemHistory),
|
||||
subtitle: Text(L10().stockItemHistoryDetail),
|
||||
leading: FaIcon(FontAwesomeIcons.history),
|
||||
trailing: Switch(
|
||||
value: stockShowHistory,
|
||||
onChanged: (bool value) {
|
||||
InvenTreeSettingsManager().setValue(INV_STOCK_SHOW_HISTORY, value);
|
||||
setState(() {
|
||||
stockShowHistory = value;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
/* Sound Settings */
|
||||
Divider(height: 3),
|
||||
ListTile(
|
||||
|
@ -16,12 +16,14 @@ import "package:inventree/widget/part_detail.dart";
|
||||
import "package:inventree/widget/progress.dart";
|
||||
import "package:inventree/widget/refreshable_state.dart";
|
||||
import "package:inventree/widget/snacks.dart";
|
||||
import "package:inventree/widget/stock_item_history.dart";
|
||||
import "package:inventree/widget/stock_item_test_results.dart";
|
||||
import "package:inventree/widget/stock_notes.dart";
|
||||
import "package:inventree/l10.dart";
|
||||
import "package:inventree/helpers.dart";
|
||||
import "package:inventree/api.dart";
|
||||
import "package:inventree/api_form.dart";
|
||||
import "package:inventree/app_settings.dart";
|
||||
|
||||
|
||||
class StockDetailWidget extends StatefulWidget {
|
||||
@ -50,6 +52,8 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> {
|
||||
final _countStockKey = GlobalKey<FormState>();
|
||||
final _moveStockKey = GlobalKey<FormState>();
|
||||
|
||||
bool stockShowHistory = false;
|
||||
|
||||
@override
|
||||
List<Widget> getAppBarActions(BuildContext context) {
|
||||
|
||||
@ -105,6 +109,8 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> {
|
||||
|
||||
final bool result = await item.reload();
|
||||
|
||||
stockShowHistory = await InvenTreeSettingsManager().getValue(INV_STOCK_SHOW_HISTORY, false) as bool;
|
||||
|
||||
// Could not load this stock item for some reason
|
||||
// Perhaps it has been depleted?
|
||||
if (!result || item.pk == -1) {
|
||||
@ -861,24 +867,24 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> {
|
||||
|
||||
// TODO - Is this stock item linked to a PurchaseOrder?
|
||||
|
||||
// TODO - Re-enable stock item history display
|
||||
/*
|
||||
if (item.trackingItemCount > 0) {
|
||||
if (stockShowHistory && item.trackingItemCount > 0) {
|
||||
tiles.add(
|
||||
ListTile(
|
||||
title: Text(L10().history),
|
||||
leading: FaIcon(FontAwesomeIcons.history),
|
||||
leading: FaIcon(FontAwesomeIcons.history, color: COLOR_CLICK),
|
||||
trailing: Text("${item.trackingItemCount}"),
|
||||
onTap: () {
|
||||
// TODO: Load tracking history
|
||||
|
||||
// TODO: Push tracking history page to the route
|
||||
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => StockItemHistoryWidget(item))
|
||||
).then((ctx) {
|
||||
refresh(context);
|
||||
});
|
||||
},
|
||||
)
|
||||
);
|
||||
}
|
||||
*/
|
||||
|
||||
// Notes field
|
||||
tiles.add(
|
||||
|
78
lib/widget/stock_item_history.dart
Normal file
78
lib/widget/stock_item_history.dart
Normal file
@ -0,0 +1,78 @@
|
||||
|
||||
|
||||
import "package:flutter/cupertino.dart";
|
||||
import "package:flutter/material.dart";
|
||||
|
||||
import "package:inventree/widget/refreshable_state.dart";
|
||||
import "package:inventree/l10.dart";
|
||||
import "package:inventree/inventree/stock.dart";
|
||||
import "package:inventree/inventree/model.dart";
|
||||
|
||||
|
||||
class StockItemHistoryWidget extends StatefulWidget {
|
||||
|
||||
const StockItemHistoryWidget(this.item, {Key? key}) : super(key: key);
|
||||
|
||||
final InvenTreeStockItem item;
|
||||
|
||||
@override
|
||||
_StockItemHistoryDisplayState createState() => _StockItemHistoryDisplayState(item);
|
||||
}
|
||||
|
||||
|
||||
class _StockItemHistoryDisplayState extends RefreshableState<StockItemHistoryWidget> {
|
||||
|
||||
_StockItemHistoryDisplayState(this.item);
|
||||
|
||||
final InvenTreeStockItem item;
|
||||
|
||||
@override
|
||||
String getAppBarTitle(BuildContext context) => L10().stockItemHistory;
|
||||
|
||||
List<InvenTreeStockItemHistory> history = [];
|
||||
|
||||
@override
|
||||
Future<void> request(BuildContext refresh) async {
|
||||
|
||||
history.clear();
|
||||
|
||||
InvenTreeStockItemHistory().list(filters: {"item": "${item.pk}"}).then((List<InvenTreeModel> results) {
|
||||
for (var result in results) {
|
||||
if (result is InvenTreeStockItemHistory) {
|
||||
history.add(result);
|
||||
}
|
||||
}
|
||||
|
||||
// Refresh
|
||||
setState(() {
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget getBody(BuildContext context) {
|
||||
return ListView(
|
||||
children: ListTile.divideTiles(
|
||||
context: context,
|
||||
tiles: historyList(),
|
||||
).toList()
|
||||
);
|
||||
}
|
||||
|
||||
List<Widget> historyList() {
|
||||
List<Widget> tiles = [];
|
||||
|
||||
for (var entry in history) {
|
||||
tiles.add(
|
||||
ListTile(
|
||||
leading: Text(entry.dateString),
|
||||
trailing: entry.quantityString.isNotEmpty ? Text(entry.quantityString) : null,
|
||||
title: Text(entry.label),
|
||||
subtitle: entry.notes.isNotEmpty ? Text(entry.notes) : null,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return tiles;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user