From 4bbd66c4d5b1b6e9be460029598125e0e519e2f1 Mon Sep 17 00:00:00 2001 From: Marvin M <39344769+M123-dev@users.noreply.github.com> Date: Sun, 19 Dec 2021 15:07:46 +0100 Subject: [PATCH] Fix: Added missing product fields to ProductField enum (#331) * fix: Added missing arguments to ProductField * Update Product.dart * Added tests * fix: #328 type product_quantity --- lib/model/Product.dart | 32 +++++++++++++++++++----- lib/model/Product.g.dart | 6 ++++- lib/utils/JsonHelper.dart | 4 +-- lib/utils/ProductFields.dart | 14 +++++++++++ test/api_getProduct_test.dart | 47 +++++++++++++++++++++++++++++++++++ 5 files changed, 94 insertions(+), 9 deletions(-) diff --git a/lib/model/Product.dart b/lib/model/Product.dart index e99ccad08a..0cc0370bdf 100644 --- a/lib/model/Product.dart +++ b/lib/model/Product.dart @@ -1,10 +1,13 @@ +import 'dart:convert'; + import 'package:json_annotation/json_annotation.dart'; -import 'package:openfoodfacts/model/AttributeGroup.dart'; import 'package:openfoodfacts/model/Attribute.dart'; +import 'package:openfoodfacts/model/AttributeGroup.dart'; import 'package:openfoodfacts/model/ProductImage.dart'; import 'package:openfoodfacts/utils/JsonHelper.dart'; import 'package:openfoodfacts/utils/LanguageHelper.dart'; import 'package:openfoodfacts/utils/ProductFields.dart'; + import '../interface/JsonObject.dart'; import 'Additives.dart'; import 'Allergens.dart'; @@ -102,6 +105,11 @@ class Product extends JsonObject { includeIfNull: false) Map? productNameInLanguages; + ///Common name + ///Example: Chocolate bar with milk and hazelnuts + @JsonKey(name: 'generic_name', includeIfNull: false) + String? genericName; + @JsonKey(name: 'brands', includeIfNull: false) String? brands; @JsonKey(name: 'brands_tags', includeIfNull: false) @@ -156,13 +164,20 @@ class Product extends JsonObject { @JsonKey(name: 'serving_size', includeIfNull: false) String? servingSize; + @JsonKey( - name: 'serving_quantity', - fromJson: JsonHelper.servingQuantityFromJson, - includeIfNull: false) + name: 'serving_quantity', + fromJson: JsonHelper.quantityFromJson, + includeIfNull: false, + ) double? servingQuantity; - @JsonKey(name: 'product_quantity', includeIfNull: false) - dynamic packagingQuantity; + + @JsonKey( + name: 'product_quantity', + fromJson: JsonHelper.quantityFromJson, + includeIfNull: false, + ) + double? packagingQuantity; /// cause nesting is sooo cool ;) @JsonKey( @@ -292,6 +307,9 @@ class Product extends JsonObject { @JsonKey(name: 'stores_tags', includeIfNull: false) List? storesTags; + @JsonKey(name: 'stores', includeIfNull: false) + String? stores; + @JsonKey( name: 'attribute_groups', includeIfNull: false, @@ -322,6 +340,7 @@ class Product extends JsonObject { {this.barcode, this.productName, this.productNameInLanguages, + this.genericName, this.brands, this.brandsTags, this.countries, @@ -369,6 +388,7 @@ class Product extends JsonObject { this.statesTags, this.tracesTags, this.storesTags, + this.stores, this.attributeGroups, this.lastModified, this.ecoscoreGrade, diff --git a/lib/model/Product.g.dart b/lib/model/Product.g.dart index ca4c8b9f43..63a73f54aa 100644 --- a/lib/model/Product.g.dart +++ b/lib/model/Product.g.dart @@ -11,6 +11,7 @@ Product _$ProductFromJson(Map json) => Product( productName: json['product_name'] as String?, productNameInLanguages: LanguageHelper.fromJsonStringMap(json['product_name_in_languages']), + genericName: json['generic_name'] as String?, brands: json['brands'] as String?, brandsTags: (json['brands_tags'] as List?) ?.map((e) => e as String) @@ -90,6 +91,7 @@ Product _$ProductFromJson(Map json) => Product( storesTags: (json['stores_tags'] as List?) ?.map((e) => e as String) .toList(), + stores: json['stores'] as String?, attributeGroups: (json['attribute_groups'] as List?) ?.map((e) => AttributeGroup.fromJson(e)) .toList(), @@ -124,6 +126,7 @@ Map _$ProductToJson(Product instance) { writeNotNull('product_name', instance.productName); writeNotNull('product_name_in_languages', LanguageHelper.toJsonStringMap(instance.productNameInLanguages)); + writeNotNull('generic_name', instance.genericName); writeNotNull('brands', instance.brands); writeNotNull('brands_tags', instance.brandsTags); writeNotNull('countries', instance.countries); @@ -143,7 +146,7 @@ Map _$ProductToJson(Product instance) { writeNotNull('image_packaging_url', instance.imagePackagingUrl); writeNotNull('image_packaging_small_url', instance.imagePackagingSmallUrl); writeNotNull('serving_size', instance.servingSize); - writeNotNull('serving_quantity', instance.servingQuantity); + writeNotNull('serving_quantity', jsonEncode(instance.servingQuantity)); writeNotNull('product_quantity', instance.packagingQuantity); writeNotNull('selected_images', JsonHelper.selectedImagesToJson(instance.selectedImages)); @@ -185,6 +188,7 @@ Map _$ProductToJson(Product instance) { writeNotNull('states_tags', instance.statesTags); writeNotNull('traces_tags', instance.tracesTags); writeNotNull('stores_tags', instance.storesTags); + writeNotNull('stores', instance.stores); writeNotNull('attribute_groups', JsonHelper.attributeGroupsToJson(instance.attributeGroups)); writeNotNull( diff --git a/lib/utils/JsonHelper.dart b/lib/utils/JsonHelper.dart index 8240a88cdb..9769843cd1 100644 --- a/lib/utils/JsonHelper.dart +++ b/lib/utils/JsonHelper.dart @@ -1,8 +1,8 @@ import 'package:openfoodfacts/interface/JsonObject.dart'; import 'package:openfoodfacts/model/AttributeGroup.dart'; -import 'package:openfoodfacts/utils/LanguageHelper.dart'; import 'package:openfoodfacts/model/Ingredient.dart'; import 'package:openfoodfacts/model/ProductImage.dart'; +import 'package:openfoodfacts/utils/LanguageHelper.dart'; /// Helper class around product field conversion to/from JSON class JsonHelper { @@ -127,7 +127,7 @@ class JsonHelper { } /// Returns a double from a JSON-encoded int or double - static double? servingQuantityFromJson(dynamic data) { + static double? quantityFromJson(dynamic data) { if (data == null || data is double) { return data; } diff --git a/lib/utils/ProductFields.dart b/lib/utils/ProductFields.dart index e5a5d61d5e..2b5ec79c73 100644 --- a/lib/utils/ProductFields.dart +++ b/lib/utils/ProductFields.dart @@ -15,6 +15,7 @@ enum ProductField { LANGUAGE, QUANTITY, SERVING_SIZE, + SERVING_QUANTITY, PACKAGING_QUANTITY, FRONT_IMAGE, SELECTED_IMAGE, @@ -43,15 +44,21 @@ enum ProductField { CATEGORIES, CATEGORIES_TAGS, CATEGORIES_TAGS_IN_LANGUAGES, + LABELS, LABELS_TAGS, LABELS_TAGS_IN_LANGUAGES, + PACKAGING, + PACKAGING_TAGS, MISC_TAGS, STATES_TAGS, TRACES_TAGS, + STORES_TAGS, + STORES, INGREDIENTS_ANALYSIS_TAGS, ALLERGENS, ENVIRONMENT_IMPACT_LEVELS, ATTRIBUTE_GROUPS, + LAST_MODIFIED, ECOSCORE_GRADE, ECOSCORE_SCORE, ECOSCORE_DATA, @@ -73,6 +80,7 @@ extension ProductFieldExtension on ProductField { ProductField.LANGUAGE: 'lang', ProductField.QUANTITY: 'quantity', ProductField.SERVING_SIZE: 'serving_size', + ProductField.SERVING_QUANTITY: 'serving_quantity', ProductField.PACKAGING_QUANTITY: 'product_quantity', ProductField.FRONT_IMAGE: 'image_small_url', ProductField.IMAGE_FRONT_URL: 'image_front_url', @@ -101,15 +109,21 @@ extension ProductFieldExtension on ProductField { ProductField.CATEGORIES: 'categories', ProductField.CATEGORIES_TAGS: 'categories_tags', ProductField.CATEGORIES_TAGS_IN_LANGUAGES: 'categories_tags_', + ProductField.LABELS: 'labels', ProductField.LABELS_TAGS: 'labels_tags', ProductField.LABELS_TAGS_IN_LANGUAGES: 'labels_tags_', + ProductField.PACKAGING: 'packaging', + ProductField.PACKAGING_TAGS: 'packaging_tags', ProductField.MISC_TAGS: 'misc', ProductField.STATES_TAGS: 'states_tags', ProductField.TRACES_TAGS: 'traces_tags', + ProductField.STORES_TAGS: 'stores_tags', + ProductField.STORES: 'stores', ProductField.INGREDIENTS_ANALYSIS_TAGS: 'ingredients_analysis_tags', ProductField.ALLERGENS: 'allergens_tags', ProductField.ENVIRONMENT_IMPACT_LEVELS: 'environment_impact_level_tags', ProductField.ATTRIBUTE_GROUPS: 'attribute_groups', + ProductField.LAST_MODIFIED: 'last_modified_t', ProductField.ECOSCORE_GRADE: 'ecoscore_grade', ProductField.ECOSCORE_SCORE: 'ecoscore_score', ProductField.ECOSCORE_DATA: 'ecoscore_data', diff --git a/test/api_getProduct_test.dart b/test/api_getProduct_test.dart index 2efc59872e..f474957de2 100644 --- a/test/api_getProduct_test.dart +++ b/test/api_getProduct_test.dart @@ -35,6 +35,7 @@ void main() { Product product = Product( barcode: barcode, productName: 'Coca Cola Light', + genericName: 'Softdrink', lang: OpenFoodFactsLanguage.GERMAN, countries: 'Frankreich,Deutschland', brands: 'Coca Cola', @@ -77,6 +78,8 @@ void main() { expect(result.product!.barcode, barcode); expect(result.product!.lastModified != null, true); + expect(result.product!.genericName, 'Softdrink'); + // only german ingredients expect(result.product!.ingredientsText != null, true); @@ -1647,4 +1650,48 @@ void main() { 'de-es.openfoodfacts.net', ); }); + + test('get minified product', () async { + String barcode = '111111555555'; + + //First add the product to the Test DB + Product product = Product( + barcode: barcode, + lang: OpenFoodFactsLanguage.GERMAN, + genericName: 'Softdrink', + labels: 'MyTestLabel', + packaging: 'de:In einer Plastikflasche', + quantity: '5.5 Liter', + ); + + await OpenFoodAPIClient.saveProduct( + TestConstants.TEST_USER, + product, + ); + + ProductQueryConfiguration configurations = ProductQueryConfiguration( + barcode, + language: OpenFoodFactsLanguage.GERMAN, + fields: [ + ProductField.GENERIC_NAME, + ProductField.LABELS, + ProductField.PACKAGING, + ProductField.PACKAGING_TAGS, + ProductField.QUANTITY, + ], + ); + + ProductResult result = await OpenFoodAPIClient.getProduct( + configurations, + user: TestConstants.TEST_USER, + ); + + expect(result.status, 1); + expect(result.product?.barcode, null); + expect(result.product?.genericName, 'Softdrink'); + expect(result.product?.labels, 'MyTestLabel'); + expect(result.product?.packaging, 'de:In einer Plastikflasche'); + expect(result.product?.packagingTags, ['de-in-einer-plastikflasche']); + expect(result.product?.quantity, '5.5 Liter'); + }); }