2
0
mirror of https://github.com/inventree/inventree-app.git synced 2025-04-28 05:26:47 +00:00

StockItem Updates (#550)
Some checks failed
Android / build (push) Has been cancelled
CI / test (push) Has been cancelled
iOS / build (push) Has been cancelled

* bump version

* Add new helpers for StockItem

* Navigate to sales order from stock item

* Navigate to customer (if specified)

* linting fix
This commit is contained in:
Oliver 2024-11-20 16:47:04 +11:00 committed by GitHub
parent 1a1521efe3
commit 20e454d287
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 157 additions and 30 deletions

View File

@ -1,3 +1,8 @@
### 0.17.0 - November 2024
---
- Clearly indicate if a StockItem is unavailable
### 0.16.5 - September 2024
---

View File

@ -291,7 +291,9 @@ class InvenTreeStockItem extends InvenTreeModel {
}
int get status => getInt("status");
bool get isInStock => getBool("in_stock", backup: true);
String get packaging => getString("packaging");
String get batch => getString("batch");
@ -321,26 +323,34 @@ class InvenTreeStockItem extends InvenTreeModel {
bool get isBuilding => getBool("is_building");
// Date of last update
DateTime? get updatedDate {
if (jsondata.containsKey("updated")) {
return DateTime.tryParse((jsondata["updated"] ?? "") as String);
} else {
return null;
}
int get salesOrderId => getInt("sales_order");
bool get hasSalesOrder => salesOrderId > 0;
int get customerId => getInt("customer");
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;
if (_updated == null) {
return "";
}
String get updatedDateString {
var _updated = updatedDate;
final DateFormat _format = DateFormat("yyyy-MM-dd");
if (_updated == null) {
return "";
}
final DateFormat _format = DateFormat("yyyy-MM-dd");
return _format.format(_updated);
}
return _format.format(_updated);
}
DateTime? get stocktakeDate {
if (jsondata.containsKey("stocktake_date")) {

View File

@ -1430,6 +1430,12 @@
"translateHelp": "Help translate the InvenTree app",
"@translateHelp": {},
"unavailable": "Unavailable",
"@unavailable": {},
"unavailableDetail": "Item is not available",
"@unavailableDetail": {},
"unitPrice": "Unit Price",
"@unitPrice": {},

View File

@ -7,6 +7,7 @@ import "package:inventree/app_colors.dart";
import "package:inventree/barcode/barcode.dart";
import "package:inventree/barcode/stock.dart";
import "package:inventree/helpers.dart";
import "package:inventree/inventree/sales_order.dart";
import "package:inventree/l10.dart";
import "package:inventree/api.dart";
import "package:inventree/api_form.dart";
@ -16,10 +17,12 @@ import "package:inventree/preferences.dart";
import "package:inventree/inventree/company.dart";
import "package:inventree/inventree/stock.dart";
import "package:inventree/inventree/part.dart";
import "package:inventree/widget/company/company_detail.dart";
import "package:inventree/widget/company/supplier_part_detail.dart";
import "package:inventree/widget/dialogs.dart";
import "package:inventree/widget/attachment_widget.dart";
import "package:inventree/widget/order/sales_order_detail.dart";
import "package:inventree/widget/stock/location_display.dart";
import "package:inventree/widget/part/part_detail.dart";
import "package:inventree/widget/progress.dart";
@ -51,6 +54,11 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> {
bool stockShowHistory = false;
bool stockShowTests = true;
// Linked data fields
InvenTreePart? part;
InvenTreeSalesOrder? salesOrder;
InvenTreeCompany? customer;
@override
List<Widget> appBarActions(BuildContext context) {
List<Widget> actions = [];
@ -199,9 +207,6 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> {
// This will be determined when the widget is loaded
List<Map<String, dynamic>> labels = [];
// Part object
InvenTreePart? part;
int attachmentCount = 0;
@override
@ -252,6 +257,40 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> {
}
});
// Request SalesOrder information
if (widget.item.hasSalesOrder) {
InvenTreeSalesOrder().get(widget.item.salesOrderId).then((instance) => {
if (mounted) {
setState(() {
salesOrder = instance as InvenTreeSalesOrder?;
})
}
});
} else {
if (mounted) {
setState(() {
salesOrder = null;
});
}
}
// Request Customer information
if (widget.item.hasCustomer) {
InvenTreeCompany().get(widget.item.customerId).then((instance) => {
if (mounted) {
setState(() {
customer = instance as InvenTreeCompany?;
})
}
});
} else {
if (mounted) {
setState(() {
customer = null;
});
}
}
List<Map<String, dynamic>> _labels = [];
bool allowLabelPrinting = await InvenTreeSettingsManager().getBool(INV_ENABLE_LABEL_PRINTING, true);
allowLabelPrinting &= api.supportsMixin("labels");
@ -455,18 +494,32 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> {
}
Widget headerTile() {
return Card(
child: ListTile(
title: Text("${widget.item.partName}"),
subtitle: Text("${widget.item.partDescription}"),
leading: InvenTreeAPI().getThumbnail(widget.item.partImage),
trailing: widget.item.isSerialized() ? null : Text(
Widget? trailing;
if (!widget.item.isInStock) {
trailing = Text(
L10().unavailable,
style: TextStyle(
color: COLOR_DANGER
)
);
} else if (!widget.item.isSerialized()) {
trailing = Text(
widget.item.quantityString(),
style: TextStyle(
fontSize: 20,
color: api.StockStatus.color(widget.item.status),
)
),
);
}
return Card(
child: ListTile(
title: Text("${widget.item.partName}"),
subtitle: Text("${widget.item.partDescription}"),
leading: InvenTreeAPI().getThumbnail(widget.item.partImage),
trailing: trailing,
onTap: () async {
if (widget.item.partId > 0) {
@ -544,7 +597,7 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> {
subtitle: Text("${widget.item.serialNumber}"),
)
);
} else {
} else if (widget.item.isInStock) {
tiles.add(
ListTile(
title: widget.item.allocated > 0 ? Text(L10().quantityAvailable) : Text(L10().quantity),
@ -554,6 +607,27 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> {
);
}
if (!widget.item.isInStock) {
tiles.add(
ListTile(
leading: Icon(TablerIcons.box_off),
title: Text(
L10().unavailable,
style: TextStyle(
color: COLOR_DANGER,
fontWeight: FontWeight.bold,
),
),
subtitle: Text(
L10().unavailableDetail,
style: TextStyle(
color: COLOR_DANGER
)
)
)
);
}
// Stock item status information
tiles.add(
ListTile(
@ -605,6 +679,38 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> {
);
}
if (widget.item.hasSalesOrder && salesOrder != null) {
tiles.add(
ListTile(
title: Text(L10().salesOrder),
subtitle: Text(salesOrder?.description ?? ""),
leading: Icon(TablerIcons.truck_delivery, color: COLOR_ACTION),
trailing: Text(salesOrder?.reference ?? ""),
onTap: () {
Navigator.push(context, MaterialPageRoute(
builder: (context) => SalesOrderDetailWidget(salesOrder!)
));
}
)
);
}
if (widget.item.hasCustomer && customer != null) {
tiles.add(
ListTile(
title: Text(L10().customer),
subtitle: Text(customer?.description ?? ""),
leading: Icon(TablerIcons.building_store, color: COLOR_ACTION),
trailing: Text(customer?.name ?? ""),
onTap: () {
Navigator.push(context, MaterialPageRoute(
builder: (context) => CompanyDetailWidget(customer!)
));
},
)
);
}
if (widget.item.batch.isNotEmpty) {
tiles.add(
ListTile(

View File

@ -1,7 +1,7 @@
name: inventree
description: InvenTree stock management
version: 0.16.5+91
version: 0.17.0+92
environment:
sdk: ">=2.19.5 <3.13.0"