mirror of
https://github.com/HendrikRauh/inventree-app.git
synced 2026-02-04 21:03:18 +00:00
Part requirements (#761)
* Add setting to control if part requirements are shown * Split settings for Part and Stock * Fetch part requirements information * Add "building" indicator * Show order allocation progress for part requirements * Bump release notes * Remove unused import
This commit is contained in:
parent
e38c51e947
commit
ee553af93b
10 changed files with 357 additions and 70 deletions
|
|
@ -54,6 +54,7 @@ class _PartDisplayState extends RefreshableState<PartDetailWidget> {
|
|||
bool allowLabelPrinting = false;
|
||||
bool showBom = false;
|
||||
bool showPricing = false;
|
||||
bool showRequirements = false;
|
||||
|
||||
int parameterCount = 0;
|
||||
int attachmentCount = 0;
|
||||
|
|
@ -62,6 +63,7 @@ class _PartDisplayState extends RefreshableState<PartDetailWidget> {
|
|||
int variantCount = 0;
|
||||
|
||||
InvenTreePartPricing? partPricing;
|
||||
InvenTreePartRequirements? partRequirements;
|
||||
|
||||
@override
|
||||
String getAppBarTitle() => L10().partDetails;
|
||||
|
|
@ -148,6 +150,12 @@ class _PartDisplayState extends RefreshableState<PartDetailWidget> {
|
|||
final bool result = await part.reload();
|
||||
|
||||
// Load page settings from local storage
|
||||
|
||||
showRequirements = await InvenTreeSettingsManager().getBool(
|
||||
INV_PART_SHOW_REQUIREMENTS,
|
||||
false,
|
||||
);
|
||||
|
||||
showPricing = await InvenTreeSettingsManager().getBool(
|
||||
INV_PART_SHOW_PRICING,
|
||||
true,
|
||||
|
|
@ -233,6 +241,23 @@ class _PartDisplayState extends RefreshableState<PartDetailWidget> {
|
|||
});
|
||||
}
|
||||
|
||||
// If show requirements information?
|
||||
if (showRequirements && api.supportsPartRequirements) {
|
||||
part.getRequirements().then((InvenTreePartRequirements? requirements) {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
partRequirements = requirements;
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
partRequirements = null;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// If show pricing information?
|
||||
if (showPricing) {
|
||||
part.getPricing().then((InvenTreePartPricing? pricing) {
|
||||
|
|
@ -242,6 +267,12 @@ class _PartDisplayState extends RefreshableState<PartDetailWidget> {
|
|||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
partPricing = null;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Request the number of BOM items
|
||||
|
|
@ -434,6 +465,103 @@ class _PartDisplayState extends RefreshableState<PartDetailWidget> {
|
|||
);
|
||||
}
|
||||
|
||||
// Part "requirements"
|
||||
if (showRequirements &&
|
||||
api.supportsPartRequirements &&
|
||||
partRequirements != null) {
|
||||
// Assembly parts
|
||||
if (part.isAssembly) {
|
||||
// Scheduled to build
|
||||
if (partRequirements!.building > 0 ||
|
||||
partRequirements!.scheduledToBuild > 0) {
|
||||
tiles.add(
|
||||
ListTile(
|
||||
title: Text(L10().building),
|
||||
subtitle: ProgressBar(
|
||||
partRequirements!.building,
|
||||
maximum: partRequirements!.scheduledToBuild,
|
||||
),
|
||||
leading: Icon(TablerIcons.tools),
|
||||
trailing: ProgressText(
|
||||
partRequirements!.building,
|
||||
maximum: partRequirements!.scheduledToBuild,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// Can build
|
||||
if (part.isActive) {
|
||||
tiles.add(
|
||||
ListTile(
|
||||
title: Text(L10().canBuild),
|
||||
subtitle: Text(L10().canBuildDetail),
|
||||
trailing: LargeText(
|
||||
simpleNumberString(partRequirements!.canBuild),
|
||||
),
|
||||
leading: Icon(TablerIcons.check),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Build requirements
|
||||
if (partRequirements!.requiredForBuildOrders > 0 ||
|
||||
partRequirements!.allocatedToBuildOrders > 0) {
|
||||
tiles.add(
|
||||
ListTile(
|
||||
title: Text(L10().allocatedToBuildOrders),
|
||||
subtitle: ProgressBar(
|
||||
partRequirements!.allocatedToBuildOrders,
|
||||
maximum: partRequirements!.requiredForBuildOrders,
|
||||
),
|
||||
trailing: ProgressText(
|
||||
partRequirements!.allocatedToBuildOrders,
|
||||
maximum: partRequirements!.requiredForBuildOrders,
|
||||
),
|
||||
leading: Icon(TablerIcons.tools),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// Sales requirements
|
||||
if (part.isSalable) {
|
||||
if (partRequirements!.requiredForSalesOrders > 0 ||
|
||||
partRequirements!.allocatedToSalesOrders > 0) {
|
||||
tiles.add(
|
||||
ListTile(
|
||||
title: Text(L10().allocatedToSalesOrders),
|
||||
subtitle: ProgressBar(
|
||||
partRequirements!.allocatedToSalesOrders,
|
||||
maximum: partRequirements!.requiredForSalesOrders,
|
||||
),
|
||||
trailing: ProgressText(
|
||||
partRequirements!.allocatedToSalesOrders,
|
||||
maximum: partRequirements!.requiredForSalesOrders,
|
||||
),
|
||||
leading: Icon(TablerIcons.truck_delivery),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Ordering stats
|
||||
if (part.isPurchaseable && partRequirements!.ordering > 0) {
|
||||
// On order
|
||||
tiles.add(
|
||||
ListTile(
|
||||
title: Text(L10().onOrder),
|
||||
subtitle: Text(L10().onOrderDetails),
|
||||
leading: Icon(TablerIcons.shopping_cart),
|
||||
trailing: LargeText("${part.onOrderString}"),
|
||||
onTap: () {
|
||||
// TODO - Order views
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (showPricing && partPricing != null) {
|
||||
String pricing = formatPriceRange(
|
||||
partPricing?.overallMin,
|
||||
|
|
@ -462,22 +590,6 @@ class _PartDisplayState extends RefreshableState<PartDetailWidget> {
|
|||
);
|
||||
}
|
||||
|
||||
// Tiles for "purchaseable" parts
|
||||
if (part.isPurchaseable) {
|
||||
// On order
|
||||
tiles.add(
|
||||
ListTile(
|
||||
title: Text(L10().onOrder),
|
||||
subtitle: Text(L10().onOrderDetails),
|
||||
leading: Icon(TablerIcons.shopping_cart),
|
||||
trailing: LargeText("${part.onOrderString}"),
|
||||
onTap: () {
|
||||
// TODO - Order views
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// Tiles for an "assembly" part
|
||||
if (part.isAssembly) {
|
||||
if (showBom && bomCount > 0) {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@ import "dart:io";
|
|||
import "package:flutter/material.dart";
|
||||
import "package:flutter_overlay_loader/flutter_overlay_loader.dart";
|
||||
import "package:inventree/app_colors.dart";
|
||||
import "package:inventree/helpers.dart";
|
||||
import "package:inventree/widget/link_icon.dart";
|
||||
import "package:one_context/one_context.dart";
|
||||
|
||||
/*
|
||||
|
|
@ -25,6 +27,15 @@ Widget ProgressBar(double value, {double maximum = 1.0}) {
|
|||
);
|
||||
}
|
||||
|
||||
Widget ProgressText(double value, {double maximum = 1.0}) {
|
||||
Color textColor = value < maximum ? COLOR_WARNING : COLOR_SUCCESS;
|
||||
|
||||
String v = simpleNumberString(value);
|
||||
String m = simpleNumberString(maximum);
|
||||
|
||||
return LargeText("${v} / ${m}", color: textColor);
|
||||
}
|
||||
|
||||
/*
|
||||
* Construct a circular progress indicator
|
||||
*/
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue