Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stock expiry #590

Merged
merged 5 commits into from
Dec 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions assets/release_notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

- Fixed error message when printing a label to a remote machine
- Prevent notification sounds from pause media playback
- Display stock expiry information
- Updated translations

### 0.17.1 - December 2024
Expand Down
4 changes: 2 additions & 2 deletions lib/api.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1532,7 +1532,7 @@ class InvenTreeAPI {
// Return a boolean global setting value
Future<bool> getGlobalBooleanSetting(String key) async {
String value = await getGlobalSetting(key);
return value.toLowerCase() == "true";
return value.toLowerCase().trim() == "true";
}

Future<String> getUserSetting(String key) async {
Expand All @@ -1557,7 +1557,7 @@ class InvenTreeAPI {
// Return a boolean user setting value
Future<bool> getUserBooleanSetting(String key) async {
String value = await getUserSetting(key);
return value.toLowerCase() == "true";
return value.toLowerCase().trim() == "true";
}

/*
Expand Down
25 changes: 25 additions & 0 deletions lib/inventree/model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import "dart:io";

import "package:flutter_tabler_icons/flutter_tabler_icons.dart";
import "package:flutter/material.dart";
import "package:intl/intl.dart";
import "package:inventree/widget/snacks.dart";
import "package:url_launcher/url_launcher.dart";
import "package:path/path.dart" as path;
Expand Down Expand Up @@ -156,6 +157,30 @@ class InvenTreeModel {
return value.toString().toLowerCase() == "true";
}

// Helper function to get date value from json data
DateTime? getDate(String key, {DateTime? backup, String subKey = ""}) {
dynamic value = getValue(key, backup: backup, subKey: subKey);

if (value == null) {
return backup;
}

return DateTime.tryParse(value as String);
}

// Helper function to get date as a string
String getDateString(String key, {DateTime? backup, String subKey = ""}) {
DateTime? dt = getDate(key, backup: backup, subKey: subKey);

if (dt == null) {
return "";
}

final DateFormat fmt = DateFormat("yyyy-MM-dd");

return fmt.format(dt);
}

// Return the InvenTree web server URL for this object
String get webUrl {

Expand Down
63 changes: 12 additions & 51 deletions lib/inventree/stock.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import "dart:async";

import "package:intl/intl.dart";

import "package:inventree/api.dart";
import "package:inventree/helpers.dart";
import "package:inventree/l10.dart";
Expand Down Expand Up @@ -107,23 +105,9 @@ class InvenTreeStockItemHistory extends InvenTreeModel {
};
}

DateTime? get date {
if (jsondata.containsKey("date")) {
return DateTime.tryParse((jsondata["date"] ?? "") as String);
} else {
return null;
}
}
DateTime? get date => getDate("date");

String get dateString {
var d = date;

if (d == null) {
return "";
}

return DateFormat("yyyy-MM-dd").format(d);
}
String get dateString => getDateString("date");

String get label => getString("label");

Expand Down Expand Up @@ -258,6 +242,7 @@ class InvenTreeStockItem extends InvenTreeModel {
"part_detail": "true",
"location_detail": "true",
"supplier_detail": "true",
"supplier_part_detail": "true",
"cascade": "false"
};
}
Expand Down Expand Up @@ -347,46 +332,22 @@ class InvenTreeStockItem extends InvenTreeModel {

bool get hasCustomer => customerId > 0;

// Date of last update
DateTime? get updatedDate {
if (jsondata.containsKey("updated")) {
return DateTime.tryParse((jsondata["updated"] ?? "") as String);
} else {
return null;
}
}

String get updatedDateString {
var _updated = updatedDate;
bool get stale => getBool("stale");

if (_updated == null) {
return "";
}
bool get expired => getBool("expired");

final DateFormat _format = DateFormat("yyyy-MM-dd");
DateTime? get expiryDate => getDate("expiry_date");

return _format.format(_updated);
}
String get expiryDateString => getDateString("expiry_date");

DateTime? get stocktakeDate {
if (jsondata.containsKey("stocktake_date")) {
return DateTime.tryParse((jsondata["stocktake_date"] ?? "") as String);
} else {
return null;
}
}

String get stocktakeDateString {
var _stocktake = stocktakeDate;
// Date of last update
DateTime? get updatedDate => getDate("updated");

if (_stocktake == null) {
return "";
}
String get updatedDateString => getDateString("updated");

final DateFormat _format = DateFormat("yyyy-MM-dd");
DateTime? get stocktakeDate => getDate("stocktake_date");

return _format.format(_stocktake);
}
String get stocktakeDateString => getDateString("stocktake_date");

String get partName {

Expand Down
9 changes: 9 additions & 0 deletions lib/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,15 @@
"errorReportUploadDetails": "Upload anonymous error reports and crash logs",
"@errorReportUploadDetails": {},

"expiryDate": "Expiry Date",
"@expiryDate": {},

"expiryExpired": "Expired",
"@expiryExpired": {},

"expiryStale": "Stale",
"@expiryStale": {},

"feedback": "Feedback",
"@feedback": {},

Expand Down
23 changes: 23 additions & 0 deletions lib/widget/stock/stock_detail.dart
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> {

bool stockShowHistory = false;
bool stockShowTests = true;
bool expiryEnabled = false;

// Linked data fields
InvenTreePart? part;
Expand Down Expand Up @@ -231,6 +232,8 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> {
Navigator.of(context).pop();
}

expiryEnabled = await api.getGlobalBooleanSetting("STOCK_ENABLE_EXPIRY");

// Request part information
part = await InvenTreePart().get(widget.item.partId) as InvenTreePart?;

Expand Down Expand Up @@ -731,6 +734,26 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> {
);
}

if (expiryEnabled && widget.item.expiryDate != null) {

Widget? _expiryIcon;

if (widget.item.stale) {
_expiryIcon = Text(L10().expiryStale, style: TextStyle(color: COLOR_WARNING));
} else if (widget.item.expired) {
_expiryIcon = Text(L10().expiryExpired, style: TextStyle(color: COLOR_DANGER));
}

tiles.add(
ListTile(
title: Text(L10().expiryDate),
subtitle: Text(widget.item.expiryDateString),
leading: Icon(TablerIcons.calendar_x),
trailing: _expiryIcon,
)
);
}

// Last update?
if (widget.item.updatedDateString.isNotEmpty) {

Expand Down
Loading