mirror of
https://github.com/inventree/inventree-app.git
synced 2025-04-28 05:26:47 +00:00
StockItem Updates (#550)
* 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:
parent
1a1521efe3
commit
20e454d287
@ -1,3 +1,8 @@
|
||||
### 0.17.0 - November 2024
|
||||
---
|
||||
|
||||
- Clearly indicate if a StockItem is unavailable
|
||||
|
||||
### 0.16.5 - September 2024
|
||||
---
|
||||
|
||||
|
@ -292,6 +292,8 @@ 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")) {
|
||||
|
@ -1430,6 +1430,12 @@
|
||||
"translateHelp": "Help translate the InvenTree app",
|
||||
"@translateHelp": {},
|
||||
|
||||
"unavailable": "Unavailable",
|
||||
"@unavailable": {},
|
||||
|
||||
"unavailableDetail": "Item is not available",
|
||||
"@unavailableDetail": {},
|
||||
|
||||
"unitPrice": "Unit Price",
|
||||
"@unitPrice": {},
|
||||
|
||||
|
@ -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(
|
||||
|
@ -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"
|
||||
|
Loading…
x
Reference in New Issue
Block a user