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
|
### 0.16.5 - September 2024
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@ -291,7 +291,9 @@ class InvenTreeStockItem extends InvenTreeModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int get status => getInt("status");
|
int get status => getInt("status");
|
||||||
|
|
||||||
|
bool get isInStock => getBool("in_stock", backup: true);
|
||||||
|
|
||||||
String get packaging => getString("packaging");
|
String get packaging => getString("packaging");
|
||||||
|
|
||||||
String get batch => getString("batch");
|
String get batch => getString("batch");
|
||||||
@ -321,26 +323,34 @@ class InvenTreeStockItem extends InvenTreeModel {
|
|||||||
|
|
||||||
bool get isBuilding => getBool("is_building");
|
bool get isBuilding => getBool("is_building");
|
||||||
|
|
||||||
// Date of last update
|
int get salesOrderId => getInt("sales_order");
|
||||||
DateTime? get updatedDate {
|
|
||||||
if (jsondata.containsKey("updated")) {
|
bool get hasSalesOrder => salesOrderId > 0;
|
||||||
return DateTime.tryParse((jsondata["updated"] ?? "") as String);
|
|
||||||
} else {
|
int get customerId => getInt("customer");
|
||||||
return null;
|
|
||||||
}
|
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 {
|
final DateFormat _format = DateFormat("yyyy-MM-dd");
|
||||||
var _updated = updatedDate;
|
|
||||||
|
|
||||||
if (_updated == null) {
|
return _format.format(_updated);
|
||||||
return "";
|
}
|
||||||
}
|
|
||||||
|
|
||||||
final DateFormat _format = DateFormat("yyyy-MM-dd");
|
|
||||||
|
|
||||||
return _format.format(_updated);
|
|
||||||
}
|
|
||||||
|
|
||||||
DateTime? get stocktakeDate {
|
DateTime? get stocktakeDate {
|
||||||
if (jsondata.containsKey("stocktake_date")) {
|
if (jsondata.containsKey("stocktake_date")) {
|
||||||
|
@ -1430,6 +1430,12 @@
|
|||||||
"translateHelp": "Help translate the InvenTree app",
|
"translateHelp": "Help translate the InvenTree app",
|
||||||
"@translateHelp": {},
|
"@translateHelp": {},
|
||||||
|
|
||||||
|
"unavailable": "Unavailable",
|
||||||
|
"@unavailable": {},
|
||||||
|
|
||||||
|
"unavailableDetail": "Item is not available",
|
||||||
|
"@unavailableDetail": {},
|
||||||
|
|
||||||
"unitPrice": "Unit Price",
|
"unitPrice": "Unit Price",
|
||||||
"@unitPrice": {},
|
"@unitPrice": {},
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ import "package:inventree/app_colors.dart";
|
|||||||
import "package:inventree/barcode/barcode.dart";
|
import "package:inventree/barcode/barcode.dart";
|
||||||
import "package:inventree/barcode/stock.dart";
|
import "package:inventree/barcode/stock.dart";
|
||||||
import "package:inventree/helpers.dart";
|
import "package:inventree/helpers.dart";
|
||||||
|
import "package:inventree/inventree/sales_order.dart";
|
||||||
import "package:inventree/l10.dart";
|
import "package:inventree/l10.dart";
|
||||||
import "package:inventree/api.dart";
|
import "package:inventree/api.dart";
|
||||||
import "package:inventree/api_form.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/company.dart";
|
||||||
import "package:inventree/inventree/stock.dart";
|
import "package:inventree/inventree/stock.dart";
|
||||||
import "package:inventree/inventree/part.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/company/supplier_part_detail.dart";
|
||||||
import "package:inventree/widget/dialogs.dart";
|
import "package:inventree/widget/dialogs.dart";
|
||||||
import "package:inventree/widget/attachment_widget.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/stock/location_display.dart";
|
||||||
import "package:inventree/widget/part/part_detail.dart";
|
import "package:inventree/widget/part/part_detail.dart";
|
||||||
import "package:inventree/widget/progress.dart";
|
import "package:inventree/widget/progress.dart";
|
||||||
@ -51,6 +54,11 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> {
|
|||||||
bool stockShowHistory = false;
|
bool stockShowHistory = false;
|
||||||
bool stockShowTests = true;
|
bool stockShowTests = true;
|
||||||
|
|
||||||
|
// Linked data fields
|
||||||
|
InvenTreePart? part;
|
||||||
|
InvenTreeSalesOrder? salesOrder;
|
||||||
|
InvenTreeCompany? customer;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Widget> appBarActions(BuildContext context) {
|
List<Widget> appBarActions(BuildContext context) {
|
||||||
List<Widget> actions = [];
|
List<Widget> actions = [];
|
||||||
@ -199,9 +207,6 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> {
|
|||||||
// This will be determined when the widget is loaded
|
// This will be determined when the widget is loaded
|
||||||
List<Map<String, dynamic>> labels = [];
|
List<Map<String, dynamic>> labels = [];
|
||||||
|
|
||||||
// Part object
|
|
||||||
InvenTreePart? part;
|
|
||||||
|
|
||||||
int attachmentCount = 0;
|
int attachmentCount = 0;
|
||||||
|
|
||||||
@override
|
@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 = [];
|
List<Map<String, dynamic>> _labels = [];
|
||||||
bool allowLabelPrinting = await InvenTreeSettingsManager().getBool(INV_ENABLE_LABEL_PRINTING, true);
|
bool allowLabelPrinting = await InvenTreeSettingsManager().getBool(INV_ENABLE_LABEL_PRINTING, true);
|
||||||
allowLabelPrinting &= api.supportsMixin("labels");
|
allowLabelPrinting &= api.supportsMixin("labels");
|
||||||
@ -455,18 +494,32 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget headerTile() {
|
Widget headerTile() {
|
||||||
return Card(
|
|
||||||
child: ListTile(
|
Widget? trailing;
|
||||||
title: Text("${widget.item.partName}"),
|
|
||||||
subtitle: Text("${widget.item.partDescription}"),
|
if (!widget.item.isInStock) {
|
||||||
leading: InvenTreeAPI().getThumbnail(widget.item.partImage),
|
trailing = Text(
|
||||||
trailing: widget.item.isSerialized() ? null : Text(
|
L10().unavailable,
|
||||||
|
style: TextStyle(
|
||||||
|
color: COLOR_DANGER
|
||||||
|
)
|
||||||
|
);
|
||||||
|
} else if (!widget.item.isSerialized()) {
|
||||||
|
trailing = Text(
|
||||||
widget.item.quantityString(),
|
widget.item.quantityString(),
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
color: api.StockStatus.color(widget.item.status),
|
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 {
|
onTap: () async {
|
||||||
if (widget.item.partId > 0) {
|
if (widget.item.partId > 0) {
|
||||||
|
|
||||||
@ -544,7 +597,7 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> {
|
|||||||
subtitle: Text("${widget.item.serialNumber}"),
|
subtitle: Text("${widget.item.serialNumber}"),
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
} else {
|
} else if (widget.item.isInStock) {
|
||||||
tiles.add(
|
tiles.add(
|
||||||
ListTile(
|
ListTile(
|
||||||
title: widget.item.allocated > 0 ? Text(L10().quantityAvailable) : Text(L10().quantity),
|
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
|
// Stock item status information
|
||||||
tiles.add(
|
tiles.add(
|
||||||
ListTile(
|
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) {
|
if (widget.item.batch.isNotEmpty) {
|
||||||
tiles.add(
|
tiles.add(
|
||||||
ListTile(
|
ListTile(
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
name: inventree
|
name: inventree
|
||||||
description: InvenTree stock management
|
description: InvenTree stock management
|
||||||
|
|
||||||
version: 0.16.5+91
|
version: 0.17.0+92
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=2.19.5 <3.13.0"
|
sdk: ">=2.19.5 <3.13.0"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user