mirror of
https://github.com/inventree/inventree-app.git
synced 2025-06-16 12:15:31 +00:00
[refactor] Scan improvements (#577)
* Handle error on unexpected barcode response * Add ManufacturerPart detail view * Support barcode scanning for manufacturer part * Refactoring for null checks * Ignore selected errors in sentry * Fix API implementation for ManufacturerPart * Update release notes * More error handling * Decode quantity betterer * Refactoring * Add option to confirm checkin details * Improve response handlign * Cleanup * Remove unused imports * Fix async function * Fix for assigning custom barcode * Handle barcode scan result for company * Fix * Adjust scan priority * Refactoring MODEL_TYPE - Use instead of duplicated const strings * @override fix
This commit is contained in:
@ -18,6 +18,8 @@ class InvenTreeCompany extends InvenTreeModel {
|
||||
@override
|
||||
String get URL => "company/";
|
||||
|
||||
static const String MODEL_TYPE = "company";
|
||||
|
||||
@override
|
||||
List<String> get rolesRequired => ["purchase_order", "sales_order", "return_order"];
|
||||
|
||||
@ -128,6 +130,8 @@ class InvenTreeSupplierPart extends InvenTreeModel {
|
||||
@override
|
||||
String get URL => "company/part/";
|
||||
|
||||
static const String MODEL_TYPE = "supplierpart";
|
||||
|
||||
@override
|
||||
List<String> get rolesRequired => ["part", "purchase_order"];
|
||||
|
||||
@ -171,7 +175,7 @@ class InvenTreeSupplierPart extends InvenTreeModel {
|
||||
|
||||
String get MPN => getString("MPN", subKey: "manufacturer_part_detail");
|
||||
|
||||
String get manufacturerImage => (jsondata["manufacturer_detail"]?["image"] ?? jsondata["manufacturer_detail"]["thumbnail"] ?? InvenTreeAPI.staticThumb) as String;
|
||||
String get manufacturerImage => (jsondata["manufacturer_detail"]?["image"] ?? jsondata["manufacturer_detail"]?["thumbnail"] ?? InvenTreeAPI.staticThumb) as String;
|
||||
|
||||
int get manufacturerPartId => getInt("manufacturer_part");
|
||||
|
||||
@ -179,14 +183,14 @@ class InvenTreeSupplierPart extends InvenTreeModel {
|
||||
|
||||
String get supplierName => getString("name", subKey: "supplier_detail");
|
||||
|
||||
String get supplierImage => (jsondata["supplier_detail"]?["image"] ?? jsondata["supplier_detail"]["thumbnail"] ?? InvenTreeAPI.staticThumb) as String;
|
||||
String get supplierImage => (jsondata["supplier_detail"]?["image"] ?? jsondata["supplier_detail"]?["thumbnail"] ?? InvenTreeAPI.staticThumb) as String;
|
||||
|
||||
String get SKU => getString("SKU");
|
||||
|
||||
bool get active => getBool("active", backup: true);
|
||||
|
||||
int get partId => getInt("part");
|
||||
|
||||
|
||||
String get partImage => (jsondata["part_detail"]?["thumbnail"] ?? InvenTreeAPI.staticThumb) as String;
|
||||
|
||||
String get partName => getString("name", subKey: "part_detail");
|
||||
@ -219,21 +223,52 @@ class InvenTreeManufacturerPart extends InvenTreeModel {
|
||||
InvenTreeManufacturerPart.fromJson(Map<String, dynamic> json) : super.fromJson(json);
|
||||
|
||||
@override
|
||||
String url = "company/part/manufacturer/";
|
||||
String URL = "company/part/manufacturer/";
|
||||
|
||||
static const String MODEL_TYPE = "manufacturerpart";
|
||||
|
||||
@override
|
||||
Map<String, String> defaultListFilters() {
|
||||
List<String> get rolesRequired => ["part"];
|
||||
|
||||
@override
|
||||
Map<String, Map<String, dynamic>> formFields() {
|
||||
Map<String, Map<String, dynamic>> fields = {
|
||||
"manufacturer": {},
|
||||
"MPN": {},
|
||||
"link": {},
|
||||
};
|
||||
|
||||
return fields;
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, String> defaultFilters() {
|
||||
return {
|
||||
"manufacturer_detail": "true",
|
||||
"part_detail": "true",
|
||||
};
|
||||
}
|
||||
|
||||
int get partId => getInt("part");
|
||||
|
||||
|
||||
String get partName => getString("name", subKey: "part_detail");
|
||||
|
||||
String get partDescription => getString("description", subKey: "part_detail");
|
||||
|
||||
String get partIPN => getString("IPN", subKey: "part_detail");
|
||||
|
||||
String get partImage => (jsondata["part_detail"]?["thumbnail"] ?? InvenTreeAPI.staticThumb) as String;
|
||||
|
||||
int get manufacturerId => getInt("manufacturer");
|
||||
|
||||
|
||||
String get manufacturerName => getString("name", subKey: "manufacturer_detail");
|
||||
|
||||
String get manufacturerDescription => getString("description", subKey: "manufacturer_detail");
|
||||
|
||||
String get manufacturerImage => (jsondata["manufacturer_detail"]?["image"] ?? jsondata["manufacturer_detail"]?["thumbnail"] ?? InvenTreeAPI.staticThumb) as String;
|
||||
|
||||
String get MPN => getString("MPN");
|
||||
|
||||
|
||||
@override
|
||||
InvenTreeModel createFromJson(Map<String, dynamic> json) => InvenTreeManufacturerPart.fromJson(json);
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ class InvenTreeModel {
|
||||
String get WEB_URL => "";
|
||||
|
||||
// Return the "model type" of this model
|
||||
String get MODEL_TYPE => "";
|
||||
static const String MODEL_TYPE = "";
|
||||
|
||||
// Helper function to set a value in the JSON data
|
||||
void setValue(String key, dynamic value) {
|
||||
|
@ -23,6 +23,8 @@ class InvenTreePartCategory extends InvenTreeModel {
|
||||
@override
|
||||
String get URL => "part/category/";
|
||||
|
||||
static const String MODEL_TYPE = "partcategory";
|
||||
|
||||
@override
|
||||
List<String> get rolesRequired => ["part_category"];
|
||||
|
||||
@ -79,6 +81,8 @@ class InvenTreePartTestTemplate extends InvenTreeModel {
|
||||
@override
|
||||
String get URL => "part/test-template/";
|
||||
|
||||
static const String MODEL_TYPE = "parttesttemplate";
|
||||
|
||||
String get key => getString("key");
|
||||
|
||||
String get testName => getString("test_name");
|
||||
@ -192,8 +196,7 @@ class InvenTreePart extends InvenTreeModel {
|
||||
@override
|
||||
String get URL => "part/";
|
||||
|
||||
@override
|
||||
String get MODEL_TYPE => "part";
|
||||
static const String MODEL_TYPE = "part";
|
||||
|
||||
@override
|
||||
List<String> get rolesRequired => ["part"];
|
||||
|
@ -16,6 +16,8 @@ class InvenTreeProjectCode extends InvenTreeModel {
|
||||
@override
|
||||
String get URL => "project-code/";
|
||||
|
||||
static const String MODEL_TYPE = "projectcode";
|
||||
|
||||
@override
|
||||
Map<String, Map<String, dynamic>> formFields() {
|
||||
return {
|
||||
|
@ -1,3 +1,5 @@
|
||||
import "package:flutter/cupertino.dart";
|
||||
import "package:flutter_tabler_icons/flutter_tabler_icons.dart";
|
||||
import "package:inventree/api.dart";
|
||||
import "package:inventree/helpers.dart";
|
||||
import "package:inventree/inventree/company.dart";
|
||||
@ -5,6 +7,9 @@ import "package:inventree/inventree/model.dart";
|
||||
import "package:inventree/inventree/orders.dart";
|
||||
import "package:inventree/widget/progress.dart";
|
||||
|
||||
import "package:inventree/api_form.dart";
|
||||
import "package:inventree/l10.dart";
|
||||
|
||||
|
||||
/*
|
||||
* Class representing an individual PurchaseOrder instance
|
||||
@ -21,8 +26,7 @@ class InvenTreePurchaseOrder extends InvenTreeOrder {
|
||||
@override
|
||||
String get URL => "order/po/";
|
||||
|
||||
@override
|
||||
String get MODEL_TYPE => "purchaseorder";
|
||||
static const String MODEL_TYPE = "purchaseorder";
|
||||
|
||||
@override
|
||||
List<String> get rolesRequired => ["purchase_order"];
|
||||
@ -212,6 +216,16 @@ class InvenTreePOLineItem extends InvenTreeOrderLine {
|
||||
}
|
||||
}
|
||||
|
||||
InvenTreePurchaseOrder? get purchaseOrder {
|
||||
dynamic detail = jsondata["order_detail"];
|
||||
|
||||
if (detail == null) {
|
||||
return null;
|
||||
} else {
|
||||
return InvenTreePurchaseOrder.fromJson(detail as Map<String, dynamic>);
|
||||
}
|
||||
}
|
||||
|
||||
String get SKU => getString("SKU", subKey: "supplier_part_detail");
|
||||
|
||||
double get purchasePrice => getDouble("purchase_price");
|
||||
@ -223,6 +237,72 @@ class InvenTreePOLineItem extends InvenTreeOrderLine {
|
||||
Map<String, dynamic> get orderDetail => getMap("order_detail");
|
||||
|
||||
Map<String, dynamic> get destinationDetail => getMap("destination_detail");
|
||||
|
||||
// Receive this line item into stock
|
||||
Future<void> receive(BuildContext context, {int? destination, double? quantity, String? barcode, Function? onSuccess}) async {
|
||||
// Infer the destination location from the line item if not provided
|
||||
if (destinationId > 0) {
|
||||
destination = destinationId;
|
||||
}
|
||||
|
||||
destination ??= (orderDetail["destination"]) as int?;
|
||||
|
||||
quantity ??= outstanding;
|
||||
|
||||
// Construct form fields
|
||||
Map<String, dynamic> fields = {
|
||||
"line_item": {
|
||||
"parent": "items",
|
||||
"nested": true,
|
||||
"hidden": true,
|
||||
"value": pk,
|
||||
},
|
||||
"quantity": {
|
||||
"parent": "items",
|
||||
"nested": true,
|
||||
"value": quantity,
|
||||
},
|
||||
"location": {},
|
||||
"status": {
|
||||
"parent": "items",
|
||||
"nested": true,
|
||||
},
|
||||
"batch_code": {
|
||||
"parent": "items",
|
||||
"nested": true,
|
||||
},
|
||||
"barcode": {
|
||||
"parent": "items",
|
||||
"nested": true,
|
||||
"type": "barcode",
|
||||
"label": L10().barcodeAssign,
|
||||
"value": barcode,
|
||||
"required": false,
|
||||
}
|
||||
};
|
||||
|
||||
if (destination != null && destination > 0) {
|
||||
fields["location"]?["value"] = destination;
|
||||
}
|
||||
|
||||
InvenTreePurchaseOrder? order = purchaseOrder;
|
||||
|
||||
if (order != null) {
|
||||
await launchApiForm(
|
||||
context,
|
||||
L10().receiveItem,
|
||||
order.receive_url,
|
||||
fields,
|
||||
method: "POST",
|
||||
icon: TablerIcons.transition_right,
|
||||
onSuccess: (data) {
|
||||
if (onSuccess != null) {
|
||||
onSuccess();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -24,8 +24,7 @@ class InvenTreeSalesOrder extends InvenTreeOrder {
|
||||
@override
|
||||
String get URL => "order/so/";
|
||||
|
||||
@override
|
||||
String get MODEL_TYPE => "salesorder";
|
||||
static const String MODEL_TYPE = "salesorder";
|
||||
|
||||
@override
|
||||
List<String> get rolesRequired => ["sales_order"];
|
||||
@ -250,6 +249,8 @@ class InvenTreeSalesOrderShipment extends InvenTreeModel {
|
||||
@override
|
||||
String get URL => "/order/so/shipment/";
|
||||
|
||||
static const String MODEL_TYPE = "salesordershipment";
|
||||
|
||||
@override
|
||||
Map<String, Map<String, dynamic>> formFields() {
|
||||
Map<String, Map<String, dynamic>> fields = {
|
||||
|
@ -158,6 +158,11 @@ Future<bool> sentryReportMessage(String message, {Map<String, String>? context})
|
||||
*/
|
||||
Future<void> sentryReportError(String source, dynamic error, StackTrace? stackTrace, {Map<String, String> context = const {}}) async {
|
||||
|
||||
if (sentryIgnoreError(error)) {
|
||||
// No action on this error
|
||||
return;
|
||||
}
|
||||
|
||||
print("----- Sentry Intercepted error: $error -----");
|
||||
print(stackTrace);
|
||||
|
||||
@ -228,3 +233,18 @@ Future<void> sentryReportError(String source, dynamic error, StackTrace? stackTr
|
||||
print("Uploaded information to Sentry.io : ${response.toString()}");
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Test if a certain error should be ignored by Sentry
|
||||
*/
|
||||
bool sentryIgnoreError(dynamic error) {
|
||||
// Ignore 404 errors for media files
|
||||
if (error is HttpException) {
|
||||
if (error.uri.toString().contains("/media/") && error.message.contains("404")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
@ -98,7 +98,7 @@ class InvenTreeStockItemHistory extends InvenTreeModel {
|
||||
String get URL => "stock/track/";
|
||||
|
||||
@override
|
||||
Map<String, String> defaultListFilters() {
|
||||
Map<String, String> defaultFilters() {
|
||||
|
||||
// By default, order by decreasing date
|
||||
return {
|
||||
@ -168,8 +168,7 @@ class InvenTreeStockItem extends InvenTreeModel {
|
||||
@override
|
||||
String get URL => "stock/";
|
||||
|
||||
@override
|
||||
String get MODEL_TYPE => "stockitem";
|
||||
static const String MODEL_TYPE = "stockitem";
|
||||
|
||||
@override
|
||||
List<String> get rolesRequired => ["stock"];
|
||||
@ -206,7 +205,7 @@ class InvenTreeStockItem extends InvenTreeModel {
|
||||
|
||||
if (isSerialized()) {
|
||||
// Prevent editing of 'quantity' field if the item is serialized
|
||||
fields["quantity"]["hidden"] = true;
|
||||
fields["quantity"]?["hidden"] = true;
|
||||
}
|
||||
|
||||
// Old API does not support these fields
|
||||
@ -395,7 +394,7 @@ class InvenTreeStockItem extends InvenTreeModel {
|
||||
|
||||
// Use the detailed part information as priority
|
||||
if (jsondata.containsKey("part_detail")) {
|
||||
nm = (jsondata["part_detail"]["full_name"] ?? "") as String;
|
||||
nm = (jsondata["part_detail"]?["full_name"] ?? "") as String;
|
||||
}
|
||||
|
||||
// Backup if first value fails
|
||||
@ -411,7 +410,7 @@ class InvenTreeStockItem extends InvenTreeModel {
|
||||
|
||||
// Use the detailed part description as priority
|
||||
if (jsondata.containsKey("part_detail")) {
|
||||
desc = (jsondata["part_detail"]["description"] ?? "") as String;
|
||||
desc = (jsondata["part_detail"]?["description"] ?? "") as String;
|
||||
}
|
||||
|
||||
if (desc.isEmpty) {
|
||||
@ -425,7 +424,7 @@ class InvenTreeStockItem extends InvenTreeModel {
|
||||
String img = "";
|
||||
|
||||
if (jsondata.containsKey("part_detail")) {
|
||||
img = (jsondata["part_detail"]["thumbnail"] ?? "") as String;
|
||||
img = (jsondata["part_detail"]?["thumbnail"] ?? "") as String;
|
||||
}
|
||||
|
||||
if (img.isEmpty) {
|
||||
@ -468,7 +467,7 @@ class InvenTreeStockItem extends InvenTreeModel {
|
||||
if (jsondata.containsKey("supplier_part_detail")) {
|
||||
thumb = (jsondata["supplier_part_detail"]?["supplier_detail"]?["image"] ?? "") as String;
|
||||
} else if (jsondata.containsKey("supplier_detail")) {
|
||||
thumb = (jsondata["supplier_detail"]["image"] ?? "") as String;
|
||||
thumb = (jsondata["supplier_detail"]?["image"] ?? "") as String;
|
||||
}
|
||||
|
||||
return thumb;
|
||||
@ -681,8 +680,7 @@ class InvenTreeStockLocation extends InvenTreeModel {
|
||||
@override
|
||||
String get URL => "stock/location/";
|
||||
|
||||
@override
|
||||
String get MODEL_TYPE => "stocklocation";
|
||||
static const String MODEL_TYPE = "stocklocation";
|
||||
|
||||
@override
|
||||
List<String> get rolesRequired => ["stock_location"];
|
||||
|
Reference in New Issue
Block a user