2
0
mirror of https://github.com/inventree/inventree-app.git synced 2025-08-06 04:31:43 +00:00

Order picture action (#557)

* Add "take picture" to purchase order detail

* Rename uploaded images

* Provide prefix when uploading images

* Add similar functionality for "sales order" detail

* Add new settings screens

* Control camera shortcut

* Bump release notes
This commit is contained in:
Oliver
2024-12-05 14:38:53 +11:00
committed by GitHub
parent 4698e7e82c
commit 2e798b1bd1
14 changed files with 321 additions and 17 deletions

View File

@@ -26,11 +26,12 @@ import "package:inventree/widget/refreshable_state.dart";
*/
class AttachmentWidget extends StatefulWidget {
const AttachmentWidget(this.attachmentClass, this.modelId, this.hasUploadPermission) : super();
const AttachmentWidget(this.attachmentClass, this.modelId, this.imagePrefix, this.hasUploadPermission) : super();
final InvenTreeAttachment attachmentClass;
final int modelId;
final bool hasUploadPermission;
final String imagePrefix;
@override
_AttachmentWidgetState createState() => _AttachmentWidgetState();
@@ -54,6 +55,10 @@ class _AttachmentWidgetState extends RefreshableState<AttachmentWidget> {
IconButton(
icon: Icon(TablerIcons.camera),
onPressed: () async {
widget.attachmentClass.uploadImage(
widget.modelId,
prefix: widget.imagePrefix,
);
FilePickerDialog.pickImageFromCamera().then((File? file) {
upload(context, file);
});
@@ -78,7 +83,6 @@ class _AttachmentWidgetState extends RefreshableState<AttachmentWidget> {
final bool result = await widget.attachmentClass.uploadAttachment(
file,
widget.attachmentClass.REF_MODEL_TYPE,
widget.modelId
);

View File

@@ -404,6 +404,7 @@ class _CompanyDetailState extends RefreshableState<CompanyDetailWidget> {
builder: (context) => AttachmentWidget(
InvenTreeCompanyAttachment(),
widget.company.pk,
widget.company.name,
InvenTreeCompany().canEdit
)
)

View File

@@ -19,6 +19,7 @@ import "package:inventree/widget/progress.dart";
import "package:inventree/widget/refreshable_state.dart";
import "package:inventree/widget/snacks.dart";
import "package:inventree/widget/stock/stock_list.dart";
import "package:inventree/preferences.dart";
/*
@@ -45,6 +46,7 @@ class _PurchaseOrderDetailState extends RefreshableState<PurchaseOrderDetailWidg
int attachmentCount = 0;
bool showCameraShortcut = true;
bool supportProjectCodes = false;
@override
@@ -73,6 +75,18 @@ class _PurchaseOrderDetailState extends RefreshableState<PurchaseOrderDetailWidg
List<SpeedDialChild> actionButtons(BuildContext context) {
List<SpeedDialChild> actions = [];
if (showCameraShortcut && widget.order.canEdit) {
actions.add(
SpeedDialChild(
child: Icon(TablerIcons.camera, color: Colors.blue),
label: L10().takePicture,
onTap: () async {
_uploadImage(context);
}
)
);
}
if (widget.order.canCreate) {
if (widget.order.isPending) {
@@ -137,6 +151,15 @@ class _PurchaseOrderDetailState extends RefreshableState<PurchaseOrderDetailWidg
);
}
/// Upload an image against the current PurchaseOrder
Future<void> _uploadImage(BuildContext context) async {
InvenTreePurchaseOrderAttachment().uploadImage(
widget.order.pk,
prefix: widget.order.reference,
).then((result) => refresh(context));
}
/// Issue this order
Future<void> _issueOrder(BuildContext context) async {
@@ -217,6 +240,7 @@ class _PurchaseOrderDetailState extends RefreshableState<PurchaseOrderDetailWidg
lines = await widget.order.getLineItems();
showCameraShortcut = await InvenTreeSettingsManager().getBool(INV_PO_SHOW_CAMERA, true);
supportProjectCodes = api.supportsProjectCodes && await api.getGlobalBooleanSetting("PROJECT_CODES_ENABLED");
completedLines = 0;
@@ -389,6 +413,7 @@ class _PurchaseOrderDetailState extends RefreshableState<PurchaseOrderDetailWidg
builder: (context) => AttachmentWidget(
InvenTreePurchaseOrderAttachment(),
widget.order.pk,
widget.order.reference,
widget.order.canEdit
)
)

View File

@@ -6,6 +6,7 @@ import "package:inventree/barcode/barcode.dart";
import "package:inventree/barcode/sales_order.dart";
import "package:inventree/inventree/company.dart";
import "package:inventree/inventree/sales_order.dart";
import "package:inventree/preferences.dart";
import "package:inventree/widget/order/so_line_list.dart";
import "package:inventree/widget/order/so_shipment_list.dart";
import "package:inventree/widget/refreshable_state.dart";
@@ -40,6 +41,7 @@ class _SalesOrderDetailState extends RefreshableState<SalesOrderDetailWidget> {
List<InvenTreeSOLineItem> lines = [];
bool showCameraShortcut = true;
bool supportsProjectCodes = false;
int attachmentCount = 0;
@@ -100,6 +102,14 @@ class _SalesOrderDetailState extends RefreshableState<SalesOrderDetailWidget> {
);
}
/// Upload an image for this order
Future<void> _uploadImage(BuildContext context) async {
InvenTreeSalesOrderAttachment().uploadImage(
widget.order.pk,
prefix: widget.order.reference,
).then((result) => refresh(context));
}
/// Issue this order
Future<void> _issueOrder(BuildContext context) async {
@@ -136,6 +146,18 @@ class _SalesOrderDetailState extends RefreshableState<SalesOrderDetailWidget> {
List<SpeedDialChild> actionButtons(BuildContext context) {
List<SpeedDialChild> actions = [];
if (showCameraShortcut && widget.order.canEdit) {
actions.add(
SpeedDialChild(
child: Icon(TablerIcons.camera, color: Colors.blue),
label: L10().takePicture,
onTap: () async {
_uploadImage(context);
}
)
);
}
if (widget.order.isPending) {
actions.add(
SpeedDialChild(
@@ -231,6 +253,7 @@ class _SalesOrderDetailState extends RefreshableState<SalesOrderDetailWidget> {
await api.SalesOrderStatus.load();
supportsProjectCodes = api.supportsProjectCodes && await api.getGlobalBooleanSetting("PROJECT_CODES_ENABLED");
showCameraShortcut = await InvenTreeSettingsManager().getBool(INV_SO_SHOW_CAMERA, true);
InvenTreeSalesOrderAttachment().countAttachments(widget.order.pk).then((int value) {
if (mounted) {
@@ -378,6 +401,7 @@ class _SalesOrderDetailState extends RefreshableState<SalesOrderDetailWidget> {
builder: (context) => AttachmentWidget(
InvenTreeSalesOrderAttachment(),
widget.order.pk,
widget.order.reference,
widget.order.canEdit
)
)

View File

@@ -181,7 +181,7 @@ class _PartDisplayState extends RefreshableState<PartDetailWidget> {
});
// Request the number of parameters for this part
showParameters = await InvenTreeSettingsManager().getValue(INV_PART_SHOW_PARAMETERS, true) as bool;
showParameters = await InvenTreeSettingsManager().getBool(INV_PART_SHOW_PARAMETERS, true);
// Request the number of attachments
InvenTreePartAttachment().countAttachments(part.pk).then((int value) {
@@ -192,7 +192,7 @@ class _PartDisplayState extends RefreshableState<PartDetailWidget> {
}
});
showBom = await InvenTreeSettingsManager().getValue(INV_PART_SHOW_BOM, true) as bool;
showBom = await InvenTreeSettingsManager().getBool(INV_PART_SHOW_BOM, true);
// Request the number of BOM items
InvenTreePart().count(
@@ -588,6 +588,7 @@ class _PartDisplayState extends RefreshableState<PartDetailWidget> {
builder: (context) => AttachmentWidget(
InvenTreePartAttachment(),
part.pk,
L10().part,
part.canEdit
)
)

View File

@@ -844,6 +844,7 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> {
builder: (context) => AttachmentWidget(
InvenTreeStockItemAttachment(),
widget.item.pk,
L10().stockItem,
widget.item.canEdit,
)
)