From c1152ee2868db506fc9cd486abb0e0ae630b75bd Mon Sep 17 00:00:00 2001 From: Oliver Date: Tue, 28 Sep 2021 17:53:14 +1000 Subject: [PATCH] Fixes for type casting --- analysis_options.yaml | 15 +++++++ lib/api.dart | 51 +++++++++++++++++----- lib/api_form.dart | 63 ++++++++++++++-------------- lib/app_settings.dart | 11 +++++ lib/barcode.dart | 64 ++++++++++++++-------------- lib/inventree/company.dart | 32 +++++++------- lib/inventree/model.dart | 50 +++++++++++----------- lib/inventree/part.dart | 32 +++++++------- lib/inventree/purchase_order.dart | 52 +++++++++++------------ lib/inventree/stock.dart | 70 +++++++++++++++---------------- lib/preferences.dart | 2 +- lib/settings/app_settings.dart | 8 ++-- lib/settings/login.dart | 11 ----- lib/user_profile.dart | 26 ++++++------ lib/widget/category_display.dart | 13 ++++-- lib/widget/location_display.dart | 13 ++++-- lib/widget/part_detail.dart | 5 ++- lib/widget/stock_detail.dart | 4 +- 18 files changed, 294 insertions(+), 228 deletions(-) diff --git a/analysis_options.yaml b/analysis_options.yaml index f177c41e..2ea080d3 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -1,8 +1,23 @@ include: package:lint/analysis_options.yaml +analyzer: + exclude: [build/**] + language: + strict-raw-types: true + strong-mode: + implicit-casts: false + linter: rules: # ------ Disable individual rules ----- # # --- # # Turn off what you don't like. # # ------------------------------------- # + + # Make constructors the first thing in every class + sort_constructors_first: true + + prefer_single_quotes: true + + # Blindly follow the Flutter code style, which prefers types everywhere + always_specify_types: true diff --git a/lib/api.dart b/lib/api.dart index 56709d4c..acd02f51 100644 --- a/lib/api.dart +++ b/lib/api.dart @@ -51,6 +51,31 @@ class APIResponse { bool clientError() => (statusCode >= 400) && (statusCode < 500); bool serverError() => (statusCode >= 500); + + bool isMap() { + return data != null && data is Map; + } + + Map asMap() { + if (isMap()) { + return data as Map; + } else { + // Empty map + return {}; + } + } + + bool isList() { + return data != null && data is List; + } + + List asList() { + if (isList()) { + return data as List; + } else { + return []; + } + } } @@ -268,8 +293,10 @@ class InvenTreeAPI { return false; } + var data = response.asMap(); + // We expect certain response from the server - if (response.data == null || !response.data.containsKey("server") || !response.data.containsKey("version") || !response.data.containsKey("instance")) { + if (!data.containsKey("server") || !data.containsKey("version") || !data.containsKey("instance")) { showServerError( L10().missingData, @@ -280,11 +307,11 @@ class InvenTreeAPI { } // Record server information - _version = response.data["version"]; - instance = response.data['instance'] ?? ''; + _version = (data["version"] ?? '') as String; + instance = (data['instance'] ?? '') as String; // Default API version is 1 if not provided - _apiVersion = (response.data['apiVersion'] ?? 1) as int; + _apiVersion = (data['apiVersion'] ?? 1) as int; if (_apiVersion < _minApiVersion) { @@ -333,7 +360,9 @@ class InvenTreeAPI { return false; } - if (response.data == null || !response.data.containsKey("token")) { + data = response.asMap(); + + if (!data.containsKey("token")) { showServerError( L10().tokenMissing, L10().tokenMissingFromResponse, @@ -343,7 +372,7 @@ class InvenTreeAPI { } // Return the received token - _token = response.data["token"]; + _token = (data["token"] ?? "") as String; print("Received token - $_token"); // Request user role information @@ -415,9 +444,11 @@ class InvenTreeAPI { return; } - if (response.data.containsKey('roles')) { + var data = response.asMap(); + + if (data.containsKey('roles')) { // Save a local copy of the user roles - roles = response.data['roles']; + roles = response.data['roles'] as Map; } } @@ -438,7 +469,7 @@ class InvenTreeAPI { } try { - List perms = List.from(roles[role]); + List perms = List.from(roles[role] as List); return perms.contains(permission); } catch (error, stackTrace) { sentryReportError(error, stackTrace); @@ -551,7 +582,7 @@ class InvenTreeAPI { showServerError(L10().connectionRefused, error.toString()); } on TimeoutException { showTimeoutError(); - } catch (error, stackTrace) { + } catch (error) { print("Error downloading image:"); print(error.toString()); showServerError(L10().downloadError, error.toString()); diff --git a/lib/api_form.dart b/lib/api_form.dart index 4b496fe9..1b8b472b 100644 --- a/lib/api_form.dart +++ b/lib/api_form.dart @@ -36,15 +36,15 @@ class APIFormField { final String name; // JSON data which defines the field - final dynamic data; + final Map data; dynamic initial_data; // Get the "api_url" associated with a related field - String get api_url => data["api_url"] ?? ""; + String get api_url => (data["api_url"] ?? '') as String; // Get the "model" associated with a related field - String get model => data["model"] ?? ""; + String get model => (data["model"] ?? '') as String; // Is this field hidden? bool get hidden => (data['hidden'] ?? false) as bool; @@ -71,7 +71,7 @@ class APIFormField { if (f is Map) { f.forEach((key, value) { - _filters[key] = value.toString(); + _filters[key as String] = value.toString(); }); } } @@ -83,7 +83,7 @@ class APIFormField { if (f is Map) { f.forEach((key, value) { - _filters[key] = value.toString(); + _filters[key as String] = value.toString(); }); } } @@ -96,7 +96,7 @@ class APIFormField { // Return the error message associated with this field List errorMessages() { - List errors = data['errors'] ?? []; + List errors = (data['errors'] ?? []) as List; List messages = []; @@ -118,7 +118,7 @@ class APIFormField { String get placeholderText => (data['placeholder'] ?? '').toString(); - List get choices => data["choices"] ?? []; + List get choices => (data["choices"] ?? []) as List; Future loadInitialData() async { @@ -193,7 +193,7 @@ class APIFormField { labelText: label, labelStyle: _labelStyle(), ), - initialValue: DateTime.tryParse(value ?? ""), + initialValue: DateTime.tryParse((value ?? '') as String), autovalidateMode: AutovalidateMode.always, validator: (e) { // TODO @@ -267,7 +267,7 @@ class APIFormField { autoFocusSearchBox: true, showClearButton: !required, itemAsString: (dynamic item) { - return item['display_name']; + return (item['display_name'] ?? '') as String; }, onSaved: (item) { if (item == null) { @@ -349,13 +349,16 @@ class APIFormField { onChanged: null, showClearButton: !required, itemAsString: (dynamic item) { + + Map data = item as Map; + switch (model) { case "part": - return InvenTreePart.fromJson(item).fullname; + return InvenTreePart.fromJson(data).fullname; case "partcategory": - return InvenTreePartCategory.fromJson(item).pathstring; + return InvenTreePartCategory.fromJson(data).pathstring; case "stocklocation": - return InvenTreeStockLocation.fromJson(item).pathstring; + return InvenTreeStockLocation.fromJson(data).pathstring; default: return "itemAsString not implemented for '${model}'"; } @@ -391,19 +394,13 @@ class APIFormField { Widget _renderRelatedField(dynamic item, bool selected, bool extended) { // Render a "related field" based on the "model" type - if (item == null) { - return Text( - helpText, - style: TextStyle( - fontStyle: FontStyle.italic - ), - ); - } + // Convert to JSON + Map data = item as Map; switch (model) { case "part": - var part = InvenTreePart.fromJson(item); + var part = InvenTreePart.fromJson(data); return ListTile( title: Text( @@ -419,7 +416,7 @@ class APIFormField { case "partcategory": - var cat = InvenTreePartCategory.fromJson(item); + var cat = InvenTreePartCategory.fromJson(data); return ListTile( title: Text( @@ -433,7 +430,7 @@ class APIFormField { ); case "stocklocation": - var loc = InvenTreeStockLocation.fromJson(item); + var loc = InvenTreeStockLocation.fromJson(data); return ListTile( title: Text( @@ -446,7 +443,7 @@ class APIFormField { ) : null, ); case "owner": - String name = item["name"] ?? ""; + String name = (item["name"] ?? '') as String; bool isGroup = (item["label"] ?? "") == "group"; return ListTile( title: Text(name), @@ -481,7 +478,7 @@ class APIFormField { readOnly: readOnly, maxLines: multiline ? null : 1, expands: false, - initialValue: value ?? '', + initialValue: (value ?? '') as String, onSaved: (val) { data["value"] = val; }, @@ -501,7 +498,7 @@ class APIFormField { labelStyle: _labelStyle(), helperText: helpText, helperStyle: _helperStyle(), - initial: value, + initial: value as bool, onSaved: (val) { data['value'] = val; }, @@ -537,13 +534,17 @@ Map extractFields(APIResponse response) { return {}; } - if (!response.data.containsKey("actions")) { + var data = response.asMap(); + + if (!data.containsKey("actions")) { return {}; } - var actions = response.data["actions"]; + var actions = response.data["actions"] as Map; - return actions["POST"] ?? actions["PUT"] ?? actions["PATCH"] ?? {}; + dynamic result = actions["POST"] ?? actions["PUT"] ?? actions["PATCH"] ?? {}; + + return result as Map; } /* @@ -599,8 +600,8 @@ Future launchApiForm(BuildContext context, String title, String url, Map remoteField = (availableFields[fieldName] ?? {}) as Map; + Map localField = (fields[fieldName] ?? {}) as Map; // Override defined field parameters, if provided for (String key in localField.keys) { diff --git a/lib/app_settings.dart b/lib/app_settings.dart index 7146b91b..5946249a 100644 --- a/lib/app_settings.dart +++ b/lib/app_settings.dart @@ -22,6 +22,17 @@ class InvenTreeSettingsManager { return value; } + // Load a boolean setting + Future getBool(String key, bool backup) async { + final dynamic value = await getValue(key, backup); + + if (value is bool) { + return value; + } else { + return backup; + } + } + Future setValue(String key, dynamic value) async { await store.record(key).put(await _db, value); diff --git a/lib/barcode.dart b/lib/barcode.dart index de3af32b..60be2aaa 100644 --- a/lib/barcode.dart +++ b/lib/barcode.dart @@ -101,8 +101,10 @@ class BarcodeHandler { _controller?.resumeCamera(); + Map data = response.asMap(); + // Handle strange response from the server - if (!response.isValid() || response.data == null || !(response.data is Map)) { + if (!response.isValid() || !response.isMap()) { onBarcodeUnknown(context, {}); // We want to know about this one! @@ -118,12 +120,12 @@ class BarcodeHandler { "errorDetail": response.errorDetail, } ); - } else if (response.data.containsKey('error')) { - onBarcodeUnknown(context, response.data); - } else if (response.data.containsKey('success')) { - onBarcodeMatched(context, response.data); + } else if (data.containsKey('error')) { + onBarcodeUnknown(context, data); + } else if (data.containsKey('success')) { + onBarcodeMatched(context, data); } else { - onBarcodeUnhandled(context, response.data); + onBarcodeUnhandled(context, data); } } } @@ -294,35 +296,35 @@ class StockItemBarcodeAssignmentHandler extends BarcodeHandler { L10().barcodeMissingHash, ); } else { + String hash = (data['hash'] ?? '') as String; - // Send the 'hash' code as the UID for the stock item - item.update( - values: { - "uid": data['hash'], - } - ).then((result) { - if (result) { + if (hash.isNotEmpty) { + item.update( + values: { + "uid": hash, + } + ).then((result) { + if (result) { + failureTone(); - failureTone(); + Navigator.of(context).pop(); - Navigator.of(context).pop(); + showSnackIcon( + L10().barcodeAssigned, + success: true, + icon: FontAwesomeIcons.qrcode + ); + } else { + successTone(); - showSnackIcon( - L10().barcodeAssigned, - success: true, - icon: FontAwesomeIcons.qrcode - ); - } else { - - successTone(); - - showSnackIcon( - L10().barcodeNotAssigned, - success: false, - icon: FontAwesomeIcons.qrcode - ); - } - }); + showSnackIcon( + L10().barcodeNotAssigned, + success: false, + icon: FontAwesomeIcons.qrcode + ); + } + }); + } } } } diff --git a/lib/inventree/company.dart b/lib/inventree/company.dart index 920aaa65..363c5d8b 100644 --- a/lib/inventree/company.dart +++ b/lib/inventree/company.dart @@ -27,21 +27,21 @@ class InvenTreeCompany extends InvenTreeModel { InvenTreeCompany() : super(); - String get image => jsondata['image'] ?? jsondata['thumbnail'] ?? InvenTreeAPI.staticImage; + String get image => (jsondata['image'] ?? jsondata['thumbnail'] ?? InvenTreeAPI.staticImage) as String; - String get thumbnail => jsondata['thumbnail'] ?? jsondata['image'] ?? InvenTreeAPI.staticThumb; + String get thumbnail => (jsondata['thumbnail'] ?? jsondata['image'] ?? InvenTreeAPI.staticThumb) as String; - String get website => jsondata['website'] ?? ''; + String get website => (jsondata['website'] ?? '') as String; - String get phone => jsondata['phone'] ?? ''; + String get phone => (jsondata['phone'] ?? '') as String; - String get email => jsondata['email'] ?? ''; + String get email => (jsondata['email'] ?? '') as String; - bool get isSupplier => jsondata['is_supplier'] ?? false; + bool get isSupplier => (jsondata['is_supplier'] ?? false) as bool; - bool get isManufacturer => jsondata['is_manufacturer'] ?? false; + bool get isManufacturer => (jsondata['is_manufacturer'] ?? false) as bool; - bool get isCustomer => jsondata['is_customer'] ?? false; + bool get isCustomer => (jsondata['is_customer'] ?? false) as bool; InvenTreeCompany.fromJson(Map json) : super.fromJson(json); @@ -85,27 +85,27 @@ class InvenTreeSupplierPart extends InvenTreeModel { int get manufacturerId => (jsondata['manufacturer'] ?? -1) as int; - String get manufacturerName => jsondata['manufacturer_detail']['name']; + String get manufacturerName => (jsondata['manufacturer_detail']['name'] ?? '') as String; - String get manufacturerImage => jsondata['manufacturer_detail']['image'] ?? jsondata['manufacturer_detail']['thumbnail']; + String get manufacturerImage => (jsondata['manufacturer_detail']['image'] ?? jsondata['manufacturer_detail']['thumbnail'] ?? InvenTreeAPI.staticThumb) as String; int get manufacturerPartId => (jsondata['manufacturer_part'] ?? -1) as int; int get supplierId => (jsondata['supplier'] ?? -1) as int; - String get supplierName => jsondata['supplier_detail']['name']; + String get supplierName => (jsondata['supplier_detail']['name'] ?? '') as String; - String get supplierImage => jsondata['supplier_detail']['image'] ?? jsondata['supplier_detail']['thumbnail']; + String get supplierImage => (jsondata['supplier_detail']['image'] ?? jsondata['supplier_detail']['thumbnail'] ?? InvenTreeAPI.staticThumb) as String; String get SKU => (jsondata['SKU'] ?? '') as String; - String get MPN => jsondata['MPN'] ?? ''; + String get MPN => (jsondata['MPN'] ?? '') as String; - int get partId => jsondata['part'] ?? -1; + int get partId => (jsondata['part'] ?? -1) as int; - String get partImage => jsondata["part_detail"]["thumbnail"] ?? InvenTreeAPI.staticThumb; + String get partImage => (jsondata["part_detail"]["thumbnail"] ?? InvenTreeAPI.staticThumb) as String; - String get partName => jsondata["part_detail"]["full_name"] ?? ""; + String get partName => (jsondata["part_detail"]["full_name"] ?? '') as String; @override InvenTreeModel createFromJson(Map json) { diff --git a/lib/inventree/model.dart b/lib/inventree/model.dart index 50ec330f..0b9abc02 100644 --- a/lib/inventree/model.dart +++ b/lib/inventree/model.dart @@ -132,16 +132,16 @@ class InvenTreeModel { int get pk => (jsondata['pk'] ?? -1) as int; // Some common accessors - String get name => jsondata['name'] ?? ''; + String get name => (jsondata['name'] ?? '') as String; - String get description => jsondata['description'] ?? ''; + String get description => (jsondata['description'] ?? '') as String; - String get notes => jsondata['notes'] ?? ''; + String get notes => (jsondata['notes'] ?? '') as String; int get parentId => (jsondata['parent'] ?? -1) as int; // Legacy API provided external link as "URL", while newer API uses "link" - String get link => jsondata['link'] ?? jsondata['URL'] ?? ''; + String get link => (jsondata['link'] ?? jsondata['URL'] ?? '') as String; void goToInvenTreePage() async { @@ -162,7 +162,7 @@ class InvenTreeModel { } } - String get keywords => jsondata['keywords'] ?? ''; + String get keywords => (jsondata['keywords'] ?? '') as String; // Create a new object from JSON data (not a constructor!) InvenTreeModel createFromJson(Map json) { @@ -224,7 +224,7 @@ class InvenTreeModel { } - jsondata = response.data; + jsondata = response.asMap(); return true; } @@ -297,13 +297,11 @@ class InvenTreeModel { } - return createFromJson(response.data); + return createFromJson(response.asMap()); } Future create(Map data) async { - print("CREATE: ${URL} ${data.toString()}"); - if (data.containsKey('pk')) { data.remove('pk'); } @@ -340,7 +338,7 @@ class InvenTreeModel { return null; } - return createFromJson(response.data); + return createFromJson(response.asMap()); } Future listPaginated(int limit, int offset, {Map filters = const {}}) async { @@ -362,13 +360,15 @@ class InvenTreeModel { // Construct the response InvenTreePageResponse page = new InvenTreePageResponse(); - if (response.data.containsKey("count") && response.data.containsKey("results")) { - page.count = response.data["count"] as int; + var data = response.asMap(); + + if (data.containsKey("count") && data.containsKey("results")) { + page.count = (data["count"] ?? 0) as int; page.results = []; for (var result in response.data["results"]) { - page.addResult(createFromJson(result)); + page.addResult(createFromJson(result as Map)); } return page; @@ -396,20 +396,22 @@ class InvenTreeModel { return results; } - dynamic data; + List data = []; - if (response.data is List) { - data = response.data; - } else if (response.data.containsKey('results')) { - data = response.data['results']; - } else { - data = []; + if (response.isList()) { + data = response.asList(); + } else if (response.isMap()) { + var mData = response.asMap(); + + if (mData.containsKey('results')) { + data = (response.data['results'] ?? []) as List; + } } for (var d in data) { // Create a new object (of the current class type - InvenTreeModel obj = createFromJson(d); + InvenTreeModel obj = createFromJson(d as Map); results.add(obj); } @@ -460,7 +462,7 @@ class InvenTreeAttachment extends InvenTreeModel { InvenTreeAttachment() : super(); - String get attachment => jsondata["attachment"] ?? ''; + String get attachment => (jsondata["attachment"] ?? '') as String; // Return the filename of the attachment String get filename { @@ -498,11 +500,11 @@ class InvenTreeAttachment extends InvenTreeModel { return FontAwesomeIcons.fileAlt; } - String get comment => jsondata["comment"] ?? ''; + String get comment => (jsondata["comment"] ?? '') as String; DateTime? get uploadDate { if (jsondata.containsKey("upload_date")) { - return DateTime.tryParse(jsondata["upload_date"] ?? ''); + return DateTime.tryParse((jsondata["upload_date"] ?? '') as String); } else { return null; } diff --git a/lib/inventree/part.dart b/lib/inventree/part.dart index 13f7911a..237695ba 100644 --- a/lib/inventree/part.dart +++ b/lib/inventree/part.dart @@ -33,7 +33,7 @@ class InvenTreePartCategory extends InvenTreeModel { return filters; } - String get pathstring => jsondata['pathstring'] ?? ''; + String get pathstring => (jsondata['pathstring'] ?? '') as String; String get parentpathstring { // TODO - Drive the refactor tractor through this @@ -52,7 +52,7 @@ class InvenTreePartCategory extends InvenTreeModel { return p; } - int get partcount => jsondata['parts'] ?? 0; + int get partcount => (jsondata['parts'] ?? 0) as int; InvenTreePartCategory() : super(); @@ -74,17 +74,17 @@ class InvenTreePartTestTemplate extends InvenTreeModel { @override String get URL => "part/test-template/"; - String get key => jsondata['key'] ?? ''; + String get key => (jsondata['key'] ?? '') as String; - String get testName => jsondata['test_name'] ?? ''; + String get testName => (jsondata['test_name'] ?? '') as String; - String get description => jsondata['description'] ?? ''; + String get description => (jsondata['description'] ?? '') as String; - bool get required => jsondata['required'] ?? false; + bool get required => (jsondata['required'] ?? false) as bool; - bool get requiresValue => jsondata['requires_value'] ?? false; + bool get requiresValue => (jsondata['requires_value'] ?? false) as bool; - bool get requiresAttachment => jsondata['requires_attachment'] ?? false; + bool get requiresAttachment => (jsondata['requires_attachment'] ?? false) as bool; InvenTreePartTestTemplate() : super(); @@ -271,7 +271,7 @@ class InvenTreePart extends InvenTreeModel { return q; } - String get units => jsondata["units"] ?? ""; + String get units => (jsondata["units"] as String) ?? ""; // Get the number of units being build for this Part double get building => double.tryParse(jsondata['building'].toString()) ?? 0; @@ -297,10 +297,10 @@ class InvenTreePart extends InvenTreeModel { bool get isTrackable => (jsondata['trackable'] ?? false) as bool; // Get the IPN (internal part number) for the Part instance - String get IPN => jsondata['IPN'] ?? ''; + String get IPN => (jsondata['IPN'] ?? '') as String; // Get the revision string for the Part instance - String get revision => jsondata['revision'] ?? ''; + String get revision => (jsondata['revision'] ?? '') as String; // Get the category ID for the Part instance (or 'null' if does not exist) int get categoryId => (jsondata['category'] ?? -1) as int; @@ -312,7 +312,7 @@ class InvenTreePart extends InvenTreeModel { if (!jsondata.containsKey('category_detail')) return ''; - return jsondata['category_detail']?['name'] ?? ''; + return (jsondata['category_detail']?['name'] ?? '') as String; } // Get the category description for the Part instance @@ -322,18 +322,18 @@ class InvenTreePart extends InvenTreeModel { if (!jsondata.containsKey('category_detail')) return ''; - return jsondata['category_detail']?['description'] ?? ''; + return (jsondata['category_detail']?['description'] ?? '') as String; } // Get the image URL for the Part instance - String get _image => jsondata['image'] ?? ''; + String get _image => (jsondata['image'] ?? '') as String; // Get the thumbnail URL for the Part instance - String get _thumbnail => jsondata['thumbnail'] ?? ''; + String get _thumbnail => (jsondata['thumbnail'] ?? '') as String; // Return the fully-qualified name for the Part instance String get fullname { - String fn = jsondata['full_name'] ?? ''; + String fn = (jsondata['full_name'] ?? '') as String; if (fn.isNotEmpty) return fn; diff --git a/lib/inventree/purchase_order.dart b/lib/inventree/purchase_order.dart index 3b279485..d5c02eef 100644 --- a/lib/inventree/purchase_order.dart +++ b/lib/inventree/purchase_order.dart @@ -44,23 +44,23 @@ class InvenTreePurchaseOrder extends InvenTreeModel { }; } - String get issueDate => jsondata['issue_date'] ?? ""; + String get issueDate => (jsondata['issue_date'] ?? '') as String; - String get completeDate => jsondata['complete_date'] ?? ""; + String get completeDate => (jsondata['complete_date'] ?? '') as String; - String get creationDate => jsondata['creation_date'] ?? ""; + String get creationDate => (jsondata['creation_date'] ?? '') as String; - String get targetDate => jsondata['target_date'] ?? ""; + String get targetDate => (jsondata['target_date'] ?? '') as String; - int get lineItemCount => jsondata['line_items'] ?? 0; + int get lineItemCount => (jsondata['line_items'] ?? 0) as int; - bool get overdue => jsondata['overdue'] ?? false; + bool get overdue => (jsondata['overdue'] ?? false) as bool; - String get reference => jsondata['reference'] ?? ""; + String get reference => (jsondata['reference'] ?? '') as String; - int get responsible => jsondata['responsible'] ?? -1; + int get responsibleId => (jsondata['responsible'] ?? -1) as int; - int get supplierId => jsondata['supplier'] ?? -1; + int get supplierId => (jsondata['supplier'] ?? -1) as int; InvenTreeCompany? get supplier { @@ -69,15 +69,15 @@ class InvenTreePurchaseOrder extends InvenTreeModel { if (supplier_detail == null) { return null; } else { - return InvenTreeCompany.fromJson(supplier_detail); + return InvenTreeCompany.fromJson(supplier_detail as Map); } } - String get supplierReference => jsondata['supplier_reference'] ?? ""; + String get supplierReference => (jsondata['supplier_reference'] ?? '') as String; - int get status => jsondata['status'] ?? -1; + int get status => (jsondata['status'] ?? -1) as int; - String get statusText => jsondata['status_text'] ?? ""; + String get statusText => (jsondata['status_text'] ?? '') as String; bool get isOpen => this.status == PO_STATUS_PENDING || this.status == PO_STATUS_PLACED; @@ -146,25 +146,25 @@ class InvenTreePOLineItem extends InvenTreeModel { bool get isComplete => received >= quantity; - double get quantity => jsondata['quantity'] ?? 0; + double get quantity => (jsondata['quantity'] ?? 0) as double; - double get received => jsondata['received'] ?? 0; + double get received => (jsondata['received'] ?? 0) as double; double get outstanding => quantity - received; - String get reference => jsondata['reference'] ?? ""; + String get reference => (jsondata['reference'] ?? '') as String; - int get orderId => jsondata['order'] ?? -1; + int get orderId => (jsondata['order'] ?? -1) as int; - int get supplirtPartId => jsondata['part'] ?? -1; + int get supplierPartId => (jsondata['part'] ?? -1) as int; InvenTreePart? get part { - dynamic part_detail = jsondata["part_detail"] ?? null; + dynamic part_detail = jsondata["part_detail"]; if (part_detail == null) { return null; } else { - return InvenTreePart.fromJson(part_detail); + return InvenTreePart.fromJson(part_detail as Map); } } @@ -175,19 +175,19 @@ class InvenTreePOLineItem extends InvenTreeModel { if (detail == null) { return null; } else { - return InvenTreeSupplierPart.fromJson(detail); + return InvenTreeSupplierPart.fromJson(detail as Map); } } - double get purchasePrice => double.parse(jsondata['purchase_price']); + double get purchasePrice => double.parse((jsondata['purchase_price'] ?? '') as String); - String get purchasePriceCurrency => jsondata['purchase_price_currency'] ?? ""; + String get purchasePriceCurrency => (jsondata['purchase_price_currency'] ?? '') as String; - String get purchasePriceString => jsondata['purchase_price_string'] ?? ""; + String get purchasePriceString => (jsondata['purchase_price_string'] ?? '') as String; - int get destination => jsondata['destination'] ?? -1; + int get destination => (jsondata['destination'] ?? -1) as int; - Map get destinationDetail => jsondata['destination_detail']; + Map get destinationDetail => (jsondata['destination_detail'] ?? {}) as Map; InvenTreePOLineItem() : super(); diff --git a/lib/inventree/stock.dart b/lib/inventree/stock.dart index ad743f8f..56b54d73 100644 --- a/lib/inventree/stock.dart +++ b/lib/inventree/stock.dart @@ -31,19 +31,19 @@ class InvenTreeStockItemTestResult extends InvenTreeModel { }; } - String get key => jsondata['key'] ?? ''; + String get key => (jsondata['key'] ?? '') as String; - String get testName => jsondata['test'] ?? ''; + String get testName => (jsondata['test'] ?? '') as String; - bool get result => jsondata['result'] ?? false; + bool get result => (jsondata['result'] ?? false) as bool; - String get value => jsondata['value'] ?? ''; + String get value => (jsondata['value'] ?? '') as String; - String get notes => jsondata['notes'] ?? ''; + String get notes => (jsondata['notes'] ?? '') as String; - String get attachment => jsondata['attachment'] ?? ''; + String get attachment => (jsondata['attachment'] ?? '') as String; - String get date => jsondata['date'] ?? ''; + String get date => (jsondata['date'] ?? '') as String; InvenTreeStockItemTestResult() : super(); @@ -204,17 +204,17 @@ class InvenTreeStockItem extends InvenTreeModel { }); } - String get uid => jsondata['uid'] ?? ''; + String get uid => (jsondata['uid'] ?? '') as String; - int get status => jsondata['status'] ?? -1; + int get status => (jsondata['status'] ?? -1) as int; - String get packaging => jsondata["packaging"] ?? ""; + String get packaging => (jsondata["packaging"] ?? '') as String; - String get batch => jsondata["batch"] ?? ""; + String get batch => (jsondata["batch"] ?? '') as String; - int get partId => jsondata['part'] ?? -1; + int get partId => (jsondata['part'] ?? -1) as int; - String get purchasePrice => jsondata['purchase_price'] ?? ""; + String get purchasePrice => (jsondata['purchase_price'] ?? '') as String; bool get hasPurchasePrice { @@ -223,14 +223,14 @@ class InvenTreeStockItem extends InvenTreeModel { return pp.isNotEmpty && pp.trim() != "-"; } - int get purchaseOrderId => jsondata['purchase_order'] ?? -1; + int get purchaseOrderId => (jsondata['purchase_order'] ?? -1) as int; int get trackingItemCount => (jsondata['tracking_items'] ?? 0) as int; // Date of last update DateTime? get updatedDate { if (jsondata.containsKey("updated")) { - return DateTime.tryParse(jsondata["updated"] ?? ''); + return DateTime.tryParse((jsondata["updated"] ?? '') as String); } else { return null; } @@ -250,7 +250,7 @@ class InvenTreeStockItem extends InvenTreeModel { DateTime? get stocktakeDate { if (jsondata.containsKey("stocktake_date")) { - return DateTime.tryParse(jsondata["stocktake_date"] ?? ''); + return DateTime.tryParse((jsondata["stocktake_date"] ?? '') as String); } else { return null; } @@ -274,12 +274,12 @@ class InvenTreeStockItem extends InvenTreeModel { // Use the detailed part information as priority if (jsondata.containsKey('part_detail')) { - nm = jsondata['part_detail']['full_name'] ?? ''; + nm = (jsondata['part_detail']['full_name'] ?? '') as String; } // Backup if first value fails if (nm.isEmpty) { - nm = jsondata['part__name'] ?? ''; + nm = (jsondata['part__name'] ?? '') as String; } return nm; @@ -290,11 +290,11 @@ class InvenTreeStockItem extends InvenTreeModel { // Use the detailed part description as priority if (jsondata.containsKey('part_detail')) { - desc = jsondata['part_detail']['description'] ?? ''; + desc = (jsondata['part_detail']['description'] ?? '') as String; } if (desc.isEmpty) { - desc = jsondata['part__description'] ?? ''; + desc = (jsondata['part__description'] ?? '') as String; } return desc; @@ -304,11 +304,11 @@ class InvenTreeStockItem extends InvenTreeModel { String img = ''; if (jsondata.containsKey('part_detail')) { - img = jsondata['part_detail']['thumbnail'] ?? ''; + img = (jsondata['part_detail']['thumbnail'] ?? '') as String; } if (img.isEmpty) { - img = jsondata['part__thumbnail'] ?? ''; + img = (jsondata['part__thumbnail'] ?? '') as String; } return img; @@ -321,16 +321,16 @@ class InvenTreeStockItem extends InvenTreeModel { String thumb = ""; - thumb = jsondata['part_detail']?['thumbnail'] ?? ''; + thumb = (jsondata['part_detail']?['thumbnail'] ?? '') as String; // Use 'image' as a backup if (thumb.isEmpty) { - thumb = jsondata['part_detail']?['image'] ?? ''; + thumb = (jsondata['part_detail']?['image'] ?? '') as String; } // Try a different approach if (thumb.isEmpty) { - thumb = jsondata['part__thumbnail'] ?? ''; + thumb = (jsondata['part__thumbnail'] ?? '') as String; } // Still no thumbnail? Use the 'no image' image @@ -345,7 +345,7 @@ class InvenTreeStockItem extends InvenTreeModel { String thumb = ''; if (jsondata.containsKey("supplier_detail")) { - thumb = jsondata['supplier_detail']['supplier_logo'] ?? ''; + thumb = (jsondata['supplier_detail']['supplier_logo'] ?? '') as String; } return thumb; @@ -355,27 +355,27 @@ class InvenTreeStockItem extends InvenTreeModel { String sname = ''; if (jsondata.containsKey("supplier_detail")) { - sname = jsondata["supplier_detail"]["supplier_name"] ?? ''; + sname = (jsondata["supplier_detail"]["supplier_name"] ?? '') as String; } return sname; } String get units { - return jsondata['part_detail']?['units'] ?? ''; + return (jsondata['part_detail']?['units'] ?? '') as String; } String get supplierSKU { String sku = ''; if (jsondata.containsKey("supplier_detail")) { - sku = jsondata["supplier_detail"]["SKU"] ?? ''; + sku = (jsondata["supplier_detail"]["SKU"] ?? '') as String; } return sku; } - String get serialNumber => jsondata['serial'] ?? ""; + String get serialNumber => (jsondata['serial'] ?? '') as String; double get quantity => double.tryParse(jsondata['quantity'].toString()) ?? 0; @@ -417,11 +417,11 @@ class InvenTreeStockItem extends InvenTreeModel { if (locationId == -1 || !jsondata.containsKey('location_detail')) return 'Unknown Location'; - loc = jsondata['location_detail']['name'] ?? ''; + loc = (jsondata['location_detail']['name'] ?? '') as String; // Old-style name if (loc.isEmpty) { - loc = jsondata['location__name'] ?? ''; + loc = (jsondata['location__name'] ?? '') as String; } return loc; @@ -431,7 +431,7 @@ class InvenTreeStockItem extends InvenTreeModel { if (locationId == -1 || !jsondata.containsKey('location_detail')) return L10().locationNotSet; - String _loc = jsondata['location_detail']['pathstring'] ?? ''; + String _loc = (jsondata['location_detail']['pathstring'] ?? '') as String; if (_loc.isNotEmpty) { return _loc; @@ -540,7 +540,7 @@ class InvenTreeStockLocation extends InvenTreeModel { @override String get URL => "stock/location/"; - String get pathstring => jsondata['pathstring'] ?? ''; + String get pathstring => (jsondata['pathstring'] ?? '') as String; @override Map formFields() { @@ -568,7 +568,7 @@ class InvenTreeStockLocation extends InvenTreeModel { return p; } - int get itemcount => jsondata['items'] ?? 0; + int get itemcount => (jsondata['items'] ?? 0) as int; InvenTreeStockLocation() : super(); diff --git a/lib/preferences.dart b/lib/preferences.dart index f6e2372f..645f614d 100644 --- a/lib/preferences.dart +++ b/lib/preferences.dart @@ -34,7 +34,7 @@ class InvenTreePreferencesDB { return _dbOpenCompleter.future; } - Future _openDatabase() async { + Future _openDatabase() async { // Get a platform-specific directory where persistent app data can be stored final appDocumentDir = await getApplicationDocumentsDirectory(); diff --git a/lib/settings/app_settings.dart b/lib/settings/app_settings.dart index 0f0938b9..bf175452 100644 --- a/lib/settings/app_settings.dart +++ b/lib/settings/app_settings.dart @@ -45,7 +45,7 @@ class _InvenTreeAppSettingsState extends State { void setBarcodeSounds(bool en) async { await InvenTreeSettingsManager().setValue("barcodeSounds", en); - barcodeSounds = await InvenTreeSettingsManager().getValue("barcodeSounds", true); + barcodeSounds = await InvenTreeSettingsManager().getBool("barcodeSounds", true); setState(() { }); @@ -54,7 +54,7 @@ class _InvenTreeAppSettingsState extends State { void setServerSounds(bool en) async { await InvenTreeSettingsManager().setValue("serverSounds", en); - serverSounds = await InvenTreeSettingsManager().getValue("serverSounds", true); + serverSounds = await InvenTreeSettingsManager().getBool("serverSounds", true); setState(() { }); @@ -62,7 +62,7 @@ class _InvenTreeAppSettingsState extends State { void setPartSubcategory(bool en) async { await InvenTreeSettingsManager().setValue("partSubcategory", en); - partSubcategory = await InvenTreeSettingsManager().getValue("partSubcategory", true); + partSubcategory = await InvenTreeSettingsManager().getBool("partSubcategory", true); setState(() { }); @@ -70,7 +70,7 @@ class _InvenTreeAppSettingsState extends State { void setStockSublocation(bool en) async { await InvenTreeSettingsManager().setValue("stockSublocation", en); - stockSublocation = await InvenTreeSettingsManager().getValue("stockSublocation", true); + stockSublocation = await InvenTreeSettingsManager().getBool("stockSublocation", true); setState(() { }); diff --git a/lib/settings/login.dart b/lib/settings/login.dart index 3bacea7f..7edf6fa0 100644 --- a/lib/settings/login.dart +++ b/lib/settings/login.dart @@ -40,17 +40,6 @@ class _InvenTreeLoginSettingsState extends State { void _editProfile(BuildContext context, {UserProfile? userProfile, bool createNew = false}) { - var _name; - var _server; - var _username; - var _password; - - UserProfile? profile; - - if (userProfile != null) { - profile = userProfile; - } - Navigator.push( context, MaterialPageRoute( diff --git a/lib/user_profile.dart b/lib/user_profile.dart index 3b6bf8f2..b0efd89a 100644 --- a/lib/user_profile.dart +++ b/lib/user_profile.dart @@ -38,10 +38,10 @@ class UserProfile { factory UserProfile.fromJson(int key, Map json, bool isSelected) => UserProfile( key: key, - name: json['name'], - server: json['server'], - username: json['username'], - password: json['password'], + name: json['name'] as String, + server: json['server'] as String, + username: json['username'] as String, + password: json['password'] as String, selected: isSelected, ); @@ -73,7 +73,7 @@ class UserProfileDBManager { return profiles.length > 0; } - Future addProfile(UserProfile profile) async { + Future addProfile(UserProfile profile) async { // Check if a profile already exists with the name final bool exists = await profileNameExists(profile.name); @@ -83,7 +83,7 @@ class UserProfileDBManager { return; } - int key = await store.add(await _db, profile.toJson()); + int key = await store.add(await _db, profile.toJson()) as int; print("Added user profile <${key}> - '${profile.name}'"); @@ -91,7 +91,7 @@ class UserProfileDBManager { profile.key = key; } - Future selectProfile(int key) async { + Future selectProfile(int key) async { /* * Mark the particular profile as selected */ @@ -101,7 +101,7 @@ class UserProfileDBManager { return result; } - Future updateProfile(UserProfile profile) async { + Future updateProfile(UserProfile profile) async { if (profile.key == null) { await addProfile(profile); @@ -115,7 +115,7 @@ class UserProfileDBManager { return result; } - Future deleteProfile(UserProfile profile) async { + Future deleteProfile(UserProfile profile) async { await store.record(profile.key).delete(await _db); print("Deleted user profile <${profile.key}> - '${profile.name}'"); } @@ -135,8 +135,8 @@ class UserProfileDBManager { if (profiles[idx].key is int && profiles[idx].key == selected) { return UserProfile.fromJson( - profiles[idx].key, - profiles[idx].value, + profiles[idx].key as int, + profiles[idx].value as Map, profiles[idx].key == selected, ); } @@ -161,8 +161,8 @@ class UserProfileDBManager { if (profiles[idx].key is int) { profileList.add( UserProfile.fromJson( - profiles[idx].key, - profiles[idx].value, + profiles[idx].key as int, + profiles[idx].value as Map, profiles[idx].key == selected, )); } diff --git a/lib/widget/category_display.dart b/lib/widget/category_display.dart index ea4e2e30..b0faa09a 100644 --- a/lib/widget/category_display.dart +++ b/lib/widget/category_display.dart @@ -224,8 +224,10 @@ class _CategoryDisplayState extends RefreshableState { data: { "parent": (pk > 0) ? pk : null, }, - onSuccess: (data) async { - + onSuccess: (result) async { + + Map data = result as Map; + if (data.containsKey("pk")) { var cat = InvenTreePartCategory.fromJson(data); @@ -252,7 +254,9 @@ class _CategoryDisplayState extends RefreshableState { data: { "category": (pk > 0) ? pk : null }, - onSuccess: (data) async { + onSuccess: (result) async { + + Map data = result as Map; if (data.containsKey("pk")) { var part = InvenTreePart.fromJson(data); @@ -440,7 +444,8 @@ class _PaginatedPartListState extends State { params["search"] = _searchTerm; - final bool cascade = await InvenTreeSettingsManager().getValue("partSubcategory", true); + final bool cascade = await InvenTreeSettingsManager().getBool("partSubcategory", true); + params["cascade"] = "${cascade}"; final page = await InvenTreePart().listPaginated(_pageSize, pageKey, filters: params); diff --git a/lib/widget/location_display.dart b/lib/widget/location_display.dart index 26e8f3b6..16d9a9a8 100644 --- a/lib/widget/location_display.dart +++ b/lib/widget/location_display.dart @@ -146,7 +146,10 @@ class _LocationDisplayState extends RefreshableState { data: { "parent": (pk > 0) ? pk : null, }, - onSuccess: (data) async { + onSuccess: (result) async { + + Map data = result as Map; + if (data.containsKey("pk")) { var loc = InvenTreeStockLocation.fromJson(data); @@ -175,7 +178,10 @@ class _LocationDisplayState extends RefreshableState { data: { "location": pk, }, - onSuccess: (data) async { + onSuccess: (result) async { + + Map data = result as Map; + if (data.containsKey("pk")) { var item = InvenTreeStockItem.fromJson(data); @@ -515,7 +521,8 @@ class _PaginatedStockListState extends State { params["search"] = "${_searchTerm}"; // Do we include stock items from sub-locations? - final bool cascade = await InvenTreeSettingsManager().getValue("stockSublocation", true); + final bool cascade = await InvenTreeSettingsManager().getBool("stockSublocation", true); + params["cascade"] = "${cascade}"; final page = await InvenTreeStockItem().listPaginated(_pageSize, pageKey, filters: params); diff --git a/lib/widget/part_detail.dart b/lib/widget/part_detail.dart index 5d52736e..778a8d70 100644 --- a/lib/widget/part_detail.dart +++ b/lib/widget/part_detail.dart @@ -405,7 +405,10 @@ class _PartDisplayState extends RefreshableState { data: { "part": "${part.pk}", }, - onSuccess: (data) async { + onSuccess: (result) async { + + Map data = result as Map; + if (data.containsKey("pk")) { var item = InvenTreeStockItem.fromJson(data); diff --git a/lib/widget/stock_detail.dart b/lib/widget/stock_detail.dart index 862d9628..343013df 100644 --- a/lib/widget/stock_detail.dart +++ b/lib/widget/stock_detail.dart @@ -349,13 +349,13 @@ class _StockItemDisplayState extends RefreshableState { hint: L10().searchLocation, onChanged: null, itemAsString: (dynamic location) { - return location['pathstring']; + return (location['pathstring'] ?? '') as String; }, onSaved: (dynamic location) { if (location == null) { location_pk = null; } else { - location_pk = location['pk']; + location_pk = location['pk'] as int; } }, isFilteredOnline: true,