diff --git a/docs/api/ref/schemas/product_ingredients.yaml b/docs/api/ref/schemas/product_ingredients.yaml index b885d5a69e945..b3705886a54e6 100644 --- a/docs/api/ref/schemas/product_ingredients.yaml +++ b/docs/api/ref/schemas/product_ingredients.yaml @@ -70,6 +70,13 @@ properties: type: array items: type: string + ingredients_lc: + type: string + description: | + Language that was used to parse the ingredient list. If `ingredients_text` is available + for the product main language (`lang`), `ingredients_lc=lang`, otherwise we look at + `ingredients_text` fields for other languages and set `ingredients_lc` to the first + non-empty `ingredient_text`. ingredients_text: type: string description: | diff --git a/docs/dev/how-to-write-and-run-tests.md b/docs/dev/how-to-write-and-run-tests.md index db70aed63cded..136e93f19eebf 100644 --- a/docs/dev/how-to-write-and-run-tests.md +++ b/docs/dev/how-to-write-and-run-tests.md @@ -88,7 +88,7 @@ If you made change that impact stored expected results, you can use: * or to generate expected results for a single test (here for integration test, `test-unit` otherwise) ```bash - make test-int="filename.t --update-expected results" + make test-int test="filename.t --update-expected-results" ``` If you re-generate test results, be sure to look carefully that the changes your commit are expected changes. diff --git a/lib/ProductOpener/APITest.pm b/lib/ProductOpener/APITest.pm index b282a7870753e..33891f20ccbaf 100644 --- a/lib/ProductOpener/APITest.pm +++ b/lib/ProductOpener/APITest.pm @@ -515,7 +515,7 @@ sub execute_api_tests ($file, $tests_ref, $ua = undef) { my $response_content = $response->decoded_content; - if ($test_ref->{expected_type} eq 'text') { + if ((defined $test_ref->{expected_type}) and ($test_ref->{expected_type} eq 'text')) { # Check that the text file is the same as expected (useful for checking dynamic robots.txt) is( compare_file_to_expected_results( diff --git a/lib/ProductOpener/Display.pm b/lib/ProductOpener/Display.pm index 06cc5d1a7988a..3533145ecaa7e 100644 --- a/lib/ProductOpener/Display.pm +++ b/lib/ProductOpener/Display.pm @@ -7838,7 +7838,7 @@ JS # try to display ingredients in the local language if available my $ingredients_text = $product_ref->{ingredients_text}; - my $ingredients_text_lang = $product_ref->{lc}; + my $ingredients_text_lang = $product_ref->{ingredients_lc}; if (defined $product_ref->{ingredients_text_with_allergens}) { $ingredients_text = $product_ref->{ingredients_text_with_allergens}; @@ -11049,7 +11049,8 @@ sub data_to_display_ingredients_analysis_details ($product_ref) { my $result_data_ref = {}; - my $ingredients_text = ""; + my $ingredients_text_lc = $product_ref->{ingredients_lc}; + my $ingredients_text = "$ingredients_text_lc: "; my $ingredients_list = ""; display_nested_list_of_ingredients($product_ref->{ingredients}, \$ingredients_text, \$ingredients_list); diff --git a/lib/ProductOpener/Ingredients.pm b/lib/ProductOpener/Ingredients.pm index 103f4b59a95aa..5c979559a52da 100644 --- a/lib/ProductOpener/Ingredients.pm +++ b/lib/ProductOpener/Ingredients.pm @@ -63,6 +63,7 @@ BEGIN { &clean_ingredients_text_for_lang &cut_ingredients_text_for_lang &clean_ingredients_text + &select_ingredients_lc &detect_allergens_from_text @@ -860,7 +861,7 @@ Array of specific ingredients. sub add_specific_ingredients_from_labels ($product_ref) { - my $product_lc = $product_ref->{lc}; + my $ingredients_lc = $product_ref->{ingredients_lc} || $product_ref->{lc}; if (defined $product_ref->{labels_tags}) { foreach my $labelid (@{$product_ref->{labels_tags}}) { @@ -920,7 +921,7 @@ Array of specific ingredients. sub parse_specific_ingredients_from_text ($product_ref, $text, $percent_or_quantity_regexp) { - my $product_lc = $product_ref->{lc}; + my $ingredients_lc = $product_ref->{ingredients_lc} || $product_ref->{lc}; # Go through the ingredient lists multiple times # as long as we have one match @@ -940,7 +941,7 @@ sub parse_specific_ingredients_from_text ($product_ref, $text, $percent_or_quant # Regexps should match until we reach a . ; or the end of the text - if ($product_lc eq "en") { + if ($ingredients_lc eq "en") { # examples: # Total Milk Content 73%. @@ -961,7 +962,7 @@ sub parse_specific_ingredients_from_text ($product_ref, $text, $percent_or_quant } # Origin of the milk: United Kingdom - elsif (match_origin_of_the_ingredient_origin($product_lc, \$text, $matched_ingredient_ref)) { + elsif (match_origin_of_the_ingredient_origin($ingredients_lc, \$text, $matched_ingredient_ref)) { $origins = $matched_ingredient_ref->{origins}; $ingredient = $matched_ingredient_ref->{ingredient}; $matched_text = $matched_ingredient_ref->{matched_text}; @@ -969,7 +970,7 @@ sub parse_specific_ingredients_from_text ($product_ref, $text, $percent_or_quant $ingredient =~ s/\s+$//; } } - elsif ($product_lc eq "fr") { + elsif ($ingredients_lc eq "fr") { # examples: # Teneur en lait 25% minimum. @@ -1011,7 +1012,7 @@ sub parse_specific_ingredients_from_text ($product_ref, $text, $percent_or_quant } # Origine du Cacao: Pérou - elsif (match_origin_of_the_ingredient_origin($product_lc, \$text, $matched_ingredient_ref)) { + elsif (match_origin_of_the_ingredient_origin($ingredients_lc, \$text, $matched_ingredient_ref)) { $origins = $matched_ingredient_ref->{origins}; $ingredient = $matched_ingredient_ref->{ingredient}; $matched_text = $matched_ingredient_ref->{matched_text}; @@ -1024,7 +1025,8 @@ sub parse_specific_ingredients_from_text ($product_ref, $text, $percent_or_quant # If we found an ingredient, save it in specific_ingredients if (defined $ingredient) { my $ingredient_id - = get_taxonomyid($product_lc, canonicalize_taxonomy_tag($product_lc, "ingredients", $ingredient)); + = get_taxonomyid($ingredients_lc, + canonicalize_taxonomy_tag($ingredients_lc, "ingredients", $ingredient)); $matched_text =~ s/^\s+//; @@ -1049,11 +1051,12 @@ sub parse_specific_ingredients_from_text ($product_ref, $text, $percent_or_quant # Add origin field - my $and_or = $and_or{$product_lc}; + my $and_or = $and_or{$ingredients_lc}; defined $origins and $specific_ingredients_ref->{origins} - = join(",", map {canonicalize_taxonomy_tag($product_lc, "origins", $_)} split(/,|$and_or/, $origins)); + = join(",", + map {canonicalize_taxonomy_tag($ingredients_lc, "origins", $_)} split(/,|$and_or/, $origins)); push @{$product_ref->{specific_ingredients}}, $specific_ingredients_ref; } @@ -1067,11 +1070,11 @@ sub parse_specific_ingredients_from_text ($product_ref, $text, $percent_or_quant # Regexps should match until we reach a . ; or the end of the text -sub match_ingredient_origin ($product_lc, $text_ref, $matched_ingredient_ref) { +sub match_ingredient_origin ($ingredients_lc, $text_ref, $matched_ingredient_ref) { - my $origins_regexp = $origins_regexps{$product_lc}; - my $and_or = $and_or{$product_lc} || ','; - my $from = $from{$product_lc} || ':'; + my $origins_regexp = $origins_regexps{$ingredients_lc}; + my $and_or = $and_or{$ingredients_lc} || ','; + my $from = $from{$ingredients_lc} || ':'; # Strawberries: Spain, Italy and Portugal # Strawberries from Spain, Italy and Portugal @@ -1110,7 +1113,7 @@ sub match_ingredient_origin ($product_lc, $text_ref, $matched_ingredient_ref) { not( exists_taxonomy_tag( "ingredients", - canonicalize_taxonomy_tag($product_lc, "ingredients", $matched_ingredient_ref->{ingredient}) + canonicalize_taxonomy_tag($ingredients_lc, "ingredients", $matched_ingredient_ref->{ingredient}) ) ) ) @@ -1127,16 +1130,16 @@ sub match_ingredient_origin ($product_lc, $text_ref, $matched_ingredient_ref) { return 0; } -sub match_origin_of_the_ingredient_origin ($product_lc, $text_ref, $matched_ingredient_ref) { +sub match_origin_of_the_ingredient_origin ($ingredients_lc, $text_ref, $matched_ingredient_ref) { my %origin_of_the_regexp_in_lc = ( en => "(?:origin of (?:the )?)", fr => "(?:origine (?:de |du |de la |des |de l'))", ); - my $origin_of_the_regexp = $origin_of_the_regexp_in_lc{$product_lc} || $origin_of_the_regexp_in_lc{en}; - my $origins_regexp = $origins_regexps{$product_lc}; - my $and_or = $and_or{$product_lc} || ','; + my $origin_of_the_regexp = $origin_of_the_regexp_in_lc{$ingredients_lc} || $origin_of_the_regexp_in_lc{en}; + my $origins_regexp = $origins_regexps{$ingredients_lc}; + my $and_or = $and_or{$ingredients_lc} || ','; # Origin of the milk: United Kingdom. if ( @@ -1190,7 +1193,7 @@ Array of specific ingredients. sub parse_origins_from_text ($product_ref, $text) { - my $product_lc = $product_ref->{lc}; + my $ingredients_lc = $product_ref->{ingredients_lc} || $product_ref->{lc}; # Normalize single quotes $text =~ s/’/'/g; @@ -1209,12 +1212,13 @@ sub parse_origins_from_text ($product_ref, $text) { # Call match functions to look for different ways to specify origins etc. foreach my $match_function_ref (\&match_origin_of_the_ingredient_origin, \&match_ingredient_origin) { - if ($match_function_ref->($product_lc, \$text, $matched_ingredient_ref)) { + if ($match_function_ref->($ingredients_lc, \$text, $matched_ingredient_ref)) { my $matched_text = $matched_ingredient_ref->{matched_text}; my $ingredient = $matched_ingredient_ref->{ingredient}; my $ingredient_id - = get_taxonomyid($product_lc, canonicalize_taxonomy_tag($product_lc, "ingredients", $ingredient)); + = get_taxonomyid($ingredients_lc, + canonicalize_taxonomy_tag($ingredients_lc, "ingredients", $ingredient)); # Remove extra spaces $ingredient =~ s/\s+$//; @@ -1227,9 +1231,9 @@ sub parse_origins_from_text ($product_ref, $text) { }; if (defined $matched_ingredient_ref->{origins}) { - my $and_or = $and_or{$product_lc}; + my $and_or = $and_or{$ingredients_lc}; $specific_ingredients_ref->{origins} = join(",", - map {canonicalize_taxonomy_tag($product_lc, "origins", $_)} + map {canonicalize_taxonomy_tag($ingredients_lc, "origins", $_)} split(/,|$and_or/, $matched_ingredient_ref->{origins})); } @@ -1244,6 +1248,34 @@ sub parse_origins_from_text ($product_ref, $text) { return $text; } +=head2 select_ingredients_lc ($product_ref) + +Return the `ingredients_lc` field to save in $product_ref. + +This is the language that will be used to parse ingredients. We first check that ingredients_text_{lang} +exists and is non-empty for the product main language (`lc`), and return it if it does. +Otherwise we look at all languages defined in `languages_codes` for a non-empty `ingredients_text_lang`. + +=head3 Arguments + +=head4 $product_ref + +=cut + +sub select_ingredients_lc ($product_ref) { + if (defined $product_ref->{languages_codes}) { + # We sort the keys so that the order is deterministic + foreach my $language ($product_ref->{lc}, sort keys %{$product_ref->{languages_codes}}) { + if ( (defined $product_ref->{"ingredients_text_" . $language}) + and ($product_ref->{"ingredients_text_" . $language} ne "")) + { + return $language; + } + } + } + return $product_ref->{lc}; +} + =head2 get_percent_or_quantity_and_normalized_quantity($percent_or_quantity_value, $percent_or_quantity_unit) Used to assign percent or quantity for strings parsed with $percent_or_quantity_regexp. @@ -1322,9 +1354,10 @@ sub parse_ingredients_text ($product_ref) { $log->debug("extracting ingredients from text", {text => $text}) if $log->is_debug(); - my $product_lc = $product_ref->{lc}; + # $product_ref->{ingredients_lc} is defined in extract_ingredients_from_text() + my $ingredients_lc = $product_ref->{ingredients_lc} || $product_ref->{lc}; - $text = preparse_ingredients_text($product_lc, $text); + $text = preparse_ingredients_text($ingredients_lc, $text); $log->debug("preparsed ingredients from text", {text => $text}) if $log->is_debug(); @@ -1332,8 +1365,8 @@ sub parse_ingredients_text ($product_ref) { # jus de pomme, eau, sucre. Traces possibles de c\x{e9}leri, moutarde et gluten.", # -> jus de pomme, eau, sucre. Traces éventuelles : céleri, Traces éventuelles : moutarde, Traces éventuelles : gluten. - my $traces = $Lang{traces}{$product_lc}; - my $allergens = $Lang{allergens}{$product_lc}; + my $traces = $Lang{traces}{$ingredients_lc}; + my $allergens = $Lang{allergens}{$ingredients_lc}; $text =~ s/\b($traces|$allergens)\s?:\s?([^,\.]+)//ig; # unify newline feeds to \n @@ -1354,15 +1387,15 @@ sub parse_ingredients_text ($product_ref) { $text =~ s/(\d),(\d)/$1‚$2/g; - my $and = $and{$product_lc} || " and "; + my $and = $and{$ingredients_lc} || " and "; my $min_regexp = ""; - if (defined $min_regexp{$product_lc}) { - $min_regexp = $min_regexp{$product_lc}; + if (defined $min_regexp{$ingredients_lc}) { + $min_regexp = $min_regexp{$ingredients_lc}; } my $ignore_strings_after_percent = ""; - if (defined $ignore_strings_after_percent{$product_lc}) { - $ignore_strings_after_percent = $ignore_strings_after_percent{$product_lc}; + if (defined $ignore_strings_after_percent{$ingredients_lc}) { + $ignore_strings_after_percent = $ignore_strings_after_percent{$ingredients_lc}; } # Regular expression to find percent or quantities @@ -1479,7 +1512,7 @@ sub parse_ingredients_text ($product_ref) { # sel marin (France, Italie) # -> if we have origins, put "origins:" before if ( ($between =~ $separators) - and (exists_taxonomy_tag("origins", canonicalize_taxonomy_tag($product_lc, "origins", $`)))) + and (exists_taxonomy_tag("origins", canonicalize_taxonomy_tag($ingredients_lc, "origins", $`)))) { $between =~ s/^(.*?$separators)/origins:$1/; } @@ -1542,14 +1575,14 @@ sub parse_ingredients_text ($product_ref) { } else { $origin = join(",", - map {canonicalize_taxonomy_tag($product_lc, "origins", $_)} + map {canonicalize_taxonomy_tag($ingredients_lc, "origins", $_)} split(/,/, $origin_string)); } } else { # origins: Fraise (France) - my $originid = canonicalize_taxonomy_tag($product_lc, "origins", $between); + my $originid = canonicalize_taxonomy_tag($ingredients_lc, "origins", $between); if (exists_taxonomy_tag("origins", $originid)) { $origin = $originid; $debug_ingredients @@ -1562,7 +1595,7 @@ sub parse_ingredients_text ($product_ref) { # Skip too short entries (1 or 2 letters) to avoid false positives elsif (length($between) >= 3) { - my $labelid = canonicalize_taxonomy_tag($product_lc, "labels", $between); + my $labelid = canonicalize_taxonomy_tag($ingredients_lc, "labels", $between); if (exists_taxonomy_tag("labels", $labelid)) { if (defined $labels) { $labels .= ", " . $labelid; @@ -1597,7 +1630,7 @@ sub parse_ingredients_text ($product_ref) { # processing method? my $processingid - = canonicalize_taxonomy_tag($product_lc, "ingredients_processing", + = canonicalize_taxonomy_tag($ingredients_lc, "ingredients_processing", $between); if (exists_taxonomy_tag("ingredients_processing", $processingid)) { if (defined $processing) { @@ -1681,7 +1714,7 @@ sub parse_ingredients_text ($product_ref) { $ingredient2 =~ s/\s$percent_or_quantity_regexp$//i; # check if the whole ingredient is an ingredient - my $canon_ingredient = canonicalize_taxonomy_tag($product_lc, "ingredients", $before); + my $canon_ingredient = canonicalize_taxonomy_tag($ingredients_lc, "ingredients", $before); $debug_ingredients and $log->debug( "ingredient contains 'and', checking if it exists", @@ -1691,8 +1724,8 @@ sub parse_ingredients_text ($product_ref) { if (not exists_taxonomy_tag("ingredients", $canon_ingredient)) { # otherwise check the 2 sub ingredients - my $canon_ingredient1 = canonicalize_taxonomy_tag($product_lc, "ingredients", $ingredient1); - my $canon_ingredient2 = canonicalize_taxonomy_tag($product_lc, "ingredients", $ingredient2); + my $canon_ingredient1 = canonicalize_taxonomy_tag($ingredients_lc, "ingredients", $ingredient1); + my $canon_ingredient2 = canonicalize_taxonomy_tag($ingredients_lc, "ingredients", $ingredient2); $debug_ingredients and $log->debug( "ingredient containing 'and' did not exist. 2 known ingredients?", @@ -1818,16 +1851,16 @@ sub parse_ingredients_text ($product_ref) { } else { $origin = join(",", - map {canonicalize_taxonomy_tag($product_lc, "origins", $_)} split(/,/, $origin_string)); + map {canonicalize_taxonomy_tag($ingredients_lc, "origins", $_)} split(/,/, $origin_string)); } } # Check if we have an ingredient + some specific labels like organic and fair-trade. # If we do, remove the label from the ingredient and add the label to labels - if (defined $labels_regexps{$product_lc}) { + if (defined $labels_regexps{$ingredients_lc}) { # start with uncomposed labels first, so that we decompose "fair-trade organic" into "fair-trade, organic" foreach my $labelid (reverse @labels) { - my $regexp = $labels_regexps{$product_lc}{$labelid}; + my $regexp = $labels_regexps{$ingredients_lc}{$labelid}; $debug_ingredients and $log->trace("checking labels regexps", {ingredient => $ingredient, labelid => $labelid, regexp => $regexp}) if $log->is_trace(); @@ -1857,7 +1890,7 @@ sub parse_ingredients_text ($product_ref) { $ingredient =~ s/^\s+//; $ingredient =~ s/\s+$//; - $ingredient_id = canonicalize_taxonomy_tag($product_lc, "ingredients", $ingredient); + $ingredient_id = canonicalize_taxonomy_tag($ingredients_lc, "ingredients", $ingredient); if (exists_taxonomy_tag("ingredients", $ingredient_id)) { $ingredient_recognized = 1; @@ -1875,22 +1908,22 @@ sub parse_ingredients_text ($product_ref) { my @maybe_origins_ingredients = (); # California almonds - if (($product_lc eq "en") and ($ingredient =~ /^(\S+) (.+)$/)) { + if (($ingredients_lc eq "en") and ($ingredient =~ /^(\S+) (.+)$/)) { push @maybe_origins_ingredients, [$1, $2]; } # South Carolina black olives - if (($product_lc eq "en") and ($ingredient =~ /^(\S+ \S+) (.+)$/)) { + if (($ingredients_lc eq "en") and ($ingredient =~ /^(\S+ \S+) (.+)$/)) { push @maybe_origins_ingredients, [$1, $2]; } - if (($product_lc eq "en") and ($ingredient =~ /^(\S+ \S+ \S+) (.+)$/)) { + if (($ingredients_lc eq "en") and ($ingredient =~ /^(\S+ \S+ \S+) (.+)$/)) { push @maybe_origins_ingredients, [$1, $2]; } # Currently does not work: pitted California prunes # Oranges from Florida - if (defined $from{$product_lc}) { - my $from = $from{$product_lc}; + if (defined $from{$ingredients_lc}) { + my $from = $from{$ingredients_lc}; if ($ingredient =~ /^(.+)($from)(.+)$/i) { push @maybe_origins_ingredients, [$3, $1]; } @@ -1903,7 +1936,7 @@ sub parse_ingredients_text ($product_ref) { # skip origins that are too small (avoid false positives with country initials etc.) next if (length($maybe_origin) < 4); - my $origin_id = canonicalize_taxonomy_tag($product_lc, "origins", $maybe_origin); + my $origin_id = canonicalize_taxonomy_tag($ingredients_lc, "origins", $maybe_origin); if ((exists_taxonomy_tag("origins", $origin_id)) and ($origin_id ne "en:unknown")) { $debug_ingredients and $log->debug( @@ -1917,21 +1950,21 @@ sub parse_ingredients_text ($product_ref) { $origin = $origin_id; $ingredient = $maybe_ingredient; - $ingredient_id = canonicalize_taxonomy_tag($product_lc, "ingredients", $ingredient); + $ingredient_id = canonicalize_taxonomy_tag($ingredients_lc, "ingredients", $ingredient); last; } } # Try to remove ingredients processing "cooked rice" -> "rice" - if (defined $ingredients_processing_regexps{$product_lc}) { + if (defined $ingredients_processing_regexps{$ingredients_lc}) { my $matches = 0; my $new_ingredient = $ingredient; my $new_processing = ''; my $matching = 1; # remove prefixes / suffixes one by one while ($matching) { $matching = 0; - foreach - my $ingredient_processing_regexp_ref (@{$ingredients_processing_regexps{$product_lc}}) + foreach my $ingredient_processing_regexp_ref ( + @{$ingredients_processing_regexps{$ingredients_lc}}) { my $regexp = $ingredient_processing_regexp_ref->[1]; $debug_ingredients and $log->trace("checking processing regexps", @@ -1941,22 +1974,22 @@ sub parse_ingredients_text ($product_ref) { if ( # match before or after the ingredient, require a space ( - #($product_lc =~ /^(en|es|it|fr)$/) + #($ingredients_lc =~ /^(en|es|it|fr)$/) ( - ($product_lc eq 'ar') - or ($product_lc eq 'bg') - or ($product_lc eq 'bs') - or ($product_lc eq 'cs') - or ($product_lc eq 'el') - or ($product_lc eq 'en') - or ($product_lc eq 'es') - or ($product_lc eq 'fr') - or ($product_lc eq 'hr') - or ($product_lc eq 'it') - or ($product_lc eq 'mk') - or ($product_lc eq 'pl') - or ($product_lc eq 'sl') - or ($product_lc eq 'sr') + ($ingredients_lc eq 'ar') + or ($ingredients_lc eq 'bg') + or ($ingredients_lc eq 'bs') + or ($ingredients_lc eq 'cs') + or ($ingredients_lc eq 'el') + or ($ingredients_lc eq 'en') + or ($ingredients_lc eq 'es') + or ($ingredients_lc eq 'fr') + or ($ingredients_lc eq 'hr') + or ($ingredients_lc eq 'it') + or ($ingredients_lc eq 'mk') + or ($ingredients_lc eq 'pl') + or ($ingredients_lc eq 'sl') + or ($ingredients_lc eq 'sr') ) and ($new_ingredient =~ /(^($regexp)\b|\b($regexp)$)/i) ) @@ -1964,10 +1997,10 @@ sub parse_ingredients_text ($product_ref) { # match before or after the ingredient, does not require a space or ( ( - ($product_lc eq 'de') - or ($product_lc eq 'hu') - or ($product_lc eq 'ja') - or ($product_lc eq 'nl') + ($ingredients_lc eq 'de') + or ($ingredients_lc eq 'hu') + or ($ingredients_lc eq 'ja') + or ($ingredients_lc eq 'nl') ) and ($new_ingredient =~ /(^($regexp)|($regexp)$)/i) ) @@ -1976,12 +2009,12 @@ sub parse_ingredients_text ($product_ref) { # match before the ingredient, require a space or ( ( - ($product_lc eq 'da') - or ($product_lc eq 'fi') - or ($product_lc eq 'nb') - or ($product_lc eq 'no') - or ($product_lc eq 'nn') - or ($product_lc eq 'sv') + ($ingredients_lc eq 'da') + or ($ingredients_lc eq 'fi') + or ($ingredients_lc eq 'nb') + or ($ingredients_lc eq 'no') + or ($ingredients_lc eq 'nn') + or ($ingredients_lc eq 'sv') ) and ($new_ingredient =~ /(^($regexp)\b|($regexp)$)/i) ) @@ -2013,7 +2046,7 @@ sub parse_ingredients_text ($product_ref) { # Stop if we now have a known ingredient. # e.g. "jambon cru en tranches" -> keep "jambon cru". my $new_ingredient_id - = canonicalize_taxonomy_tag($product_lc, "ingredients", $new_ingredient); + = canonicalize_taxonomy_tag($ingredients_lc, "ingredients", $new_ingredient); if (exists_taxonomy_tag("ingredients", $new_ingredient_id)) { $debug_ingredients and $log->debug( @@ -2035,7 +2068,7 @@ sub parse_ingredients_text ($product_ref) { if ($matches) { my $new_ingredient_id - = canonicalize_taxonomy_tag($product_lc, "ingredients", $new_ingredient); + = canonicalize_taxonomy_tag($ingredients_lc, "ingredients", $new_ingredient); if (exists_taxonomy_tag("ingredients", $new_ingredient_id)) { $debug_ingredients and $log->debug( "found existing ingredient after removing processing", @@ -2070,11 +2103,11 @@ sub parse_ingredients_text ($product_ref) { # We need to be careful with stopwords, "produit" was a stopword, # and "France" matched "produit de France" / made in France (bug #2927) - my $label_id = canonicalize_taxonomy_tag($product_lc, "labels", $ingredient); + my $label_id = canonicalize_taxonomy_tag($ingredients_lc, "labels", $ingredient); if (exists_taxonomy_tag("labels", $label_id)) { # Add the label to the product - add_tags_to_field($product_ref, $product_lc, "labels", $label_id); + add_tags_to_field($product_ref, $ingredients_lc, "labels", $label_id); $ingredient_recognized = 1; @@ -2268,8 +2301,8 @@ sub parse_ingredients_text ($product_ref) { ], ); - if (defined $ignore_regexps{$product_lc}) { - foreach my $regexp (@{$ignore_regexps{$product_lc}}) { + if (defined $ignore_regexps{$ingredients_lc}) { + foreach my $regexp (@{$ignore_regexps{$ingredients_lc}}) { if ($ingredient =~ /$regexp/i) { $debug_ingredients and $log->debug( @@ -2290,7 +2323,7 @@ sub parse_ingredients_text ($product_ref) { if (not $skip_ingredient) { my %ingredient = ( - id => get_taxonomyid($product_ref->{lc}, $ingredient_id), + id => get_taxonomyid($ingredients_lc, $ingredient_id), text => $ingredient ); @@ -2484,18 +2517,19 @@ sub compute_ingredients_tags ($product_ref) { my $field = "ingredients"; $product_ref->{ingredients_original_tags} = $product_ref->{ingredients_tags}; + my $ingredients_lc = $product_ref->{ingredients_lc} || $product_ref->{lc}; if (defined $taxonomy_fields{$field}) { $product_ref->{$field . "_hierarchy"} = [ gen_ingredients_tags_hierarchy_taxonomy( - $product_ref->{lc}, join(", ", @{$product_ref->{ingredients_original_tags}}) + $ingredients_lc, join(", ", @{$product_ref->{ingredients_original_tags}}) ) ]; $product_ref->{$field . "_tags"} = []; my $unknown = 0; my $known = 0; foreach my $tag (@{$product_ref->{$field . "_hierarchy"}}) { - my $tagid = get_taxonomyid($product_ref->{lc}, $tag); + my $tagid = get_taxonomyid($ingredients_lc, $tag); push @{$product_ref->{$field . "_tags"}}, $tagid; if (exists_taxonomy_tag("ingredients", $tagid)) { $known++; @@ -2551,11 +2585,12 @@ sub extract_ingredients_from_text ($product_ref) { $product_ref->{specific_ingredients} = []; + my $ingredients_lc = $product_ref->{ingredients_lc} || $product_ref->{lc}; + # Ingredients origins may be listed in the origin field # e.g. "Origin of the rice: Thailand." - my $product_lc = $product_ref->{lc}; - if (defined $product_ref->{"origin_" . $product_lc}) { - parse_origins_from_text($product_ref, $product_ref->{"origin_" . $product_lc}); + if (defined $product_ref->{"origin_" . $ingredients_lc}) { + parse_origins_from_text($product_ref, $product_ref->{"origin_" . $ingredients_lc}); } # Add specific ingredients from labels @@ -4416,7 +4451,6 @@ sub cut_ingredients_text_for_lang ($text, $language) { } sub clean_ingredients_text ($product_ref) { - if (defined $product_ref->{languages_codes}) { foreach my $language (keys %{$product_ref->{languages_codes}}) { @@ -4438,7 +4472,7 @@ sub clean_ingredients_text ($product_ref) { $product_ref->{"ingredients_text_" . $language} = $text; } - if ($language eq $product_ref->{lc}) { + if ($language eq ($product_ref->{ingredients_lc} || $product_ref->{lc})) { $product_ref->{"ingredients_text"} = $product_ref->{"ingredients_text_" . $language}; } } @@ -4462,9 +4496,9 @@ sub is_compound_word_with_dash ($word_lc, $compound_word) { # additive class + additive (e.g. "colour caramel" -> "colour : caramel" # warning: the additive class may also be the start of the name of an additive. # e.g. "regulatory kwasowości: kwas cytrynowy i cytryniany sodu." -> "kwas" means acid / acidifier. -sub separate_additive_class ($product_lc, $additive_class, $spaces, $colon, $after) { +sub separate_additive_class ($ingredients_lc, $additive_class, $spaces, $colon, $after) { - my $and = $and{$product_lc} || " and "; + my $and = $and{$ingredients_lc} || " and "; # check that we have an additive after the additive class # keep only what is before the first separator @@ -4485,13 +4519,13 @@ sub separate_additive_class ($product_lc, $additive_class, $spaces, $colon, $aft if ( ( not exists_taxonomy_tag( - "additives", canonicalize_taxonomy_tag($product_lc, "additives", $additive_class . " " . $after) + "additives", canonicalize_taxonomy_tag($ingredients_lc, "additives", $additive_class . " " . $after) ) ) and ( - exists_taxonomy_tag("additives", canonicalize_taxonomy_tag($product_lc, "additives", $after)) + exists_taxonomy_tag("additives", canonicalize_taxonomy_tag($ingredients_lc, "additives", $after)) or ((defined $after2) - and exists_taxonomy_tag("additives", canonicalize_taxonomy_tag($product_lc, "additives", $after2))) + and exists_taxonomy_tag("additives", canonicalize_taxonomy_tag($ingredients_lc, "additives", $after2))) ) ) { @@ -4535,7 +4569,7 @@ sub replace_additive ($number, $letter, $variant) { return $additive; } -=head2 develop_ingredients_categories_and_types ( $product_lc, $text ) - turn "oil (sunflower, olive and palm)" into "sunflower oil, olive oil, palm oil" +=head2 develop_ingredients_categories_and_types ( $ingredients_lc, $text ) - turn "oil (sunflower, olive and palm)" into "sunflower oil, olive oil, palm oil" Some ingredients are specified by an ingredient "category" (e.g. "oil", "flavouring") and a "type" (e.g. "sunflower", "palm" or "strawberry", "vanilla"). @@ -4718,11 +4752,11 @@ my %ingredients_categories_and_types = ( my @symbols = ('\*\*\*', '\*\*', '\*', '°°°', '°°', '°', '\(1\)', '\(2\)', '¹', '²'); my $symbols_regexp = join('|', @symbols); -sub develop_ingredients_categories_and_types ($product_lc, $text) { +sub develop_ingredients_categories_and_types ($ingredients_lc, $text) { - if (defined $ingredients_categories_and_types{$product_lc}) { + if (defined $ingredients_categories_and_types{$ingredients_lc}) { - foreach my $categories_and_types_ref (@{$ingredients_categories_and_types{$product_lc}}) { + foreach my $categories_and_types_ref (@{$ingredients_categories_and_types{$ingredients_lc}}) { my $category_regexp = ""; foreach my $category (@{$categories_and_types_ref->[0]}) { @@ -4735,10 +4769,10 @@ sub develop_ingredients_categories_and_types ($product_lc, $text) { } $category_regexp =~ s/^\|//; - if ($product_lc eq "en") { + if ($ingredients_lc eq "en") { $category_regexp = '(?:organic |fair trade )*(?:' . $category_regexp . ')(?:' . $symbols_regexp . ')*'; } - elsif ($product_lc eq "fr") { + elsif ($ingredients_lc eq "fr") { $category_regexp = '(?:' . $category_regexp . ')(?: bio| biologique| équitable|s|\s|' . $symbols_regexp . ')*'; } @@ -4762,36 +4796,36 @@ sub develop_ingredients_categories_and_types ($product_lc, $text) { $text =~ s/($type_regexp)-($type_regexp)/$1, $2/g; my $and = ' - '; - if (defined $and{$product_lc}) { - $and = $and{$product_lc}; + if (defined $and{$ingredients_lc}) { + $and = $and{$ingredients_lc}; } my $of = ' - '; - if (defined $of{$product_lc}) { - $of = $of{$product_lc}; + if (defined $of{$ingredients_lc}) { + $of = $of{$ingredients_lc}; } my $and_of = ' - '; - if (defined $and_of{$product_lc}) { - $and_of = $and_of{$product_lc}; + if (defined $and_of{$ingredients_lc}) { + $and_of = $and_of{$ingredients_lc}; } my $and_or = ' - '; - if (defined $and_or{$product_lc}) { - $and_or = $and_or{$product_lc}; + if (defined $and_or{$ingredients_lc}) { + $and_or = $and_or{$ingredients_lc}; } - if (($product_lc eq "en") or ($product_lc eq "ru") or ($product_lc eq "pl")) { + if (($ingredients_lc eq "en") or ($ingredients_lc eq "ru") or ($ingredients_lc eq "pl")) { # vegetable oil (palm, sunflower and olive) $text - =~ s/($category_regexp)(?::|\(|\[| | $of )+((($type_regexp)($symbols_regexp|\s)*( |\/| \/ | - |,|, |$and|$of|$and_of|$and_or)+)+($type_regexp)($symbols_regexp|\s)*)\b(\s?(\)|\]))?/normalize_enumeration($product_lc,$1,$2)/ieg; + =~ s/($category_regexp)(?::|\(|\[| | $of )+((($type_regexp)($symbols_regexp|\s)*( |\/| \/ | - |,|, |$and|$of|$and_of|$and_or)+)+($type_regexp)($symbols_regexp|\s)*)\b(\s?(\)|\]))?/normalize_enumeration($ingredients_lc,$1,$2)/ieg; # vegetable oil (palm) $text - =~ s/($category_regexp)\s?(?:\(|\[)\s?($type_regexp)\b(\s?(\)|\]))/normalize_enumeration($product_lc,$1,$2)/ieg; + =~ s/($category_regexp)\s?(?:\(|\[)\s?($type_regexp)\b(\s?(\)|\]))/normalize_enumeration($ingredients_lc,$1,$2)/ieg; # vegetable oil: palm $text - =~ s/($category_regexp)\s?(?::)\s?($type_regexp)(?=$separators|$)/normalize_enumeration($product_lc,$1,$2)/ieg; + =~ s/($category_regexp)\s?(?::)\s?($type_regexp)(?=$separators|$)/normalize_enumeration($ingredients_lc,$1,$2)/ieg; } - elsif ($product_lc eq "fr") { + elsif ($ingredients_lc eq "fr") { # arôme naturel de pomme avec d'autres âromes $text =~ s/ (ou|et|avec) (d')?autres /, /g; @@ -4803,21 +4837,21 @@ sub develop_ingredients_categories_and_types ($product_lc, $text) { # TODO 18/07/2020 remove when we have a better solution $text =~ s/fer (é|e)l(é|e)mentaire/fer_élémentaire/ig; $text - =~ s/($category_regexp)(?::|\(|\[| | de | d')+((($type_regexp)($symbols_regexp|\s)*( |\/| \/ | - |,|, | et | de | et de | et d'| d')+)+($type_regexp)($symbols_regexp|\s)*)\b(\s?(\)|\]))?/normalize_enumeration($product_lc,$1,$2)/ieg; + =~ s/($category_regexp)(?::|\(|\[| | de | d')+((($type_regexp)($symbols_regexp|\s)*( |\/| \/ | - |,|, | et | de | et de | et d'| d')+)+($type_regexp)($symbols_regexp|\s)*)\b(\s?(\)|\]))?/normalize_enumeration($ingredients_lc,$1,$2)/ieg; $text =~ s/fer_élémentaire/fer élémentaire/ig; # huile végétale (colza) $text - =~ s/($category_regexp)\s?(?:\(|\[)\s?($type_regexp)\b(\s?(\)|\]))/normalize_enumeration($product_lc,$1,$2)/ieg; + =~ s/($category_regexp)\s?(?:\(|\[)\s?($type_regexp)\b(\s?(\)|\]))/normalize_enumeration($ingredients_lc,$1,$2)/ieg; # huile végétale : colza, $text - =~ s/($category_regexp)\s?(?::)\s?($type_regexp)(?=$separators|$)/normalize_enumeration($product_lc,$1,$2)/ieg; + =~ s/($category_regexp)\s?(?::)\s?($type_regexp)(?=$separators|$)/normalize_enumeration($ingredients_lc,$1,$2)/ieg; } } # Some additives have "et" in their name: need to recombine them - if ($product_lc eq "fr") { + if ($ingredients_lc eq "fr") { # Sels de sodium et de potassium de complexes cupriques de chlorophyllines, @@ -4865,7 +4899,7 @@ INFO return $text; } -=head2 preparse_ingredients_text ($product_lc, $text) - normalize the ingredient list to make parsing easier +=head2 preparse_ingredients_text ($ingredients_lc, $text) - normalize the ingredient list to make parsing easier This function transform the ingredients list in a more normalized list that is easier to parse. @@ -4892,7 +4926,7 @@ It does the following: =cut -sub preparse_ingredients_text ($product_lc, $text) { +sub preparse_ingredients_text ($ingredients_lc, $text) { not defined $text and return; @@ -4904,11 +4938,11 @@ sub preparse_ingredients_text ($product_lc, $text) { state $prev_text = ''; state $prev_return = ''; - if (($product_lc eq $prev_lc) && ($text eq $prev_text)) { + if (($ingredients_lc eq $prev_lc) && ($text eq $prev_text)) { return $prev_return; } - $prev_lc = $product_lc; + $prev_lc = $ingredients_lc; $prev_text = $text; if ((scalar keys %labels_regexps) == 0) { @@ -4919,19 +4953,19 @@ sub preparse_ingredients_text ($product_lc, $text) { init_origins_regexps(); } - my $and = $and{$product_lc} || " and "; + my $and = $and{$ingredients_lc} || " and "; my $and_without_spaces = $and; $and_without_spaces =~ s/^ //; $and_without_spaces =~ s/ $//; my $of = ' - '; - if (defined $of{$product_lc}) { - $of = $of{$product_lc}; + if (defined $of{$ingredients_lc}) { + $of = $of{$ingredients_lc}; } my $and_of = ' - '; - if (defined $and_of{$product_lc}) { - $and_of = $and_of{$product_lc}; + if (defined $and_of{$ingredients_lc}) { + $and_of = $and_of{$ingredients_lc}; } # Spanish "and" is y or e when before "i" or "hi" @@ -4942,8 +4976,8 @@ sub preparse_ingredients_text ($product_lc, $text) { # replace "and / or" by "and" # except if followed by a separator, a digit, or "and", to avoid false positives my $and_or = ' - '; - if (defined $and_or{$product_lc}) { - $and_or = $and_or{$product_lc}; + if (defined $and_or{$ingredients_lc}) { + $and_or = $and_or{$ingredients_lc}; $text =~ s/($and_or)(?!($and_without_spaces |\d|$separators))/$and/ig; } @@ -4965,7 +4999,7 @@ sub preparse_ingredients_text ($product_lc, $text) { # number + gr / grams -> g $text =~ s/(\d\s*)(gr|gram|grams)\b/$1g/ig; - if ($product_lc eq 'fr') { + if ($ingredients_lc eq 'fr') { $text =~ s/(\d\s*)(gramme|grammes)\b/$1g/ig; } @@ -4978,7 +5012,7 @@ sub preparse_ingredients_text ($product_lc, $text) { $text =~ s/—/-/g; # abbreviations, replace language specific abbreviations first - foreach my $abbreviations_lc ($product_lc, "all") { + foreach my $abbreviations_lc ($ingredients_lc, "all") { if (defined $abbreviations{$abbreviations_lc}) { foreach my $abbreviation_ref (@{$abbreviations{$abbreviations_lc}}) { my $source = $abbreviation_ref->[0]; @@ -4998,7 +5032,7 @@ sub preparse_ingredients_text ($product_lc, $text) { # céleri - rave 3.9% -> stop at numbers $text - =~ s/((^|$separators)([^,;\-\/\.0-9]+?) - ([^,;\-\/\.0-9]+?)(?=[0-9]|$separators|$))/is_compound_word_with_dash($product_lc,$1)/ieg; + =~ s/((^|$separators)([^,;\-\/\.0-9]+?) - ([^,;\-\/\.0-9]+?)(?=[0-9]|$separators|$))/is_compound_word_with_dash($ingredients_lc,$1)/ieg; # vitamins... # vitamines A, B1, B2, B5, B6, B9, B12, C, D, H, PP et E (lactose, protéines de lait) @@ -5051,7 +5085,7 @@ sub preparse_ingredients_text ($product_lc, $text) { } $text - =~ s/\b(e|ins|sin|i-n-s|s-i-n|i\.n\.s\.?|s\.i\.n\.?)(:|\(|\[| | n| nb|#|°)+((($additivesregexp)( |\/| \/ | - |,|, |$and))+($additivesregexp))\b(\s?(\)|\]))?/normalize_additives_enumeration($product_lc,$3)/ieg; + =~ s/\b(e|ins|sin|i-n-s|s-i-n|i\.n\.s\.?|s\.i\.n\.?)(:|\(|\[| | n| nb|#|°)+((($additivesregexp)( |\/| \/ | - |,|, |$and))+($additivesregexp))\b(\s?(\)|\]))?/normalize_additives_enumeration($ingredients_lc,$3)/ieg; # in India: INS 240 instead of E 240, bug #1133) # also INS N°420, bug #3618 @@ -5088,11 +5122,11 @@ sub preparse_ingredients_text ($product_lc, $text) { # additive class + additive (e.g. "colour caramel" -> "colour : caramel" # warning: the additive class may also be the start of the name of an additive. # e.g. "regulatory kwasowości: kwas cytrynowy i cytryniany sodu." -> "kwas" means acid / acidifier. - if (defined $additives_classes_regexps{$product_lc}) { - my $regexp = $additives_classes_regexps{$product_lc}; + if (defined $additives_classes_regexps{$ingredients_lc}) { + my $regexp = $additives_classes_regexps{$ingredients_lc}; # negative look ahead so that the additive class is not preceded by other words # e.g. "de l'acide" should not match "acide" - $text =~ s/(?debug("preparse_ingredients_text - before language specific preparsing", {text => $text}) if $log->is_debug(); - if ($product_lc eq 'de') { + if ($ingredients_lc eq 'de') { # deletes comma in "Bienenwachs, weiß und gelb" since it is just one ingredient $text =~ s/Bienenwachs, weiß und gelb/Bienenwachs weiß und gelb/ig; # deletes brackets in "Bienenwachs, weiß und gelb" since it is just one ingredient $text =~ s/Bienenwachs \(weiß und gelb\)/Bienenwachs weiß und gelb/ig; } - elsif ($product_lc eq 'es') { + elsif ($ingredients_lc eq 'es') { # Special handling for sal as it can mean salt or shorea robusta # aceites vegetales (palma, shea, sal (shorea robusta), hueso de mango) $text =~ s/\bsal \(shorea robusta\)/shorea robusta/ig; $text =~ s/\bshorea robusta \(sal\)/shorea robusta/ig; } - elsif ($product_lc eq 'fi') { + elsif ($ingredients_lc eq 'fi') { # Organic label can appear as a part of a longer word. # Separate it so it can be detected $text =~ s/\b(luomu)\B/$1 /ig; } - elsif ($product_lc eq 'fr') { + elsif ($ingredients_lc eq 'fr') { # huiles de palme et de @@ -5166,14 +5200,14 @@ sub preparse_ingredients_text ($product_lc, $text) { $text =~ s/dient\(s\)/dients/ig; $text =~ s/\bissu(\(e\))?(\(s\))?/issu/ig; } - elsif ($product_lc eq 'pl') { + elsif ($ingredients_lc eq 'pl') { # remove stopwords $text =~ s/w? (zmiennych|różnych)? proporcjach?//i; } - $text = develop_ingredients_categories_and_types($product_lc, $text); + $text = develop_ingredients_categories_and_types($ingredients_lc, $text); # vitamines A, B1, B2, B5, B6, B9, B12, C, D, H, PP et E # vitamines (A, B1, B2, B5, B6, B9, B12, C, D, H, PP et E) @@ -5196,22 +5230,22 @@ sub preparse_ingredients_text ($product_lc, $text) { # Add synonyms in target language if (defined $translations_to{vitamins}) { foreach my $vitamin (keys %{$translations_to{vitamins}}) { - if (defined $translations_to{vitamins}{$vitamin}{$product_lc}) { - push @vitaminssuffixes, $translations_to{vitamins}{$vitamin}{$product_lc}; + if (defined $translations_to{vitamins}{$vitamin}{$ingredients_lc}) { + push @vitaminssuffixes, $translations_to{vitamins}{$vitamin}{$ingredients_lc}; } } } # Add synonyms in target language my $vitamin_in_lc - = get_string_id_for_lang($product_lc, display_taxonomy_tag($product_lc, "ingredients", "en:vitamins")); + = get_string_id_for_lang($ingredients_lc, display_taxonomy_tag($ingredients_lc, "ingredients", "en:vitamins")); $vitamin_in_lc =~ s/^\w\w://; if ( (defined $synonyms_for{ingredients}) - and (defined $synonyms_for{ingredients}{$product_lc}) - and (defined $synonyms_for{ingredients}{$product_lc}{$vitamin_in_lc})) + and (defined $synonyms_for{ingredients}{$ingredients_lc}) + and (defined $synonyms_for{ingredients}{$ingredients_lc}{$vitamin_in_lc})) { - foreach my $synonym (@{$synonyms_for{ingredients}{$product_lc}{$vitamin_in_lc}}) { + foreach my $synonym (@{$synonyms_for{ingredients}{$ingredients_lc}{$vitamin_in_lc}}) { $vitaminsprefixregexp .= '|' . $synonym; } } @@ -5245,7 +5279,7 @@ sub preparse_ingredients_text ($product_lc, $text) { # vitamines (B1, acide folique (B9)) <-- we need to match (B9) which is not followed by a \b boundary, hence the ((\s?((\)|\]))|\b)) in the regexp below $text - =~ s/($vitaminsprefixregexp)(:|\(|\[| )+((($vitaminssuffixregexp)( |\/| \/ | - |,|, |$and)+)+($vitaminssuffixregexp))((\s?((\)|\]))|\b))/normalize_vitamins_enumeration($product_lc,$3)/ieg; + =~ s/($vitaminsprefixregexp)(:|\(|\[| )+((($vitaminssuffixregexp)( |\/| \/ | - |,|, |$and)+)+($vitaminssuffixregexp))((\s?((\)|\]))|\b))/normalize_vitamins_enumeration($ingredients_lc,$3)/ieg; # Allergens and traces # Traces de lait, d'oeufs et de soja. @@ -5253,36 +5287,36 @@ sub preparse_ingredients_text ($product_lc, $text) { foreach my $allergens_type ("allergens", "traces") { - if (defined $contains_or_may_contain_regexps{$allergens_type}{$product_lc}) { + if (defined $contains_or_may_contain_regexps{$allergens_type}{$ingredients_lc}) { - my $contains_or_may_contain_regexp = $contains_or_may_contain_regexps{$allergens_type}{$product_lc}; - my $allergens_regexp = $allergens_regexps{$product_lc}; + my $contains_or_may_contain_regexp = $contains_or_may_contain_regexps{$allergens_type}{$ingredients_lc}; + my $allergens_regexp = $allergens_regexps{$ingredients_lc}; # stopwords # e.g. Kann Spuren von Senf und Sellerie enthalten. my $stopwords = ""; - if (defined $allergens_stopwords{$product_lc}) { - $stopwords = $allergens_stopwords{$product_lc}; + if (defined $allergens_stopwords{$ingredients_lc}) { + $stopwords = $allergens_stopwords{$ingredients_lc}; } # $contains_or_may_contain_regexp may be the end of a sentence, remove the beginning # e.g. this product has been manufactured in a factory that also uses... # Some text with comma May contain ... -> Some text with comma, May contain # ! does not work in German and languages that have words with a capital letter - if ($product_lc ne "de") { + if ($ingredients_lc ne "de") { my $ucfirst_contains_or_may_contain_regexp = $contains_or_may_contain_regexp; $ucfirst_contains_or_may_contain_regexp =~ s/(^|\|)(\w)/$1 . uc($2)/ieg; $text =~ s/([a-z]) ($ucfirst_contains_or_may_contain_regexp)/$1, $2/g; } #$log->debug("allergens regexp", { regex => "s/([^,-\.;\(\)\/]*)\b($contains_or_may_contain_regexp)\b(:|\(|\[| |$and|$of)+((($allergens_regexp)( |\/| \/ | - |,|, |$and|$of|$and_of)+)+($allergens_regexp))\b(s?(\)|\]))?" }) if $log->is_debug(); - #$log->debug("allergens", { lc => $product_lc, may_contain_regexps => \%may_contain_regexps, contains_or_may_contain_regexp => $contains_or_may_contain_regexp, text => $text }) if $log->is_debug(); + #$log->debug("allergens", { lc => $ingredients_lc, may_contain_regexps => \%may_contain_regexps, contains_or_may_contain_regexp => $contains_or_may_contain_regexp, text => $text }) if $log->is_debug(); # warning: we should remove a parenthesis at the end only if we remove one at the beginning # e.g. contains (milk, eggs) -> contains milk, eggs # chocolate (contains milk) -> chocolate (contains milk) $text - =~ s/([^,-\.;\(\)\/]*)\b($contains_or_may_contain_regexp)\b((:|\(|\[| |$of)+)((_?($allergens_regexp)_?\b((\s)($stopwords)\b)*( |\/| \/ | - |,|, |$and|$of|$and_of)+)*_?($allergens_regexp)_?)\b((\s)($stopwords)\b)*(\s?(\)|\]))?/normalize_allergens_enumeration($allergens_type,$product_lc,$3,$5,$17)/ieg; + =~ s/([^,-\.;\(\)\/]*)\b($contains_or_may_contain_regexp)\b((:|\(|\[| |$of)+)((_?($allergens_regexp)_?\b((\s)($stopwords)\b)*( |\/| \/ | - |,|, |$and|$of|$and_of)+)*_?($allergens_regexp)_?)\b((\s)($stopwords)\b)*(\s?(\)|\]))?/normalize_allergens_enumeration($allergens_type,$ingredients_lc,$3,$5,$17)/ieg; # we may have added an extra dot in order to make sure we have at least one $text =~ s/\.\./\./g; } @@ -5293,7 +5327,7 @@ sub preparse_ingredients_text ($product_lc, $text) { # Pâte de cacao°* du Pérou 65 %, sucre de canne°*, beurre de cacao°*. °Issus de l'agriculture biologique (100 %). *Issus du commerce équitable (100 % du poids total avec 93 % SPP). # riz* de Camargue IGP(1) (16,5%) (riz complet*, riz rouge complet*, huiles* (tournesol*, olive* vierge extra), sel marin. *issus de l'agriculture biologique. (1) IGP : Indication Géographique Protégée. - if (defined $labels_regexps{$product_lc}) { + if (defined $labels_regexps{$ingredients_lc}) { foreach my $symbol (@symbols) { # Find the last occurence of the symbol or symbol in parenthesis: * (*) @@ -5302,7 +5336,7 @@ sub preparse_ingredients_text ($product_lc, $text) { my $after = $'; #print STDERR "symbol: $symbol - after: $after\n"; foreach my $labelid (@labels) { - my $regexp = $labels_regexps{$product_lc}{$labelid}; + my $regexp = $labels_regexps{$ingredients_lc}{$labelid}; if (defined $regexp) { #print STDERR "-- label: $labelid - regexp: $regexp\n"; # try to also match optional precisions like "Issus de l'agriculture biologique (100 % du poids total)" @@ -5311,8 +5345,8 @@ sub preparse_ingredients_text ($product_lc, $text) { my $label = $1; $text =~ s/^(.*)(\($symbol\)|$symbol)(?!\))\s?(:|=)?\s?$label\s*(\([^\)]+\))?\s*\.?\s*/$1 /i; - my $product_lc_label = display_taxonomy_tag($product_lc, "labels", $labelid); - $text =~ s/$symbol/ $product_lc_label /g; + my $ingredients_lc_label = display_taxonomy_tag($ingredients_lc, "labels", $labelid); + $text =~ s/$symbol/ $ingredients_lc_label /g; last; } } @@ -5336,10 +5370,10 @@ sub preparse_ingredients_text ($product_lc, $text) { sub extract_ingredients_classes_from_text ($product_ref) { not defined $product_ref->{ingredients_text} and return; - - my $text = preparse_ingredients_text($product_ref->{lc}, $product_ref->{ingredients_text}); + my $ingredients_lc = $product_ref->{ingredients_lc} || $product_ref->{lc}; + my $text = preparse_ingredients_text($ingredients_lc, $product_ref->{ingredients_text}); # do not match anything if we don't have a translation for "and" - my $and = $and{$product_ref->{lc}} || " will not match "; + my $and = $and{$ingredients_lc} || " will not match "; $and =~ s/ /-/g; # remove % / percent (to avoid identifying 100% as E100 in some cases) @@ -5349,7 +5383,7 @@ sub extract_ingredients_classes_from_text ($product_ref) { my @ingredients_ids = (); foreach my $ingredient (@ingredients) { - my $ingredientid = get_string_id_for_lang($product_ref->{lc}, $ingredient); + my $ingredientid = get_string_id_for_lang($ingredients_lc, $ingredient); if ((defined $ingredientid) and ($ingredientid ne '')) { # split additives @@ -5362,16 +5396,15 @@ sub extract_ingredients_classes_from_text ($product_ref) { #print STDERR "ingredients_classes - ingredient1: $ingredientid1 - ingredient2: $ingredientid2\n"; # check if the whole ingredient is an additive - my $canon_ingredient_additive - = canonicalize_taxonomy_tag($product_ref->{lc}, "additives", $ingredientid); + my $canon_ingredient_additive = canonicalize_taxonomy_tag($ingredients_lc, "additives", $ingredientid); if (not exists_taxonomy_tag("additives", $canon_ingredient_additive)) { # otherwise check the 2 sub ingredients my $canon_ingredient_additive1 - = canonicalize_taxonomy_tag($product_ref->{lc}, "additives", $ingredientid1); + = canonicalize_taxonomy_tag($ingredients_lc, "additives", $ingredientid1); my $canon_ingredient_additive2 - = canonicalize_taxonomy_tag($product_ref->{lc}, "additives", $ingredientid2); + = canonicalize_taxonomy_tag($ingredients_lc, "additives", $ingredientid2); if ( (exists_taxonomy_tag("additives", $canon_ingredient_additive1)) and (exists_taxonomy_tag("additives", $canon_ingredient_additive2))) @@ -5445,7 +5478,7 @@ sub extract_ingredients_classes_from_text ($product_ref) { # additive class? my $canon_ingredient_additive_class - = canonicalize_taxonomy_tag($product_ref->{lc}, "additives_classes", $ingredient_id_copy); + = canonicalize_taxonomy_tag($ingredients_lc, "additives_classes", $ingredient_id_copy); if (exists_taxonomy_tag("additives_classes", $canon_ingredient_additive_class)) { $current_additive_class = $canon_ingredient_additive_class; @@ -5454,21 +5487,20 @@ sub extract_ingredients_classes_from_text ($product_ref) { } # additive? - my $canon_ingredient = canonicalize_taxonomy_tag($product_ref->{lc}, $tagtype, $ingredient_id_copy); + my $canon_ingredient = canonicalize_taxonomy_tag($ingredients_lc, $tagtype, $ingredient_id_copy); # in Hong Kong, the E- can be omitted in E-numbers my $canon_e_ingredient - = canonicalize_taxonomy_tag($product_ref->{lc}, $tagtype, "e" . $ingredient_id_copy); + = canonicalize_taxonomy_tag($ingredients_lc, $tagtype, "e" . $ingredient_id_copy); my $canon_ingredient_vitamins - = canonicalize_taxonomy_tag($product_ref->{lc}, "vitamins", $ingredient_id_copy); + = canonicalize_taxonomy_tag($ingredients_lc, "vitamins", $ingredient_id_copy); my $canon_ingredient_minerals - = canonicalize_taxonomy_tag($product_ref->{lc}, "minerals", $ingredient_id_copy); + = canonicalize_taxonomy_tag($ingredients_lc, "minerals", $ingredient_id_copy); my $canon_ingredient_amino_acids - = canonicalize_taxonomy_tag($product_ref->{lc}, "amino_acids", $ingredient_id_copy); + = canonicalize_taxonomy_tag($ingredients_lc, "amino_acids", $ingredient_id_copy); my $canon_ingredient_nucleotides - = canonicalize_taxonomy_tag($product_ref->{lc}, "nucleotides", $ingredient_id_copy); + = canonicalize_taxonomy_tag($ingredients_lc, "nucleotides", $ingredient_id_copy); my $canon_ingredient_other_nutritional_substances - = canonicalize_taxonomy_tag($product_ref->{lc}, "other_nutritional_substances", - $ingredient_id_copy); + = canonicalize_taxonomy_tag($ingredients_lc, "other_nutritional_substances", $ingredient_id_copy); $product_ref->{$tagtype} .= " [ $ingredient_id_copy -> $canon_ingredient "; @@ -5688,14 +5720,14 @@ sub extract_ingredients_classes_from_text ($product_ref) { and ( not exists_taxonomy_tag( "ingredients", - canonicalize_taxonomy_tag($product_ref->{lc}, "ingredients", $ingredient_id_copy) + canonicalize_taxonomy_tag($ingredients_lc, "ingredients", $ingredient_id_copy) ) ) ) { my ($corrected_canon_tagid, $corrected_tagid, $corrected_tag) - = spellcheck_taxonomy_tag($product_ref->{lc}, $tagtype, $ingredient_id_copy); + = spellcheck_taxonomy_tag($ingredients_lc, $tagtype, $ingredient_id_copy); if ( (defined $corrected_canon_tagid) and ($corrected_tag ne $ingredient_id_copy) @@ -5717,10 +5749,10 @@ sub extract_ingredients_classes_from_text ($product_ref) { $product_ref->{$tagtype} .= " -- spell correction (lc: " - . $product_ref->{lc} + . $ingredients_lc . "): $ingredient_id_copy -> $corrected_tag"; print STDERR "spell correction (lc: " - . $product_ref->{lc} + . $ingredients_lc . "): $ingredient_id_copy -> $corrected_tag - code: $product_ref->{code}\n"; $ingredient_id_copy = $corrected_tag; @@ -5735,11 +5767,11 @@ sub extract_ingredients_classes_from_text ($product_ref) { # try to shorten the ingredient to make it less specific, to see if it matches then # in last resort, try with the first (in French, Spanish) or last (in English) word only - if (($product_ref->{lc} eq 'en') and ($ingredient_id_copy =~ /^([^-]+)-/)) { + if (($ingredients_lc eq 'en') and ($ingredient_id_copy =~ /^([^-]+)-/)) { # soy-lecithin -> lecithin $ingredient_id_copy = $'; } - elsif ( (($product_ref->{lc} eq 'es') or ($product_ref->{lc} eq 'fr')) + elsif ( (($ingredients_lc eq 'es') or ($ingredients_lc eq 'fr')) and ($ingredient_id_copy =~ /-([^-]+)$/)) { # lecitina-de-girasol -> lecitina-de -> lecitina @@ -5899,7 +5931,7 @@ sub extract_ingredients_classes_from_text ($product_ref) { # keep the old additives for France until we can fix the new taxonomy matching to support all special cases # e.g. lecithine de soja - #if ($product_ref->{lc} ne 'fr') { + #if ($ingredients_lc ne 'fr') { # $product_ref->{additives_tags} = $product_ref->{new_additives_tags}; # $product_ref->{additives_tags_n} = $product_ref->{new_additives_tags_n}; #} @@ -5988,6 +6020,7 @@ sub extract_ingredients_classes_from_text ($product_ref) { sub replace_allergen ($language, $product_ref, $allergen, $before) { + my $ingredients_lc = $product_ref->{ingredients_lc} || $product_ref->{lc}; my $field = "allergens"; my $traces_regexp = $may_contain_regexps{$language}; @@ -5997,7 +6030,7 @@ sub replace_allergen ($language, $product_ref, $allergen, $before) { } # to build the product allergens list, just use the ingredients in the main language - if ($language eq $product_ref->{lc}) { + if ($language eq $ingredients_lc) { # skip allergens like "moutarde et céleri" (will be caught later by replace_allergen_between_separators) if (not(($language eq 'fr') and $allergen =~ / et /i)) { $product_ref->{$field . "_from_ingredients"} .= $allergen . ', '; @@ -6009,6 +6042,7 @@ sub replace_allergen ($language, $product_ref, $allergen, $before) { sub replace_allergen_in_caps ($language, $product_ref, $allergen, $before) { + my $ingredients_lc = $product_ref->{ingredients_lc} || $product_ref->{lc}; my $field = "allergens"; my $traces_regexp = $may_contain_regexps{$language}; @@ -6022,7 +6056,7 @@ sub replace_allergen_in_caps ($language, $product_ref, $allergen, $before) { if (exists_taxonomy_tag("allergens", $tagid)) { #$allergen = display_taxonomy_tag($product_ref->{lang},"allergens", $tagid); # to build the product allergens list, just use the ingredients in the main language - if ($language eq $product_ref->{lc}) { + if ($language eq $ingredients_lc) { $product_ref->{$field . "_from_ingredients"} .= $allergen . ', '; } return '' . $allergen . ''; @@ -6034,6 +6068,7 @@ sub replace_allergen_in_caps ($language, $product_ref, $allergen, $before) { sub replace_allergen_between_separators ($language, $product_ref, $start_separator, $allergen, $end_separator, $before) { + my $ingredients_lc = $product_ref->{ingredients_lc} || $product_ref->{lc}; my $field = "allergens"; #print STDERR "replace_allergen_between_separators - allergen: $allergen\n"; @@ -6087,7 +6122,7 @@ sub replace_allergen_between_separators ($language, $product_ref, $start_separat if (($tagid ne "en:none") and (exists_taxonomy_tag("allergens", $tagid))) { #$allergen = display_taxonomy_tag($product_ref->{lang},"allergens", $tagid); # to build the product allergens list, just use the ingredients in the main language - if ($language eq $product_ref->{lc}) { + if ($language eq $ingredients_lc) { $product_ref->{$field . "_from_ingredients"} .= $allergen . ', '; } return @@ -6185,6 +6220,8 @@ sub detect_allergens_from_text ($product_ref) { init_allergens_regexps(); } + my $ingredients_lc = $product_ref->{ingredients_lc} || $product_ref->{lc}; + # Keep allergens entered by users in the allergens and traces field foreach my $field ("allergens", "traces") { @@ -6264,7 +6301,7 @@ sub detect_allergens_from_text ($product_ref) { $product_ref->{"ingredients_text_with_allergens_" . $language} = $text; - if ($language eq $product_ref->{lc}) { + if ($language eq $ingredients_lc) { $product_ref->{"ingredients_text_with_allergens"} = $text; } @@ -6275,8 +6312,8 @@ sub detect_allergens_from_text ($product_ref) { # Use the language the tag have been entered in my $traces_regexp; - if (defined $may_contain_regexps{$product_ref->{traces_lc} || $product_ref->{lc}}) { - $traces_regexp = $may_contain_regexps{$product_ref->{traces_lc} || $product_ref->{lc}}; + if (defined $may_contain_regexps{$product_ref->{traces_lc} || $ingredients_lc}) { + $traces_regexp = $may_contain_regexps{$product_ref->{traces_lc} || $ingredients_lc}; } if ( (defined $traces_regexp) @@ -6298,7 +6335,7 @@ sub detect_allergens_from_text ($product_ref) { # regenerate allergens and traces from the allergens_tags field so that it is prefixed with the values in the # main language of the product (which may be different than the $tag_lc language of the interface) - my $tag_lc = $product_ref->{$field . "_lc"} || $product_ref->{lc} || "?"; + my $tag_lc = $product_ref->{$field . "_lc"} || $ingredients_lc || "?"; $product_ref->{$field . "_from_user"} = "($tag_lc) " . ($product_ref->{$field} // ""); $product_ref->{$field . "_hierarchy"} = [gen_tags_hierarchy_taxonomy($tag_lc, $field, $product_ref->{$field})]; $product_ref->{$field} = join(',', @{$product_ref->{$field . "_hierarchy"}}); @@ -6314,11 +6351,11 @@ sub detect_allergens_from_text ($product_ref) { $allergens .= ", " . $product_ref->{$field}; } - $product_ref->{$field . "_hierarchy"} = [gen_tags_hierarchy_taxonomy($product_ref->{lc}, $field, $allergens)]; + $product_ref->{$field . "_hierarchy"} = [gen_tags_hierarchy_taxonomy($ingredients_lc, $field, $allergens)]; $product_ref->{$field . "_tags"} = []; # print STDERR "result for $field : "; foreach my $tag (@{$product_ref->{$field . "_hierarchy"}}) { - push @{$product_ref->{$field . "_tags"}}, get_taxonomyid($product_ref->{lc}, $tag); + push @{$product_ref->{$field . "_tags"}}, get_taxonomyid($ingredients_lc, $tag); # print STDERR " - $tag"; } # print STDERR "\n"; diff --git a/lib/ProductOpener/KnowledgePanels.pm b/lib/ProductOpener/KnowledgePanels.pm index af37041f42271..5c9dadc450ead 100644 --- a/lib/ProductOpener/KnowledgePanels.pm +++ b/lib/ProductOpener/KnowledgePanels.pm @@ -1146,7 +1146,7 @@ sub create_ingredients_panel ($product_ref, $target_lc, $target_cc, $options_ref my $ingredients_text = $product_ref->{ingredients_text}; my $ingredients_text_with_allergens = $product_ref->{ingredients_text_with_allergens}; - my $ingredients_text_lc = $product_ref->{lc}; + my $ingredients_text_lc = $product_ref->{ingredients_lc}; if ( (defined $product_ref->{"ingredients_text" . "_" . $target_lc}) and ($product_ref->{"ingredients_text" . "_" . $target_lc} ne '')) diff --git a/lib/ProductOpener/Products.pm b/lib/ProductOpener/Products.pm index e937653f1f42e..644be0b8b9090 100644 --- a/lib/ProductOpener/Products.pm +++ b/lib/ProductOpener/Products.pm @@ -3558,6 +3558,8 @@ sub analyze_and_enrich_product_data ($product_ref, $response_ref) { compute_languages($product_ref); # need languages for allergens detection and cleaning ingredients # Ingredients classes + # Select best language to parse ingredients + $product_ref->{ingredients_lc} = select_ingredients_lc($product_ref); clean_ingredients_text($product_ref); extract_ingredients_from_text($product_ref); extract_ingredients_classes_from_text($product_ref); diff --git a/tests/integration/expected_test_results/api_v2_product_read/get-existing-product.json b/tests/integration/expected_test_results/api_v2_product_read/get-existing-product.json index 15ab7340f7303..279926ce5412e 100644 --- a/tests/integration/expected_test_results/api_v2_product_read/get-existing-product.json +++ b/tests/integration/expected_test_results/api_v2_product_read/get-existing-product.json @@ -646,6 +646,7 @@ "en:vegetable-oil-and-fat", "en:palm-oil-and-fat" ], + "ingredients_lc" : "en", "ingredients_n" : 4, "ingredients_n_tags" : [ "4", diff --git a/tests/integration/expected_test_results/api_v2_product_read/get-fields-all-knowledge-panels.json b/tests/integration/expected_test_results/api_v2_product_read/get-fields-all-knowledge-panels.json index 5b578032d3ca8..a48ea19a83962 100644 --- a/tests/integration/expected_test_results/api_v2_product_read/get-fields-all-knowledge-panels.json +++ b/tests/integration/expected_test_results/api_v2_product_read/get-fields-all-knowledge-panels.json @@ -646,6 +646,7 @@ "en:vegetable-oil-and-fat", "en:palm-oil-and-fat" ], + "ingredients_lc" : "en", "ingredients_n" : 4, "ingredients_n_tags" : [ "4", @@ -1383,7 +1384,7 @@ { "element_type" : "text", "text_element" : { - "html" : "apple, milk, eggs, palm oil" + "html" : "en: apple, milk, eggs, palm oil" } }, { diff --git a/tests/integration/expected_test_results/api_v2_product_read/get-fields-all.json b/tests/integration/expected_test_results/api_v2_product_read/get-fields-all.json index 15ab7340f7303..279926ce5412e 100644 --- a/tests/integration/expected_test_results/api_v2_product_read/get-fields-all.json +++ b/tests/integration/expected_test_results/api_v2_product_read/get-fields-all.json @@ -646,6 +646,7 @@ "en:vegetable-oil-and-fat", "en:palm-oil-and-fat" ], + "ingredients_lc" : "en", "ingredients_n" : 4, "ingredients_n_tags" : [ "4", diff --git a/tests/integration/expected_test_results/api_v2_product_read/get-fields-attribute-groups-all-knowledge-panels.json b/tests/integration/expected_test_results/api_v2_product_read/get-fields-attribute-groups-all-knowledge-panels.json index 19934070ea24b..af8f60293910e 100644 --- a/tests/integration/expected_test_results/api_v2_product_read/get-fields-attribute-groups-all-knowledge-panels.json +++ b/tests/integration/expected_test_results/api_v2_product_read/get-fields-attribute-groups-all-knowledge-panels.json @@ -970,6 +970,7 @@ "en:vegetable-oil-and-fat", "en:palm-oil-and-fat" ], + "ingredients_lc" : "en", "ingredients_n" : 4, "ingredients_n_tags" : [ "4", @@ -1707,7 +1708,7 @@ { "element_type" : "text", "text_element" : { - "html" : "apple, milk, eggs, palm oil" + "html" : "en: apple, milk, eggs, palm oil" } }, { diff --git a/tests/integration/expected_test_results/api_v2_product_read/get-fields-raw.json b/tests/integration/expected_test_results/api_v2_product_read/get-fields-raw.json index a50857702001a..18586edc6606a 100644 --- a/tests/integration/expected_test_results/api_v2_product_read/get-fields-raw.json +++ b/tests/integration/expected_test_results/api_v2_product_read/get-fields-raw.json @@ -641,6 +641,7 @@ "en:vegetable-oil-and-fat", "en:palm-oil-and-fat" ], + "ingredients_lc" : "en", "ingredients_n" : 4, "ingredients_n_tags" : [ "4", diff --git a/tests/integration/expected_test_results/api_v2_product_read/get-knowledge-panels-fr.json b/tests/integration/expected_test_results/api_v2_product_read/get-knowledge-panels-fr.json index 863870adc89db..715a98a700c12 100644 --- a/tests/integration/expected_test_results/api_v2_product_read/get-knowledge-panels-fr.json +++ b/tests/integration/expected_test_results/api_v2_product_read/get-knowledge-panels-fr.json @@ -699,7 +699,7 @@ { "element_type" : "text", "text_element" : { - "html" : "apple, milk, eggs, palm oil" + "html" : "en: apple, milk, eggs, palm oil" } }, { diff --git a/tests/integration/expected_test_results/api_v2_product_read/get-knowledge-panels.json b/tests/integration/expected_test_results/api_v2_product_read/get-knowledge-panels.json index 8644d569d41d5..43dce689ec063 100644 --- a/tests/integration/expected_test_results/api_v2_product_read/get-knowledge-panels.json +++ b/tests/integration/expected_test_results/api_v2_product_read/get-knowledge-panels.json @@ -699,7 +699,7 @@ { "element_type" : "text", "text_element" : { - "html" : "apple, milk, eggs, palm oil" + "html" : "en: apple, milk, eggs, palm oil" } }, { diff --git a/tests/integration/expected_test_results/api_v2_product_write/get-product-auth-good-password.json b/tests/integration/expected_test_results/api_v2_product_write/get-product-auth-good-password.json index 71e5c51d5a0d4..6ebe8b1fa8f7f 100644 --- a/tests/integration/expected_test_results/api_v2_product_write/get-product-auth-good-password.json +++ b/tests/integration/expected_test_results/api_v2_product_write/get-product-auth-good-password.json @@ -582,6 +582,7 @@ "en:added-sugar", "en:disaccharide" ], + "ingredients_lc" : "fr", "ingredients_n" : 4, "ingredients_n_tags" : [ "4", diff --git a/tests/integration/expected_test_results/api_v2_product_write/get-product-ingredients-text-without-language.json b/tests/integration/expected_test_results/api_v2_product_write/get-product-ingredients-text-without-language.json index 4c9bfeb54b712..8cb8b05997458 100644 --- a/tests/integration/expected_test_results/api_v2_product_write/get-product-ingredients-text-without-language.json +++ b/tests/integration/expected_test_results/api_v2_product_write/get-product-ingredients-text-without-language.json @@ -6,11 +6,17 @@ "sausage" ], "added_countries_tags" : [], + "additives_n" : 0, + "additives_old_n" : 0, + "additives_old_tags" : [], + "additives_original_tags" : [], + "additives_tags" : [], "allergens" : "", "allergens_from_ingredients" : "", - "allergens_from_user" : "(fr) ", + "allergens_from_user" : "(en) ", "allergens_hierarchy" : [], "allergens_tags" : [], + "amino_acids_tags" : [], "categories" : "Sausages", "categories_hierarchy" : [ "en:meats-and-their-products", @@ -51,7 +57,7 @@ "1xxxxxxxxxxxx" ], "complete" : 0, - "completeness" : 0.2, + "completeness" : 0.3, "correctors_tags" : [], "countries" : "en:united-kingdom", "countries_hierarchy" : [ @@ -66,6 +72,7 @@ "data_quality_errors_tags" : [], "data_quality_info_tags" : [ "en:no-packaging-data", + "en:ingredients-percent-analysis-ok", "en:ecoscore-extended-data-not-computed", "en:food-groups-1-known", "en:food-groups-2-known", @@ -73,20 +80,19 @@ ], "data_quality_tags" : [ "en:no-packaging-data", + "en:ingredients-percent-analysis-ok", "en:ecoscore-extended-data-not-computed", "en:food-groups-1-known", "en:food-groups-2-known", "en:food-groups-3-unknown", "en:ecoscore-origins-of-ingredients-origins-are-100-percent-unknown", "en:ecoscore-packaging-packaging-data-missing", - "en:ecoscore-production-system-no-label", - "en:ecoscore-threatened-species-ingredients-missing" + "en:ecoscore-production-system-no-label" ], "data_quality_warnings_tags" : [ "en:ecoscore-origins-of-ingredients-origins-are-100-percent-unknown", "en:ecoscore-packaging-packaging-data-missing", - "en:ecoscore-production-system-no-label", - "en:ecoscore-threatened-species-ingredients-missing" + "en:ecoscore-production-system-no-label" ], "ecoscore_data" : { "adjustments" : { @@ -314,16 +320,13 @@ "value" : 0, "warning" : "no_label" }, - "threatened_species" : { - "warning" : "ingredients_missing" - } + "threatened_species" : {} }, "agribalyse" : { "warning" : "missing_agribalyse_match" }, "missing" : { "agb_category" : 1, - "ingredients" : 1, "labels" : 1, "origins" : 1, "packagings" : 1 @@ -350,10 +353,85 @@ "informers_tags" : [ "openfoodfacts-contributors" ], + "ingredients" : [ + { + "id" : "en:pork-meat", + "percent_estimate" : 75, + "percent_max" : 100, + "percent_min" : 50, + "text" : "Pork meat", + "vegan" : "no", + "vegetarian" : "no" + }, + { + "ciqual_food_code" : "11058", + "id" : "en:salt", + "percent_estimate" : 25, + "percent_max" : 50, + "percent_min" : 0, + "text" : "salt", + "vegan" : "yes", + "vegetarian" : "yes" + } + ], + "ingredients_analysis" : { + "en:non-vegan" : [ + "en:pork-meat" + ], + "en:non-vegetarian" : [ + "en:pork-meat" + ] + }, + "ingredients_analysis_tags" : [ + "en:palm-oil-free", + "en:non-vegan", + "en:non-vegetarian" + ], + "ingredients_from_or_that_may_be_from_palm_oil_n" : 0, + "ingredients_from_palm_oil_n" : 0, + "ingredients_from_palm_oil_tags" : [], + "ingredients_hierarchy" : [ + "en:pork-meat", + "en:animal", + "en:meat", + "en:pork", + "en:salt" + ], + "ingredients_lc" : "en", + "ingredients_n" : 2, + "ingredients_n_tags" : [ + "2", + "1-10" + ], + "ingredients_original_tags" : [ + "en:pork-meat", + "en:salt" + ], + "ingredients_percent_analysis" : 1, + "ingredients_tags" : [ + "en:pork-meat", + "en:animal", + "en:meat", + "en:pork", + "en:salt" + ], + "ingredients_text" : "Pork meat, salt", "ingredients_text_en" : "Pork meat, salt", + "ingredients_text_with_allergens" : "Pork meat, salt", "ingredients_text_with_allergens_en" : "Pork meat, salt", + "ingredients_that_may_be_from_palm_oil_n" : 0, + "ingredients_that_may_be_from_palm_oil_tags" : [], + "ingredients_with_specified_percent_n" : 0, + "ingredients_with_specified_percent_sum" : 0, + "ingredients_with_unspecified_percent_n" : 2, + "ingredients_with_unspecified_percent_sum" : 100, + "ingredients_without_ciqual_codes" : [ + "en:pork-meat" + ], + "ingredients_without_ciqual_codes_n" : 1, "interface_version_created" : "20150316.jqm2", "interface_version_modified" : "20150316.jqm2", + "known_ingredients_n" : 5, "lang" : "fr", "languages" : { "en:english" : 2 @@ -372,6 +450,7 @@ "last_modified_t" : "--ignore--", "lc" : "fr", "main_countries_tags" : [], + "minerals_tags" : [], "misc_tags" : [ "en:nutrition-not-enough-data-to-compute-nutrition-score", "en:nutriscore-missing-nutrition-data", @@ -383,7 +462,7 @@ "en:nutriscore-missing-nutrition-data-proteins", "en:nutrition-no-fiber", "en:nutriscore-not-computed", - "en:nutrition-no-fruits-vegetables-nuts", + "en:nutrition-fruits-vegetables-nuts-estimate-from-ingredients", "en:nutrition-no-fiber-or-fruits-vegetables-nuts", "en:packagings-number-of-components-0", "en:packagings-not-complete", @@ -392,14 +471,38 @@ "en:ecoscore-not-computed", "en:main-countries-new-product" ], - "nova_group_debug" : "no nova group when the product does not have ingredients", - "nova_group_error" : "missing_ingredients", + "nova_group" : 3, + "nova_group_debug" : "", + "nova_groups" : "3", + "nova_groups_markers" : { + "3" : [ + [ + "categories", + "en:prepared-meats" + ], + [ + "categories", + "en:sausages" + ], + [ + "ingredients", + "en:salt" + ] + ] + }, "nova_groups_tags" : [ - "unknown" + "en:3-processed-foods" ], + "nucleotides_tags" : [], "nutrient_levels" : {}, "nutrient_levels_tags" : [], - "nutriments" : {}, + "nutriments" : { + "fruits-vegetables-nuts-estimate-from-ingredients_100g" : 0, + "fruits-vegetables-nuts-estimate-from-ingredients_serving" : 0, + "nova-group" : 3, + "nova-group_100g" : 3, + "nova-group_serving" : 3 + }, "nutriscore" : { "2021" : { "category_available" : 1, @@ -462,8 +565,10 @@ ], "nutrition_score_beverage" : 0, "nutrition_score_debug" : "missing energy_100g - missing fat_100g - missing saturated-fat_100g - missing sugars_100g - missing sodium_100g - missing proteins_100g", + "nutrition_score_warning_fruits_vegetables_nuts_estimate_from_ingredients" : 1, + "nutrition_score_warning_fruits_vegetables_nuts_estimate_from_ingredients_value" : 0, "nutrition_score_warning_no_fiber" : 1, - "nutrition_score_warning_no_fruits_vegetables_nuts" : 1, + "other_nutritional_substances_tags" : [], "packaging_materials_tags" : [], "packaging_recycling_tags" : [], "packaging_shapes_tags" : [], @@ -488,11 +593,11 @@ "rev" : 1, "serving_quantity" : "20", "serving_size" : "20 g", - "states" : "en:to-be-completed, en:nutrition-facts-to-be-completed, en:ingredients-to-be-completed, en:expiration-date-to-be-completed, en:packaging-code-to-be-completed, en:characteristics-to-be-completed, en:origins-to-be-completed, en:categories-completed, en:brands-to-be-completed, en:packaging-to-be-completed, en:quantity-completed, en:product-name-to-be-completed, en:photos-to-be-uploaded", + "states" : "en:to-be-completed, en:nutrition-facts-to-be-completed, en:ingredients-completed, en:expiration-date-to-be-completed, en:packaging-code-to-be-completed, en:characteristics-to-be-completed, en:origins-to-be-completed, en:categories-completed, en:brands-to-be-completed, en:packaging-to-be-completed, en:quantity-completed, en:product-name-to-be-completed, en:photos-to-be-uploaded", "states_hierarchy" : [ "en:to-be-completed", "en:nutrition-facts-to-be-completed", - "en:ingredients-to-be-completed", + "en:ingredients-completed", "en:expiration-date-to-be-completed", "en:packaging-code-to-be-completed", "en:characteristics-to-be-completed", @@ -507,7 +612,7 @@ "states_tags" : [ "en:to-be-completed", "en:nutrition-facts-to-be-completed", - "en:ingredients-to-be-completed", + "en:ingredients-completed", "en:expiration-date-to-be-completed", "en:packaging-code-to-be-completed", "en:characteristics-to-be-completed", @@ -521,10 +626,12 @@ ], "traces" : "", "traces_from_ingredients" : "", - "traces_from_user" : "(fr) ", + "traces_from_user" : "(en) ", "traces_hierarchy" : [], "traces_tags" : [], + "unknown_ingredients_n" : 0, "unknown_nutrients_tags" : [], + "vitamins_tags" : [], "weighers_tags" : [] }, "status" : 1, diff --git a/tests/integration/expected_test_results/api_v2_product_write/get-product.json b/tests/integration/expected_test_results/api_v2_product_write/get-product.json index d449f9c074f4e..938997a3a3866 100644 --- a/tests/integration/expected_test_results/api_v2_product_write/get-product.json +++ b/tests/integration/expected_test_results/api_v2_product_write/get-product.json @@ -582,6 +582,7 @@ "en:added-sugar", "en:disaccharide" ], + "ingredients_lc" : "fr", "ingredients_n" : 4, "ingredients_n_tags" : [ "4", diff --git a/tests/integration/expected_test_results/api_v3_product_read/get-existing-product.json b/tests/integration/expected_test_results/api_v3_product_read/get-existing-product.json index 6cea5f8181b67..8999dec94e561 100644 --- a/tests/integration/expected_test_results/api_v3_product_read/get-existing-product.json +++ b/tests/integration/expected_test_results/api_v3_product_read/get-existing-product.json @@ -647,6 +647,7 @@ "en:vegetable-oil-and-fat", "en:palm-oil-and-fat" ], + "ingredients_lc" : "en", "ingredients_n" : 4, "ingredients_n_tags" : [ "4", diff --git a/tests/integration/expected_test_results/api_v3_product_read/get-fields-all-knowledge-panels.json b/tests/integration/expected_test_results/api_v3_product_read/get-fields-all-knowledge-panels.json index 4fe102b568958..f42eced5fbb1b 100644 --- a/tests/integration/expected_test_results/api_v3_product_read/get-fields-all-knowledge-panels.json +++ b/tests/integration/expected_test_results/api_v3_product_read/get-fields-all-knowledge-panels.json @@ -647,6 +647,7 @@ "en:vegetable-oil-and-fat", "en:palm-oil-and-fat" ], + "ingredients_lc" : "en", "ingredients_n" : 4, "ingredients_n_tags" : [ "4", @@ -1384,7 +1385,7 @@ { "element_type" : "text", "text_element" : { - "html" : "apple, milk, eggs, palm oil" + "html" : "en: apple, milk, eggs, palm oil" } }, { diff --git a/tests/integration/expected_test_results/api_v3_product_read/get-fields-all.json b/tests/integration/expected_test_results/api_v3_product_read/get-fields-all.json index 6cea5f8181b67..8999dec94e561 100644 --- a/tests/integration/expected_test_results/api_v3_product_read/get-fields-all.json +++ b/tests/integration/expected_test_results/api_v3_product_read/get-fields-all.json @@ -647,6 +647,7 @@ "en:vegetable-oil-and-fat", "en:palm-oil-and-fat" ], + "ingredients_lc" : "en", "ingredients_n" : 4, "ingredients_n_tags" : [ "4", diff --git a/tests/integration/expected_test_results/api_v3_product_read/get-fields-attribute-groups-all-knowledge-panels.json b/tests/integration/expected_test_results/api_v3_product_read/get-fields-attribute-groups-all-knowledge-panels.json index 7310511a142f8..4e71cabf47512 100644 --- a/tests/integration/expected_test_results/api_v3_product_read/get-fields-attribute-groups-all-knowledge-panels.json +++ b/tests/integration/expected_test_results/api_v3_product_read/get-fields-attribute-groups-all-knowledge-panels.json @@ -971,6 +971,7 @@ "en:vegetable-oil-and-fat", "en:palm-oil-and-fat" ], + "ingredients_lc" : "en", "ingredients_n" : 4, "ingredients_n_tags" : [ "4", @@ -1708,7 +1709,7 @@ { "element_type" : "text", "text_element" : { - "html" : "apple, milk, eggs, palm oil" + "html" : "en: apple, milk, eggs, palm oil" } }, { diff --git a/tests/integration/expected_test_results/api_v3_product_read/get-fields-raw.json b/tests/integration/expected_test_results/api_v3_product_read/get-fields-raw.json index fbc5167ff3cb4..903fe854a5333 100644 --- a/tests/integration/expected_test_results/api_v3_product_read/get-fields-raw.json +++ b/tests/integration/expected_test_results/api_v3_product_read/get-fields-raw.json @@ -642,6 +642,7 @@ "en:vegetable-oil-and-fat", "en:palm-oil-and-fat" ], + "ingredients_lc" : "en", "ingredients_n" : 4, "ingredients_n_tags" : [ "4", diff --git a/tests/integration/expected_test_results/api_v3_product_read/get-knowledge-panels-fr.json b/tests/integration/expected_test_results/api_v3_product_read/get-knowledge-panels-fr.json index 9ebad360bb7d1..e78bfe6f21f92 100644 --- a/tests/integration/expected_test_results/api_v3_product_read/get-knowledge-panels-fr.json +++ b/tests/integration/expected_test_results/api_v3_product_read/get-knowledge-panels-fr.json @@ -700,7 +700,7 @@ { "element_type" : "text", "text_element" : { - "html" : "apple, milk, eggs, palm oil" + "html" : "en: apple, milk, eggs, palm oil" } }, { diff --git a/tests/integration/expected_test_results/api_v3_product_read/get-knowledge-panels.json b/tests/integration/expected_test_results/api_v3_product_read/get-knowledge-panels.json index b5dd4202232ff..029fdc4c3b73b 100644 --- a/tests/integration/expected_test_results/api_v3_product_read/get-knowledge-panels.json +++ b/tests/integration/expected_test_results/api_v3_product_read/get-knowledge-panels.json @@ -700,7 +700,7 @@ { "element_type" : "text", "text_element" : { - "html" : "apple, milk, eggs, palm oil" + "html" : "en: apple, milk, eggs, palm oil" } }, { diff --git a/tests/integration/expected_test_results/api_v3_product_write/patch-request-fields-all.json b/tests/integration/expected_test_results/api_v3_product_write/patch-request-fields-all.json index 89ab4337af8ce..5bf39d5e68b0f 100644 --- a/tests/integration/expected_test_results/api_v3_product_write/patch-request-fields-all.json +++ b/tests/integration/expected_test_results/api_v3_product_write/patch-request-fields-all.json @@ -330,6 +330,7 @@ "informers_tags" : [ "openfoodfacts-contributors" ], + "ingredients_lc" : "en", "interface_version_created" : "20221102/api/v3", "lang" : "en", "languages" : {}, diff --git a/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390017165.json b/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390017165.json index 90f5ec0e68d21..1314ce72ea7ad 100644 --- a/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390017165.json +++ b/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390017165.json @@ -363,6 +363,7 @@ "informers_tags" : [ "test-user" ], + "ingredients_lc" : "fr", "interface_version_created" : "import_csv_file - version 2019/09/17", "lang" : "fr", "lang_imported" : "fr", diff --git a/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390020745.json b/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390020745.json index 0025f6543656d..f051af56762cc 100644 --- a/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390020745.json +++ b/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390020745.json @@ -360,6 +360,7 @@ "informers_tags" : [ "test-user" ], + "ingredients_lc" : "fr", "interface_version_created" : "import_csv_file - version 2019/09/17", "lang" : "fr", "lang_imported" : "fr", diff --git a/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390020806.json b/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390020806.json index 60fba34163642..79dd71d53f9ef 100644 --- a/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390020806.json +++ b/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390020806.json @@ -349,6 +349,7 @@ "informers_tags" : [ "test-user" ], + "ingredients_lc" : "fr", "interface_version_created" : "import_csv_file - version 2019/09/17", "lang" : "fr", "lang_imported" : "fr", diff --git a/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390020998.json b/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390020998.json index 8bf855d0e498b..a4156223e91d9 100644 --- a/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390020998.json +++ b/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390020998.json @@ -363,6 +363,7 @@ "informers_tags" : [ "test-user" ], + "ingredients_lc" : "fr", "interface_version_created" : "import_csv_file - version 2019/09/17", "lang" : "fr", "lang_imported" : "fr", diff --git a/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390021001.json b/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390021001.json index d22f73941f416..35c3d5b4ab5f1 100644 --- a/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390021001.json +++ b/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390021001.json @@ -357,6 +357,7 @@ "informers_tags" : [ "test-user" ], + "ingredients_lc" : "fr", "interface_version_created" : "import_csv_file - version 2019/09/17", "lang" : "fr", "lang_imported" : "fr", diff --git a/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390021469.json b/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390021469.json index af95fa858f463..972aa1d577962 100644 --- a/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390021469.json +++ b/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390021469.json @@ -354,6 +354,7 @@ "informers_tags" : [ "test-user" ], + "ingredients_lc" : "fr", "interface_version_created" : "import_csv_file - version 2019/09/17", "lang" : "fr", "lang_imported" : "fr", diff --git a/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390021544.json b/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390021544.json index 0db7d0c68d0f7..d816fa03c407f 100644 --- a/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390021544.json +++ b/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390021544.json @@ -357,6 +357,7 @@ "informers_tags" : [ "test-user" ], + "ingredients_lc" : "fr", "interface_version_created" : "import_csv_file - version 2019/09/17", "lang" : "fr", "lang_imported" : "fr", diff --git a/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390021568.json b/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390021568.json index d0116fb51ef42..7151ac45b4503 100644 --- a/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390021568.json +++ b/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390021568.json @@ -355,6 +355,7 @@ "informers_tags" : [ "test-user" ], + "ingredients_lc" : "fr", "interface_version_created" : "import_csv_file - version 2019/09/17", "lang" : "fr", "lang_imported" : "fr", diff --git a/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390021926.json b/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390021926.json index cad79dc1b23b9..fceae400ea7b5 100644 --- a/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390021926.json +++ b/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390021926.json @@ -347,6 +347,7 @@ "informers_tags" : [ "test-user" ], + "ingredients_lc" : "fr", "interface_version_created" : "import_csv_file - version 2019/09/17", "lang" : "fr", "lang_imported" : "fr", diff --git a/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390024781.json b/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390024781.json index 1d960f3668cf5..5ba36a8e806d3 100644 --- a/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390024781.json +++ b/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390024781.json @@ -382,6 +382,7 @@ "informers_tags" : [ "test-user" ], + "ingredients_lc" : "fr", "interface_version_created" : "import_csv_file - version 2019/09/17", "lang" : "fr", "lang_imported" : "fr", diff --git a/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390024804.json b/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390024804.json index c69d18e822d51..1460760f18270 100644 --- a/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390024804.json +++ b/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390024804.json @@ -371,6 +371,7 @@ "informers_tags" : [ "test-user" ], + "ingredients_lc" : "fr", "interface_version_created" : "import_csv_file - version 2019/09/17", "lang" : "fr", "lang_imported" : "fr", diff --git a/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390024842.json b/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390024842.json index b6d26097b41cf..02350dab45b85 100644 --- a/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390024842.json +++ b/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390024842.json @@ -372,6 +372,7 @@ "informers_tags" : [ "test-user" ], + "ingredients_lc" : "fr", "interface_version_created" : "import_csv_file - version 2019/09/17", "lang" : "fr", "lang_imported" : "fr", diff --git a/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390024866.json b/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390024866.json index 4453e97e7b58e..e792ae40199d5 100644 --- a/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390024866.json +++ b/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390024866.json @@ -372,6 +372,7 @@ "informers_tags" : [ "test-user" ], + "ingredients_lc" : "fr", "interface_version_created" : "import_csv_file - version 2019/09/17", "lang" : "fr", "lang_imported" : "fr", diff --git a/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390025399.json b/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390025399.json index 56a0363463c53..67a8065a42eae 100644 --- a/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390025399.json +++ b/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390025399.json @@ -364,6 +364,7 @@ "informers_tags" : [ "test-user" ], + "ingredients_lc" : "fr", "interface_version_created" : "import_csv_file - version 2019/09/17", "lang" : "fr", "lang_imported" : "fr", diff --git a/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390025863.json b/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390025863.json index e4931aa3c1c20..2e04154fb1633 100644 --- a/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390025863.json +++ b/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390025863.json @@ -346,6 +346,7 @@ "informers_tags" : [ "test-user" ], + "ingredients_lc" : "fr", "interface_version_created" : "import_csv_file - version 2019/09/17", "lang" : "fr", "lang_imported" : "fr", diff --git a/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390026044.json b/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390026044.json index 03c4d73c47962..9366f848c87de 100644 --- a/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390026044.json +++ b/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390026044.json @@ -368,6 +368,7 @@ "informers_tags" : [ "test-user" ], + "ingredients_lc" : "fr", "interface_version_created" : "import_csv_file - version 2019/09/17", "lang" : "fr", "lang_imported" : "fr", diff --git a/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390026648.json b/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390026648.json index df17885cf3c7e..3a1ecfcc999c7 100644 --- a/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390026648.json +++ b/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390026648.json @@ -383,6 +383,7 @@ "informers_tags" : [ "test-user" ], + "ingredients_lc" : "fr", "interface_version_created" : "import_csv_file - version 2019/09/17", "lang" : "fr", "lang_imported" : "fr", diff --git a/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390026754.json b/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390026754.json index b2bad183153ba..cbfd68813e762 100644 --- a/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390026754.json +++ b/tests/integration/expected_test_results/convert_and_import_excel_file/packagings-mousquetaires/products/3250390026754.json @@ -365,6 +365,7 @@ "informers_tags" : [ "test-user" ], + "ingredients_lc" : "fr", "interface_version_created" : "import_csv_file - version 2019/09/17", "lang" : "fr", "lang_imported" : "fr", diff --git a/tests/integration/expected_test_results/convert_and_import_excel_file/test/products/3270190128403.json b/tests/integration/expected_test_results/convert_and_import_excel_file/test/products/3270190128403.json index 56b761b0a0175..0e7758684f26a 100644 --- a/tests/integration/expected_test_results/convert_and_import_excel_file/test/products/3270190128403.json +++ b/tests/integration/expected_test_results/convert_and_import_excel_file/test/products/3270190128403.json @@ -600,6 +600,7 @@ "en:legume", "en:lentils" ], + "ingredients_lc" : "fr", "ingredients_n" : 1, "ingredients_n_tags" : [ "1", diff --git a/tests/integration/expected_test_results/convert_and_import_excel_file/test/products/4270190128403.json b/tests/integration/expected_test_results/convert_and_import_excel_file/test/products/4270190128403.json index df8a7b48d3d44..60228842e9ed4 100644 --- a/tests/integration/expected_test_results/convert_and_import_excel_file/test/products/4270190128403.json +++ b/tests/integration/expected_test_results/convert_and_import_excel_file/test/products/4270190128403.json @@ -5,11 +5,17 @@ "test" ], "added_countries_tags" : [], + "additives_n" : 0, + "additives_old_n" : 0, + "additives_old_tags" : [], + "additives_original_tags" : [], + "additives_tags" : [], "allergens" : "", "allergens_from_ingredients" : "", - "allergens_from_user" : "(en) ", + "allergens_from_user" : "(fr) ", "allergens_hierarchy" : [], "allergens_tags" : [], + "amino_acids_tags" : [], "brands" : "Test", "brands_imported" : "Test", "brands_tags" : [ @@ -49,7 +55,7 @@ "4xxxxxxxxxxxx" ], "complete" : 0, - "completeness" : 0.3, + "completeness" : 0.4, "correctors_tags" : [], "countries" : "Etats-Unis", "countries_hierarchy" : [ @@ -66,6 +72,7 @@ "data_quality_errors_tags" : [], "data_quality_info_tags" : [ "en:no-packaging-data", + "en:ingredients-percent-analysis-ok", "en:ecoscore-extended-data-not-computed", "en:food-groups-1-unknown", "en:food-groups-2-unknown", @@ -73,22 +80,25 @@ ], "data_quality_tags" : [ "en:no-packaging-data", + "en:ingredients-percent-analysis-ok", "en:ecoscore-extended-data-not-computed", "en:food-groups-1-unknown", "en:food-groups-2-unknown", "en:food-groups-3-unknown", + "en:ingredients-unknown-score-above-0", + "en:ingredients-100-percent-unknown", "en:nutri-score-grade-from-producer-does-not-match-calculated-grade", "en:ecoscore-origins-of-ingredients-origins-are-100-percent-unknown", "en:ecoscore-packaging-packaging-data-missing", - "en:ecoscore-production-system-no-label", - "en:ecoscore-threatened-species-ingredients-missing" + "en:ecoscore-production-system-no-label" ], "data_quality_warnings_tags" : [ + "en:ingredients-unknown-score-above-0", + "en:ingredients-100-percent-unknown", "en:nutri-score-grade-from-producer-does-not-match-calculated-grade", "en:ecoscore-origins-of-ingredients-origins-are-100-percent-unknown", "en:ecoscore-packaging-packaging-data-missing", - "en:ecoscore-production-system-no-label", - "en:ecoscore-threatened-species-ingredients-missing" + "en:ecoscore-production-system-no-label" ], "data_sources" : "Producers, Producer - test-food-company", "data_sources_imported" : "Producers, Producer - test-food-company", @@ -317,16 +327,13 @@ "value" : 0, "warning" : "no_label" }, - "threatened_species" : { - "warning" : "ingredients_missing" - } + "threatened_species" : {} }, "agribalyse" : { "warning" : "missing_agribalyse_match" }, "missing" : { "agb_category" : 1, - "ingredients" : 1, "labels" : 1, "origins" : 1, "packagings" : 1 @@ -348,10 +355,81 @@ "informers_tags" : [ "test-user" ], + "ingredients" : [ + { + "id" : "fr:white-peaches", + "percent_estimate" : 75, + "percent_max" : 100, + "percent_min" : 50, + "text" : "White peaches" + }, + { + "id" : "fr:high-fructose-corn-syrup", + "percent_estimate" : 25, + "percent_max" : 50, + "percent_min" : 0, + "text" : "high fructose corn syrup" + } + ], + "ingredients_analysis" : { + "en:palm-oil-content-unknown" : [ + "fr:white-peaches", + "fr:high-fructose-corn-syrup" + ], + "en:vegan-status-unknown" : [ + "fr:white-peaches", + "fr:high-fructose-corn-syrup" + ], + "en:vegetarian-status-unknown" : [ + "fr:white-peaches", + "fr:high-fructose-corn-syrup" + ] + }, + "ingredients_analysis_tags" : [ + "en:palm-oil-content-unknown", + "en:vegan-status-unknown", + "en:vegetarian-status-unknown" + ], + "ingredients_from_or_that_may_be_from_palm_oil_n" : 0, + "ingredients_from_palm_oil_n" : 0, + "ingredients_from_palm_oil_tags" : [], + "ingredients_hierarchy" : [ + "fr:white-peaches", + "fr:high-fructose-corn-syrup" + ], + "ingredients_lc" : "fr", + "ingredients_n" : 2, + "ingredients_n_tags" : [ + "2", + "1-10" + ], + "ingredients_original_tags" : [ + "fr:white-peaches", + "fr:high-fructose-corn-syrup" + ], + "ingredients_percent_analysis" : 1, + "ingredients_tags" : [ + "fr:white-peaches", + "fr:high-fructose-corn-syrup" + ], + "ingredients_text" : "White peaches, high fructose corn syrup", "ingredients_text_fr" : "White peaches, high fructose corn syrup", "ingredients_text_fr_imported" : "White peaches, high fructose corn syrup", + "ingredients_text_with_allergens" : "White peaches, high fructose corn syrup", "ingredients_text_with_allergens_fr" : "White peaches, high fructose corn syrup", + "ingredients_that_may_be_from_palm_oil_n" : 0, + "ingredients_that_may_be_from_palm_oil_tags" : [], + "ingredients_with_specified_percent_n" : 0, + "ingredients_with_specified_percent_sum" : 0, + "ingredients_with_unspecified_percent_n" : 2, + "ingredients_with_unspecified_percent_sum" : 100, + "ingredients_without_ciqual_codes" : [ + "fr:high-fructose-corn-syrup", + "fr:white-peaches" + ], + "ingredients_without_ciqual_codes_n" : 2, "interface_version_created" : "import_csv_file - version 2019/09/17", + "known_ingredients_n" : 0, "lang" : "en", "lang_imported" : "en", "languages" : { @@ -374,6 +452,7 @@ "lc" : "en", "lc_imported" : "en", "main_countries_tags" : [], + "minerals_tags" : [], "misc_tags" : [ "en:nutrition-not-enough-data-to-compute-nutrition-score", "en:nutriscore-missing-nutrition-data", @@ -384,7 +463,7 @@ "en:nutriscore-missing-nutrition-data-proteins", "en:nutrition-no-fiber", "en:nutriscore-not-computed", - "en:nutrition-no-fruits-vegetables-nuts", + "en:nutrition-fruits-vegetables-nuts-estimate-from-ingredients", "en:nutrition-no-fiber-or-fruits-vegetables-nuts", "en:packagings-number-of-components-0", "en:packagings-not-complete", @@ -393,11 +472,12 @@ "en:ecoscore-not-computed", "en:main-countries-new-product" ], - "nova_group_debug" : "no nova group when the product does not have ingredients", - "nova_group_error" : "missing_ingredients", + "nova_group_debug" : "no nova group if too many ingredients are unknown: 2 out of 2", + "nova_group_error" : "too_many_unknown_ingredients", "nova_groups_tags" : [ "unknown" ], + "nucleotides_tags" : [], "nutrient_levels" : {}, "nutrient_levels_tags" : [], "nutriments" : { @@ -408,7 +488,9 @@ "energy-kj_value" : 500, "energy_100g" : 500, "energy_unit" : "kJ", - "energy_value" : 500 + "energy_value" : 500, + "fruits-vegetables-nuts-estimate-from-ingredients_100g" : 0, + "fruits-vegetables-nuts-estimate-from-ingredients_serving" : 0 }, "nutriscore" : { "2021" : { @@ -475,8 +557,10 @@ ], "nutrition_score_beverage" : 0, "nutrition_score_debug" : "missing fat_100g - missing saturated-fat_100g - missing sugars_100g - missing sodium_100g - missing proteins_100g", + "nutrition_score_warning_fruits_vegetables_nuts_estimate_from_ingredients" : 1, + "nutrition_score_warning_fruits_vegetables_nuts_estimate_from_ingredients_value" : 0, "nutrition_score_warning_no_fiber" : 1, - "nutrition_score_warning_no_fruits_vegetables_nuts" : 1, + "other_nutritional_substances_tags" : [], "owner" : "org-test-org", "owner_fields" : "--ignore--", "owners_tags" : "org-test-org", @@ -522,11 +606,11 @@ "url" : null } ], - "states" : "en:to-be-completed, en:nutrition-facts-completed, en:ingredients-to-be-completed, en:expiration-date-to-be-completed, en:packaging-code-to-be-completed, en:characteristics-to-be-completed, en:origins-to-be-completed, en:categories-completed, en:brands-completed, en:packaging-to-be-completed, en:quantity-to-be-completed, en:product-name-to-be-completed, en:photos-to-be-uploaded", + "states" : "en:to-be-completed, en:nutrition-facts-completed, en:ingredients-completed, en:expiration-date-to-be-completed, en:packaging-code-to-be-completed, en:characteristics-to-be-completed, en:origins-to-be-completed, en:categories-completed, en:brands-completed, en:packaging-to-be-completed, en:quantity-to-be-completed, en:product-name-to-be-completed, en:photos-to-be-uploaded", "states_hierarchy" : [ "en:to-be-completed", "en:nutrition-facts-completed", - "en:ingredients-to-be-completed", + "en:ingredients-completed", "en:expiration-date-to-be-completed", "en:packaging-code-to-be-completed", "en:characteristics-to-be-completed", @@ -541,7 +625,7 @@ "states_tags" : [ "en:to-be-completed", "en:nutrition-facts-completed", - "en:ingredients-to-be-completed", + "en:ingredients-completed", "en:expiration-date-to-be-completed", "en:packaging-code-to-be-completed", "en:characteristics-to-be-completed", @@ -555,9 +639,11 @@ ], "traces" : "", "traces_from_ingredients" : "", - "traces_from_user" : "(en) ", + "traces_from_user" : "(fr) ", "traces_hierarchy" : [], "traces_tags" : [], + "unknown_ingredients_n" : 2, "unknown_nutrients_tags" : [], + "vitamins_tags" : [], "weighers_tags" : [] } diff --git a/tests/integration/expected_test_results/convert_and_import_excel_file/test/products/5270190128403.json b/tests/integration/expected_test_results/convert_and_import_excel_file/test/products/5270190128403.json index 50c44059807de..6060be76e69c3 100644 --- a/tests/integration/expected_test_results/convert_and_import_excel_file/test/products/5270190128403.json +++ b/tests/integration/expected_test_results/convert_and_import_excel_file/test/products/5270190128403.json @@ -369,6 +369,7 @@ "en:banana", "en:fruit" ], + "ingredients_lc" : "fr", "ingredients_n" : 1, "ingredients_n_tags" : [ "1", diff --git a/tests/integration/expected_test_results/convert_and_import_excel_file/test/products/7270190128403.json b/tests/integration/expected_test_results/convert_and_import_excel_file/test/products/7270190128403.json index 03a36235dc116..1cc192bf9f9fd 100644 --- a/tests/integration/expected_test_results/convert_and_import_excel_file/test/products/7270190128403.json +++ b/tests/integration/expected_test_results/convert_and_import_excel_file/test/products/7270190128403.json @@ -337,6 +337,7 @@ "informers_tags" : [ "test-user" ], + "ingredients_lc" : "en", "interface_version_created" : "import_csv_file - version 2019/09/17", "lang" : "en", "lang_imported" : "en", diff --git a/tests/integration/expected_test_results/data_quality_knowledge_panel/data-quality.json b/tests/integration/expected_test_results/data_quality_knowledge_panel/data-quality.json index 9719bc5ab77eb..f7f59d5419389 100644 --- a/tests/integration/expected_test_results/data_quality_knowledge_panel/data-quality.json +++ b/tests/integration/expected_test_results/data_quality_knowledge_panel/data-quality.json @@ -370,7 +370,7 @@ { "element_type" : "text", "text_element" : { - "html" : "water, test_ingredient" + "html" : "en: water, test_ingredient" } }, { diff --git a/tests/integration/expected_test_results/data_quality_knowledge_panel/no-data-quality.json b/tests/integration/expected_test_results/data_quality_knowledge_panel/no-data-quality.json index 647119ac32cf2..4a3544d20d3fd 100644 --- a/tests/integration/expected_test_results/data_quality_knowledge_panel/no-data-quality.json +++ b/tests/integration/expected_test_results/data_quality_knowledge_panel/no-data-quality.json @@ -332,7 +332,7 @@ { "element_type" : "text", "text_element" : { - "html" : "water, test_ingredient" + "html" : "en: water, test_ingredient" } }, { diff --git a/tests/integration/expected_test_results/import_csv_file/replace_existing_values/3003004006001.json b/tests/integration/expected_test_results/import_csv_file/replace_existing_values/3003004006001.json index 916b526a792d8..d879330b28b71 100644 --- a/tests/integration/expected_test_results/import_csv_file/replace_existing_values/3003004006001.json +++ b/tests/integration/expected_test_results/import_csv_file/replace_existing_values/3003004006001.json @@ -532,6 +532,7 @@ "informers_tags" : [ "test-user" ], + "ingredients_lc" : "fr", "interface_version_created" : "import_csv_file - version 2019/09/17", "lang" : "fr", "lang_imported" : "fr", diff --git a/tests/integration/expected_test_results/import_csv_file/replace_existing_values/3003004006002.json b/tests/integration/expected_test_results/import_csv_file/replace_existing_values/3003004006002.json index dd625a7646be8..5496504c1c009 100644 --- a/tests/integration/expected_test_results/import_csv_file/replace_existing_values/3003004006002.json +++ b/tests/integration/expected_test_results/import_csv_file/replace_existing_values/3003004006002.json @@ -347,6 +347,7 @@ "informers_tags" : [ "test-user" ], + "ingredients_lc" : "fr", "interface_version_created" : "import_csv_file - version 2019/09/17", "lang" : "fr", "lang_imported" : "fr", diff --git a/tests/integration/expected_test_results/import_csv_file/replace_existing_values/3003004006003.json b/tests/integration/expected_test_results/import_csv_file/replace_existing_values/3003004006003.json index 3154d25fd35f8..9fce12608f8b4 100644 --- a/tests/integration/expected_test_results/import_csv_file/replace_existing_values/3003004006003.json +++ b/tests/integration/expected_test_results/import_csv_file/replace_existing_values/3003004006003.json @@ -342,6 +342,7 @@ "informers_tags" : [ "test-user" ], + "ingredients_lc" : "fr", "interface_version_created" : "import_csv_file - version 2019/09/17", "lang" : "fr", "lang_imported" : "fr", diff --git a/tests/integration/expected_test_results/import_csv_file/replace_existing_values/3003004006004.json b/tests/integration/expected_test_results/import_csv_file/replace_existing_values/3003004006004.json index ff9f665ac6407..d039cfd2e31f2 100644 --- a/tests/integration/expected_test_results/import_csv_file/replace_existing_values/3003004006004.json +++ b/tests/integration/expected_test_results/import_csv_file/replace_existing_values/3003004006004.json @@ -554,6 +554,7 @@ "informers_tags" : [ "test-user" ], + "ingredients_lc" : "en", "interface_version_created" : "import_csv_file - version 2019/09/17", "lang" : "en", "lang_imported" : "en", diff --git a/tests/integration/expected_test_results/import_csv_file/replace_existing_values/3003004006005.json b/tests/integration/expected_test_results/import_csv_file/replace_existing_values/3003004006005.json index fb4b6afe1d779..e2c21a14b20f6 100644 --- a/tests/integration/expected_test_results/import_csv_file/replace_existing_values/3003004006005.json +++ b/tests/integration/expected_test_results/import_csv_file/replace_existing_values/3003004006005.json @@ -357,6 +357,7 @@ "informers_tags" : [ "test-user" ], + "ingredients_lc" : "en", "interface_version_created" : "import_csv_file - version 2019/09/17", "lang" : "en", "lang_imported" : "en", diff --git a/tests/integration/expected_test_results/import_csv_file/replace_existing_values/3003004006006.json b/tests/integration/expected_test_results/import_csv_file/replace_existing_values/3003004006006.json index 9f89906fd4bc0..f5e53b8b5b8e0 100644 --- a/tests/integration/expected_test_results/import_csv_file/replace_existing_values/3003004006006.json +++ b/tests/integration/expected_test_results/import_csv_file/replace_existing_values/3003004006006.json @@ -351,6 +351,7 @@ "informers_tags" : [ "test-user" ], + "ingredients_lc" : "en", "interface_version_created" : "import_csv_file - version 2019/09/17", "lang" : "en", "lang_imported" : "en", diff --git a/tests/integration/expected_test_results/import_csv_file/replace_existing_values/3003004006007.json b/tests/integration/expected_test_results/import_csv_file/replace_existing_values/3003004006007.json index 0a34253048072..905a1a0a80630 100644 --- a/tests/integration/expected_test_results/import_csv_file/replace_existing_values/3003004006007.json +++ b/tests/integration/expected_test_results/import_csv_file/replace_existing_values/3003004006007.json @@ -345,6 +345,7 @@ "informers_tags" : [ "test-user" ], + "ingredients_lc" : "en", "interface_version_created" : "import_csv_file - version 2019/09/17", "lang" : "en", "lang_imported" : "en", diff --git a/tests/integration/expected_test_results/import_csv_file/test/2003004006001.json b/tests/integration/expected_test_results/import_csv_file/test/2003004006001.json index 92028afd8a57f..40e235e6b352d 100644 --- a/tests/integration/expected_test_results/import_csv_file/test/2003004006001.json +++ b/tests/integration/expected_test_results/import_csv_file/test/2003004006001.json @@ -524,6 +524,7 @@ "informers_tags" : [ "test-user" ], + "ingredients_lc" : "fr", "interface_version_created" : "import_csv_file - version 2019/09/17", "lang" : "fr", "lang_imported" : "fr", diff --git a/tests/integration/expected_test_results/import_csv_file/test/2003004006002.json b/tests/integration/expected_test_results/import_csv_file/test/2003004006002.json index d94b8597d8466..1ca3dc682fda7 100644 --- a/tests/integration/expected_test_results/import_csv_file/test/2003004006002.json +++ b/tests/integration/expected_test_results/import_csv_file/test/2003004006002.json @@ -339,6 +339,7 @@ "informers_tags" : [ "test-user" ], + "ingredients_lc" : "fr", "interface_version_created" : "import_csv_file - version 2019/09/17", "lang" : "fr", "lang_imported" : "fr", diff --git a/tests/integration/expected_test_results/import_csv_file/test/2003004006003.json b/tests/integration/expected_test_results/import_csv_file/test/2003004006003.json index 8fdf4b38474a0..ad61638c9fb17 100644 --- a/tests/integration/expected_test_results/import_csv_file/test/2003004006003.json +++ b/tests/integration/expected_test_results/import_csv_file/test/2003004006003.json @@ -342,6 +342,7 @@ "informers_tags" : [ "test-user" ], + "ingredients_lc" : "fr", "interface_version_created" : "import_csv_file - version 2019/09/17", "lang" : "fr", "lang_imported" : "fr", diff --git a/tests/integration/expected_test_results/import_csv_file/test/2003004006004.json b/tests/integration/expected_test_results/import_csv_file/test/2003004006004.json index 28cdee8bc1807..9c52d30661995 100644 --- a/tests/integration/expected_test_results/import_csv_file/test/2003004006004.json +++ b/tests/integration/expected_test_results/import_csv_file/test/2003004006004.json @@ -517,6 +517,7 @@ "informers_tags" : [ "test-user" ], + "ingredients_lc" : "en", "interface_version_created" : "import_csv_file - version 2019/09/17", "lang" : "en", "lang_imported" : "en", diff --git a/tests/integration/expected_test_results/import_csv_file/test/2003004006005.json b/tests/integration/expected_test_results/import_csv_file/test/2003004006005.json index adc27c716ff6e..5cb71a8847873 100644 --- a/tests/integration/expected_test_results/import_csv_file/test/2003004006005.json +++ b/tests/integration/expected_test_results/import_csv_file/test/2003004006005.json @@ -349,6 +349,7 @@ "informers_tags" : [ "test-user" ], + "ingredients_lc" : "en", "interface_version_created" : "import_csv_file - version 2019/09/17", "lang" : "en", "lang_imported" : "en", diff --git a/tests/integration/expected_test_results/import_csv_file/test/2003004006006.json b/tests/integration/expected_test_results/import_csv_file/test/2003004006006.json index 492e92e91b1bc..eb5e27154c2aa 100644 --- a/tests/integration/expected_test_results/import_csv_file/test/2003004006006.json +++ b/tests/integration/expected_test_results/import_csv_file/test/2003004006006.json @@ -349,6 +349,7 @@ "informers_tags" : [ "test-user" ], + "ingredients_lc" : "en", "interface_version_created" : "import_csv_file - version 2019/09/17", "lang" : "en", "lang_imported" : "en", diff --git a/tests/integration/expected_test_results/import_csv_file/test/2003004006007.json b/tests/integration/expected_test_results/import_csv_file/test/2003004006007.json index 59cd2bea06e32..fbd30658d0f79 100644 --- a/tests/integration/expected_test_results/import_csv_file/test/2003004006007.json +++ b/tests/integration/expected_test_results/import_csv_file/test/2003004006007.json @@ -345,6 +345,7 @@ "informers_tags" : [ "test-user" ], + "ingredients_lc" : "en", "interface_version_created" : "import_csv_file - version 2019/09/17", "lang" : "en", "lang_imported" : "en", diff --git a/tests/integration/expected_test_results/protected_product/get-edited-protected-product-api-v2-moderator.json b/tests/integration/expected_test_results/protected_product/get-edited-protected-product-api-v2-moderator.json index a5e945ced4eb3..38c0a4c3f5c67 100644 --- a/tests/integration/expected_test_results/protected_product/get-edited-protected-product-api-v2-moderator.json +++ b/tests/integration/expected_test_results/protected_product/get-edited-protected-product-api-v2-moderator.json @@ -496,6 +496,7 @@ "en:vegetable-oil-and-fat", "en:palm-oil-and-fat" ], + "ingredients_lc" : "en", "ingredients_n" : 4, "ingredients_n_tags" : [ "4", diff --git a/tests/integration/expected_test_results/protected_product/get-edited-protected-product-api-v2.json b/tests/integration/expected_test_results/protected_product/get-edited-protected-product-api-v2.json index 1dee3a8851d9f..130d25cb80b1d 100644 --- a/tests/integration/expected_test_results/protected_product/get-edited-protected-product-api-v2.json +++ b/tests/integration/expected_test_results/protected_product/get-edited-protected-product-api-v2.json @@ -495,6 +495,7 @@ "en:vegetable-oil-and-fat", "en:palm-oil-and-fat" ], + "ingredients_lc" : "en", "ingredients_n" : 4, "ingredients_n_tags" : [ "4", diff --git a/tests/integration/expected_test_results/protected_product/get-edited-protected-product-web-form-moderator.json b/tests/integration/expected_test_results/protected_product/get-edited-protected-product-web-form-moderator.json index c2e5f82199a68..1502ede439aa3 100644 --- a/tests/integration/expected_test_results/protected_product/get-edited-protected-product-web-form-moderator.json +++ b/tests/integration/expected_test_results/protected_product/get-edited-protected-product-web-form-moderator.json @@ -500,6 +500,7 @@ "en:vegetable-oil-and-fat", "en:palm-oil-and-fat" ], + "ingredients_lc" : "en", "ingredients_n" : 4, "ingredients_n_tags" : [ "4", diff --git a/tests/integration/expected_test_results/protected_product/get-edited-protected-product-web-form.json b/tests/integration/expected_test_results/protected_product/get-edited-protected-product-web-form.json index cd4c78d90baee..7ce5d40263212 100644 --- a/tests/integration/expected_test_results/protected_product/get-edited-protected-product-web-form.json +++ b/tests/integration/expected_test_results/protected_product/get-edited-protected-product-web-form.json @@ -499,6 +499,7 @@ "en:vegetable-oil-and-fat", "en:palm-oil-and-fat" ], + "ingredients_lc" : "en", "ingredients_n" : 4, "ingredients_n_tags" : [ "4", diff --git a/tests/integration/expected_test_results/protected_product/get-edited-unprotected-product-api-v2.json b/tests/integration/expected_test_results/protected_product/get-edited-unprotected-product-api-v2.json index ad22bbfc121cc..9d95d1ddd47e5 100644 --- a/tests/integration/expected_test_results/protected_product/get-edited-unprotected-product-api-v2.json +++ b/tests/integration/expected_test_results/protected_product/get-edited-unprotected-product-api-v2.json @@ -494,6 +494,7 @@ "en:vegetable-oil-and-fat", "en:palm-oil-and-fat" ], + "ingredients_lc" : "en", "ingredients_n" : 4, "ingredients_n_tags" : [ "4", diff --git a/tests/integration/expected_test_results/protected_product/get-edited-unprotected-product-web-form.json b/tests/integration/expected_test_results/protected_product/get-edited-unprotected-product-web-form.json index 3f94787fce97e..4d303bd05c645 100644 --- a/tests/integration/expected_test_results/protected_product/get-edited-unprotected-product-web-form.json +++ b/tests/integration/expected_test_results/protected_product/get-edited-unprotected-product-web-form.json @@ -498,6 +498,7 @@ "en:vegetable-oil-and-fat", "en:palm-oil-and-fat" ], + "ingredients_lc" : "en", "ingredients_n" : 4, "ingredients_n_tags" : [ "4", diff --git a/tests/integration/expected_test_results/search_v1/search-no-filter.json b/tests/integration/expected_test_results/search_v1/search-no-filter.json index 4fc80f6ab43f0..1e691dac19b0e 100644 --- a/tests/integration/expected_test_results/search_v1/search-no-filter.json +++ b/tests/integration/expected_test_results/search_v1/search-no-filter.json @@ -471,6 +471,7 @@ "en:vegetable-oil-and-fat", "en:palm-oil-and-fat" ], + "ingredients_lc" : "en", "ingredients_n" : 4, "ingredients_n_tags" : [ "4", @@ -1122,6 +1123,7 @@ "en:fruit", "en:rice" ], + "ingredients_lc" : "en", "ingredients_n" : 2, "ingredients_n_tags" : [ "2", @@ -1775,6 +1777,7 @@ "en:dairy", "en:egg" ], + "ingredients_lc" : "en", "ingredients_n" : 3, "ingredients_n_tags" : [ "3", @@ -2012,11 +2015,17 @@ "snack" ], "added_countries_tags" : [], + "additives_n" : 0, + "additives_old_n" : 0, + "additives_old_tags" : [], + "additives_original_tags" : [], + "additives_tags" : [], "allergens" : "", "allergens_from_ingredients" : "", - "allergens_from_user" : "(es) ", + "allergens_from_user" : "(en) ", "allergens_hierarchy" : [], "allergens_tags" : [], + "amino_acids_tags" : [], "categories" : "snacks", "categories_hierarchy" : [ "en:snacks" @@ -2049,7 +2058,7 @@ "2xxxxxxxxxxx" ], "complete" : 0, - "completeness" : 0.2, + "completeness" : 0.4, "correctors_tags" : [], "created_t" : "--ignore--", "creator" : "tests", @@ -2057,6 +2066,7 @@ "data_quality_errors_tags" : [], "data_quality_info_tags" : [ "en:no-packaging-data", + "en:ingredients-percent-analysis-ok", "en:ecoscore-extended-data-not-computed", "en:food-groups-1-unknown", "en:food-groups-2-unknown", @@ -2064,20 +2074,19 @@ ], "data_quality_tags" : [ "en:no-packaging-data", + "en:ingredients-percent-analysis-ok", "en:ecoscore-extended-data-not-computed", "en:food-groups-1-unknown", "en:food-groups-2-unknown", "en:food-groups-3-unknown", "en:ecoscore-origins-of-ingredients-origins-are-100-percent-unknown", "en:ecoscore-packaging-packaging-data-missing", - "en:ecoscore-production-system-no-label", - "en:ecoscore-threatened-species-ingredients-missing" + "en:ecoscore-production-system-no-label" ], "data_quality_warnings_tags" : [ "en:ecoscore-origins-of-ingredients-origins-are-100-percent-unknown", "en:ecoscore-packaging-packaging-data-missing", - "en:ecoscore-production-system-no-label", - "en:ecoscore-threatened-species-ingredients-missing" + "en:ecoscore-production-system-no-label" ], "ecoscore_data" : { "adjustments" : { @@ -2306,7 +2315,8 @@ "warning" : "no_label" }, "threatened_species" : { - "warning" : "ingredients_missing" + "ingredient" : "en:palm-oil", + "value" : -10 } }, "agribalyse" : { @@ -2314,7 +2324,6 @@ }, "missing" : { "agb_category" : 1, - "ingredients" : 1, "labels" : 1, "origins" : 1, "packagings" : 1 @@ -2338,10 +2347,100 @@ "informers_tags" : [ "tests" ], + "ingredients" : [ + { + "ciqual_food_code" : "13050", + "id" : "en:apple", + "percent_estimate" : 66.6666666666667, + "percent_max" : 100, + "percent_min" : 33.3333333333333, + "rank" : 1, + "text" : "apple", + "vegan" : "yes", + "vegetarian" : "yes" + }, + { + "ciqual_food_code" : "18066", + "id" : "en:water", + "percent_estimate" : 16.6666666666667, + "percent_max" : 50, + "percent_min" : 0, + "rank" : 2, + "text" : "water", + "vegan" : "yes", + "vegetarian" : "yes" + }, + { + "ciqual_food_code" : "16129", + "from_palm_oil" : "yes", + "id" : "en:palm-oil", + "percent_estimate" : 16.6666666666667, + "percent_max" : 33.3333333333333, + "percent_min" : 0, + "rank" : 3, + "text" : "palm oil", + "vegan" : "yes", + "vegetarian" : "yes" + } + ], + "ingredients_analysis" : { + "en:palm-oil" : [ + "en:palm-oil" + ] + }, + "ingredients_analysis_tags" : [ + "en:palm-oil", + "en:vegan", + "en:vegetarian" + ], + "ingredients_from_or_that_may_be_from_palm_oil_n" : 0, + "ingredients_from_palm_oil_n" : 0, + "ingredients_from_palm_oil_tags" : [], + "ingredients_hierarchy" : [ + "en:apple", + "en:fruit", + "en:water", + "en:palm-oil", + "en:oil-and-fat", + "en:vegetable-oil-and-fat", + "en:palm-oil-and-fat" + ], + "ingredients_lc" : "en", + "ingredients_n" : 3, + "ingredients_n_tags" : [ + "3", + "1-10" + ], + "ingredients_original_tags" : [ + "en:apple", + "en:water", + "en:palm-oil" + ], + "ingredients_percent_analysis" : 1, + "ingredients_tags" : [ + "en:apple", + "en:fruit", + "en:water", + "en:palm-oil", + "en:oil-and-fat", + "en:vegetable-oil-and-fat", + "en:palm-oil-and-fat" + ], + "ingredients_text" : "apple, water, palm oil", "ingredients_text_en" : "apple, water, palm oil", + "ingredients_text_with_allergens" : "apple, water, palm oil", "ingredients_text_with_allergens_en" : "apple, water, palm oil", + "ingredients_that_may_be_from_palm_oil_n" : 0, + "ingredients_that_may_be_from_palm_oil_tags" : [], + "ingredients_with_specified_percent_n" : 0, + "ingredients_with_specified_percent_sum" : 0, + "ingredients_with_unspecified_percent_n" : 3, + "ingredients_with_unspecified_percent_sum" : 100, + "ingredients_without_ciqual_codes" : [], + "ingredients_without_ciqual_codes_n" : 0, "interface_version_created" : "20150316.jqm2", "interface_version_modified" : "20150316.jqm2", + "known_ingredients_n" : 7, "lang" : "es", "languages" : { "en:english" : 4 @@ -2363,6 +2462,7 @@ "lc" : "es", "link" : "http://world.openfoodfacts.org/", "main_countries_tags" : [], + "minerals_tags" : [], "misc_tags" : [ "en:nutrition-not-enough-data-to-compute-nutrition-score", "en:nutriscore-missing-nutrition-data", @@ -2373,9 +2473,12 @@ "en:nutriscore-missing-nutrition-data-sodium", "en:nutriscore-missing-nutrition-data-proteins", "en:nutrition-no-fiber", - "en:nutriscore-not-computed", - "en:nutrition-no-fruits-vegetables-nuts", - "en:nutrition-no-fiber-or-fruits-vegetables-nuts", + "en:nutriscore-using-estimated-nutrition-facts", + "en:nutriscore-computed", + "en:nutrition-fruits-vegetables-nuts-estimate-from-ingredients", + "en:nutrition-all-nutriscore-values-known", + "en:nutriscore-2021-same-as-2023", + "en:nutriscore-2021-d-2023-d", "en:packagings-number-of-components-0", "en:packagings-not-complete", "en:packagings-empty", @@ -2383,79 +2486,212 @@ "en:ecoscore-not-computed", "en:main-countries-new-product" ], - "nova_group_debug" : "no nova group when the product does not have ingredients", - "nova_group_error" : "missing_ingredients", + "nova_group" : 1, + "nova_group_debug" : "", + "nova_groups" : "1", + "nova_groups_markers" : {}, "nova_groups_tags" : [ - "unknown" + "en:1-unprocessed-or-minimally-processed-foods" ], + "nucleotides_tags" : [], "nutrient_levels" : {}, "nutrient_levels_tags" : [], - "nutriments" : {}, + "nutriments" : { + "fruits-vegetables-nuts-estimate-from-ingredients_100g" : 33.3333333333333, + "fruits-vegetables-nuts-estimate-from-ingredients_serving" : 33.3333333333333, + "nova-group" : 1, + "nova-group_100g" : 1, + "nova-group_serving" : 1, + "nutrition-score-fr" : 11, + "nutrition-score-fr_100g" : 11 + }, + "nutriments_estimated" : { + "alcohol_100g" : 0, + "beta-carotene_100g" : 1.13333333333333e-05, + "calcium_100g" : 0.00452166666666667, + "carbohydrates_100g" : 7.13333333333333, + "cholesterol_100g" : 0, + "copper_100g" : 2.35e-05, + "energy-kcal_100g" : 182.6, + "energy-kj_100g" : 754.666666666666, + "energy_100g" : 754.666666666666, + "fat_100g" : 16.7533333333333, + "fiber_100g" : 0.866666666666667, + "fructose_100g" : 4.02, + "galactose_100g" : 0, + "glucose_100g" : 2.16666666666667, + "iodine_100g" : 9.66666666666666e-07, + "iron_100g" : 5.33333333333333e-05, + "lactose_100g" : 0, + "magnesium_100g" : 0.00283166666666667, + "maltose_100g" : 0, + "manganese_100g" : 2.5595e-05, + "pantothenic-acid_100g" : 4.73333333333333e-05, + "phosphorus_100g" : 0.00733333333333333, + "phylloquinone_100g" : 1.73333333333333e-06, + "polyols_100g" : 0.393333333333333, + "potassium_100g" : 0.0601216666666667, + "proteins_100g" : 0.18, + "salt_100g" : 0.00126666666666667, + "saturated-fat_100g" : 8.23066666666666, + "selenium_100g" : 1.43333333333333e-06, + "sodium_100g" : 0.0004, + "starch_100g" : 0, + "sucrose_100g" : 0.546666666666667, + "sugars_100g" : 6.73333333333333, + "vitamin-a_100g" : 0, + "vitamin-b12_100g" : 0, + "vitamin-b1_100g" : 1.26666666666667e-05, + "vitamin-b2_100g" : 1.86666666666667e-05, + "vitamin-b6_100g" : 2.46666666666667e-05, + "vitamin-b9_100g" : 0, + "vitamin-c_100g" : 0.00266666666666667, + "vitamin-d_100g" : 0, + "vitamin-e_100g" : 0.00268333333333333, + "vitamin-pp_100g" : 6.06666666666667e-05, + "water_100g" : 74.4666666666667, + "zinc_100g" : 3.51666666666667e-05 + }, "nutriscore" : { "2021" : { "category_available" : 1, "data" : { - "energy" : null, - "fiber" : 0, - "fruits_vegetables_nuts_colza_walnut_olive_oils" : 0, + "energy" : 754.666666666666, + "energy_points" : 2, + "energy_value" : 754.7, + "fiber" : 0.866666666666667, + "fiber_points" : 0, + "fiber_value" : 0.87, + "fruits_vegetables_nuts_colza_walnut_olive_oils" : 33.3333333333333, + "fruits_vegetables_nuts_colza_walnut_olive_oils_points" : 0, + "fruits_vegetables_nuts_colza_walnut_olive_oils_value" : 33.3, "is_beverage" : 0, "is_cheese" : 0, "is_fat" : 0, "is_water" : 0, - "proteins" : null, - "saturated_fat" : null, - "sodium" : null, - "sugars" : null + "negative_points" : 11, + "positive_points" : 0, + "proteins" : 0.18, + "proteins_points" : 0, + "proteins_value" : 0.18, + "saturated_fat" : 8.23066666666666, + "saturated_fat_points" : 8, + "saturated_fat_value" : 8.2, + "sodium" : 0.4, + "sodium_points" : 0, + "sodium_value" : 0.4, + "sugars" : 6.73333333333333, + "sugars_points" : 1, + "sugars_value" : 6.73 }, - "grade" : "unknown", - "nutrients_available" : 0, + "grade" : "d", + "nutrients_available" : 1, "nutriscore_applicable" : 1, - "nutriscore_computed" : 0 + "nutriscore_computed" : 1, + "score" : 11 }, "2023" : { "category_available" : 1, "data" : { - "energy" : null, - "fiber" : 0, - "fruits_vegetables_legumes" : 0, + "count_proteins" : 0, + "count_proteins_reason" : "negative_points_more_than_11", + "energy" : 754.666666666666, + "energy_points" : 2, + "fiber" : 0.866666666666667, + "fiber_points" : 0, + "fruits_vegetables_legumes" : 33.3333333333333, + "fruits_vegetables_legumes_points" : 0, "is_beverage" : 0, "is_cheese" : 0, "is_fat_oil_nuts_seeds" : 0, "is_water" : 0, - "proteins" : null, - "salt" : null, - "saturated_fat" : null, - "sugars" : null + "negative_nutrients" : [ + "energy", + "sugars", + "saturated_fat", + "salt", + "sweeteners" + ], + "negative_points" : 11, + "positive_nutrients" : [ + "fruits_vegetables_legumes", + "fiber" + ], + "positive_points" : 0, + "proteins" : 0.18, + "proteins_points" : 0, + "salt" : 0.00126666666666667, + "salt_points" : 0, + "saturated_fat" : 8.23066666666666, + "saturated_fat_points" : 8, + "sugars" : 6.73333333333333, + "sugars_points" : 1 }, - "grade" : "unknown", - "nutrients_available" : 0, + "grade" : "d", + "nutrients_available" : 1, "nutriscore_applicable" : 1, - "nutriscore_computed" : 0 + "nutriscore_computed" : 1, + "score" : 11 } }, "nutriscore_2021_tags" : [ - "unknown" + "d" ], "nutriscore_2023_tags" : [ - "unknown" + "d" ], - "nutriscore_grade" : "unknown", + "nutriscore_data" : { + "energy" : 754.666666666666, + "energy_points" : 2, + "energy_value" : 754.7, + "fiber" : 0.866666666666667, + "fiber_points" : 0, + "fiber_value" : 0.87, + "fruits_vegetables_nuts_colza_walnut_olive_oils" : 33.3333333333333, + "fruits_vegetables_nuts_colza_walnut_olive_oils_points" : 0, + "fruits_vegetables_nuts_colza_walnut_olive_oils_value" : 33.3, + "grade" : "d", + "is_beverage" : 0, + "is_cheese" : 0, + "is_fat" : 0, + "is_water" : 0, + "negative_points" : 11, + "positive_points" : 0, + "proteins" : 0.18, + "proteins_points" : 0, + "proteins_value" : 0.18, + "saturated_fat" : 8.23066666666666, + "saturated_fat_points" : 8, + "saturated_fat_value" : 8.2, + "score" : 11, + "sodium" : 0.4, + "sodium_points" : 0, + "sodium_value" : 0.4, + "sugars" : 6.73333333333333, + "sugars_points" : 1, + "sugars_value" : 6.73 + }, + "nutriscore_grade" : "d", + "nutriscore_score" : 11, + "nutriscore_score_opposite" : -11, "nutriscore_tags" : [ - "unknown" + "d" ], "nutriscore_version" : "2021", "nutrition_data_per" : "100g", "nutrition_data_prepared_per" : "100g", - "nutrition_grade_fr" : "unknown", - "nutrition_grades" : "unknown", + "nutrition_grade_fr" : "d", + "nutrition_grades" : "d", "nutrition_grades_tags" : [ - "unknown" + "d" ], "nutrition_score_beverage" : 0, "nutrition_score_debug" : "missing energy_100g - missing fat_100g - missing saturated-fat_100g - missing sugars_100g - missing sodium_100g - missing proteins_100g", - "nutrition_score_warning_no_fiber" : 1, - "nutrition_score_warning_no_fruits_vegetables_nuts" : 1, + "nutrition_score_warning_fruits_vegetables_nuts_estimate_from_ingredients" : 1, + "nutrition_score_warning_fruits_vegetables_nuts_estimate_from_ingredients_value" : 33.3333333333333, + "nutrition_score_warning_nutriments_estimated" : 1, "origin_en" : "spain", + "other_nutritional_substances_tags" : [], "packaging_materials_tags" : [], "packaging_recycling_tags" : [], "packaging_shapes_tags" : [], @@ -2480,11 +2716,11 @@ "rev" : 1, "serving_quantity" : 10, "serving_size" : "10 g", - "states" : "en:to-be-completed, en:nutrition-facts-to-be-completed, en:ingredients-to-be-completed, en:expiration-date-to-be-completed, en:packaging-code-to-be-completed, en:characteristics-to-be-completed, en:origins-to-be-completed, en:categories-completed, en:brands-to-be-completed, en:packaging-to-be-completed, en:quantity-completed, en:product-name-to-be-completed, en:photos-to-be-uploaded", + "states" : "en:to-be-completed, en:nutrition-facts-completed, en:ingredients-completed, en:expiration-date-to-be-completed, en:packaging-code-to-be-completed, en:characteristics-to-be-completed, en:origins-to-be-completed, en:categories-completed, en:brands-to-be-completed, en:packaging-to-be-completed, en:quantity-completed, en:product-name-to-be-completed, en:photos-to-be-uploaded", "states_hierarchy" : [ "en:to-be-completed", - "en:nutrition-facts-to-be-completed", - "en:ingredients-to-be-completed", + "en:nutrition-facts-completed", + "en:ingredients-completed", "en:expiration-date-to-be-completed", "en:packaging-code-to-be-completed", "en:characteristics-to-be-completed", @@ -2498,8 +2734,8 @@ ], "states_tags" : [ "en:to-be-completed", - "en:nutrition-facts-to-be-completed", - "en:ingredients-to-be-completed", + "en:nutrition-facts-completed", + "en:ingredients-completed", "en:expiration-date-to-be-completed", "en:packaging-code-to-be-completed", "en:characteristics-to-be-completed", @@ -2513,11 +2749,13 @@ ], "traces" : "", "traces_from_ingredients" : "", - "traces_from_user" : "(es) ", + "traces_from_user" : "(en) ", "traces_hierarchy" : [], "traces_tags" : [], + "unknown_ingredients_n" : 0, "unknown_nutrients_tags" : [], "url" : "http://world.openfoodfacts.localhost/product/200000000039/vegan-test-snack-with-palm-oil", + "vitamins_tags" : [], "weighers_tags" : [] }, { @@ -2527,11 +2765,17 @@ "cereal" ], "added_countries_tags" : [], + "additives_n" : 0, + "additives_old_n" : 0, + "additives_old_tags" : [], + "additives_original_tags" : [], + "additives_tags" : [], "allergens" : "", "allergens_from_ingredients" : "", - "allergens_from_user" : "(es) ", + "allergens_from_user" : "(en) ", "allergens_hierarchy" : [], "allergens_tags" : [], + "amino_acids_tags" : [], "categories" : "breakfast cereals", "categories_hierarchy" : [ "en:plant-based-foods-and-beverages", @@ -2580,7 +2824,7 @@ "2xxxxxxxxxxx" ], "complete" : 0, - "completeness" : 0.2, + "completeness" : 0.4, "correctors_tags" : [], "created_t" : "--ignore--", "creator" : "tests", @@ -2588,6 +2832,7 @@ "data_quality_errors_tags" : [], "data_quality_info_tags" : [ "en:no-packaging-data", + "en:ingredients-percent-analysis-ok", "en:ecoscore-extended-data-not-computed", "en:food-groups-1-known", "en:food-groups-2-known", @@ -2595,20 +2840,19 @@ ], "data_quality_tags" : [ "en:no-packaging-data", + "en:ingredients-percent-analysis-ok", "en:ecoscore-extended-data-not-computed", "en:food-groups-1-known", "en:food-groups-2-known", "en:food-groups-3-unknown", "en:ecoscore-origins-of-ingredients-origins-are-100-percent-unknown", "en:ecoscore-packaging-packaging-data-missing", - "en:ecoscore-production-system-no-label", - "en:ecoscore-threatened-species-ingredients-missing" + "en:ecoscore-production-system-no-label" ], "data_quality_warnings_tags" : [ "en:ecoscore-origins-of-ingredients-origins-are-100-percent-unknown", "en:ecoscore-packaging-packaging-data-missing", - "en:ecoscore-production-system-no-label", - "en:ecoscore-threatened-species-ingredients-missing" + "en:ecoscore-production-system-no-label" ], "ecoscore_data" : { "adjustments" : { @@ -2836,9 +3080,7 @@ "value" : 0, "warning" : "no_label" }, - "threatened_species" : { - "warning" : "ingredients_missing" - } + "threatened_species" : {} }, "agribalyse" : { "agribalyse_proxy_food_code" : "32135", @@ -2931,7 +3173,6 @@ "xk" : "d" }, "missing" : { - "ingredients" : 1, "labels" : 1, "origins" : 1, "packagings" : 1 @@ -3025,10 +3266,75 @@ "informers_tags" : [ "tests" ], + "ingredients" : [ + { + "ciqual_food_code" : "13050", + "id" : "en:apple", + "percent_estimate" : 75, + "percent_max" : 100, + "percent_min" : 50, + "rank" : 1, + "text" : "apple", + "vegan" : "yes", + "vegetarian" : "yes" + }, + { + "ciqual_food_code" : "18066", + "id" : "en:water", + "percent_estimate" : 25, + "percent_max" : 50, + "percent_min" : 0, + "rank" : 2, + "text" : "water", + "vegan" : "yes", + "vegetarian" : "yes" + } + ], + "ingredients_analysis" : {}, + "ingredients_analysis_tags" : [ + "en:palm-oil-free", + "en:vegan", + "en:vegetarian" + ], + "ingredients_from_or_that_may_be_from_palm_oil_n" : 0, + "ingredients_from_palm_oil_n" : 0, + "ingredients_from_palm_oil_tags" : [], + "ingredients_hierarchy" : [ + "en:apple", + "en:fruit", + "en:water" + ], + "ingredients_lc" : "en", + "ingredients_n" : 2, + "ingredients_n_tags" : [ + "2", + "1-10" + ], + "ingredients_original_tags" : [ + "en:apple", + "en:water" + ], + "ingredients_percent_analysis" : 1, + "ingredients_tags" : [ + "en:apple", + "en:fruit", + "en:water" + ], + "ingredients_text" : "apple, water", "ingredients_text_en" : "apple, water", + "ingredients_text_with_allergens" : "apple, water", "ingredients_text_with_allergens_en" : "apple, water", + "ingredients_that_may_be_from_palm_oil_n" : 0, + "ingredients_that_may_be_from_palm_oil_tags" : [], + "ingredients_with_specified_percent_n" : 0, + "ingredients_with_specified_percent_sum" : 0, + "ingredients_with_unspecified_percent_n" : 2, + "ingredients_with_unspecified_percent_sum" : 100, + "ingredients_without_ciqual_codes" : [], + "ingredients_without_ciqual_codes_n" : 0, "interface_version_created" : "20150316.jqm2", "interface_version_modified" : "20150316.jqm2", + "known_ingredients_n" : 3, "lang" : "es", "languages" : { "en:english" : 5 @@ -3050,6 +3356,7 @@ "lc" : "es", "link" : "http://world.openfoodfacts.org/", "main_countries_tags" : [], + "minerals_tags" : [], "misc_tags" : [ "en:nutrition-not-enough-data-to-compute-nutrition-score", "en:nutriscore-missing-nutrition-data", @@ -3060,9 +3367,13 @@ "en:nutriscore-missing-nutrition-data-sodium", "en:nutriscore-missing-nutrition-data-proteins", "en:nutrition-no-fiber", - "en:nutriscore-not-computed", - "en:nutrition-no-fruits-vegetables-nuts", - "en:nutrition-no-fiber-or-fruits-vegetables-nuts", + "en:nutriscore-using-estimated-nutrition-facts", + "en:nutriscore-computed", + "en:nutrition-fruits-vegetables-nuts-estimate-from-ingredients", + "en:nutrition-all-nutriscore-values-known", + "en:nutriscore-2021-different-from-2023", + "en:nutriscore-2021-better-than-2023", + "en:nutriscore-2021-a-2023-b", "en:packagings-number-of-components-0", "en:packagings-not-complete", "en:packagings-empty", @@ -3077,79 +3388,213 @@ "en:ecoscore-grade-changed", "en:main-countries-new-product" ], - "nova_group_debug" : "no nova group when the product does not have ingredients", - "nova_group_error" : "missing_ingredients", + "nova_group" : 1, + "nova_group_debug" : "", + "nova_groups" : "1", + "nova_groups_markers" : {}, "nova_groups_tags" : [ - "unknown" + "en:1-unprocessed-or-minimally-processed-foods" ], + "nucleotides_tags" : [], "nutrient_levels" : {}, "nutrient_levels_tags" : [], - "nutriments" : {}, + "nutriments" : { + "fruits-vegetables-nuts-estimate-from-ingredients_100g" : 50, + "fruits-vegetables-nuts-estimate-from-ingredients_serving" : 50, + "nova-group" : 1, + "nova-group_100g" : 1, + "nova-group_serving" : 1, + "nutrition-score-fr" : -1, + "nutrition-score-fr_100g" : -1 + }, + "nutriments_estimated" : { + "alcohol_100g" : 0, + "beta-carotene_100g" : 1.275e-05, + "calcium_100g" : 0.0055325, + "carbohydrates_100g" : 8.025, + "cholesterol_100g" : 0, + "copper_100g" : 2.75e-05, + "energy-kcal_100g" : 36.675, + "energy-kj_100g" : 155.25, + "energy_100g" : 155.25, + "fat_100g" : 0.0975, + "fiber_100g" : 0.975, + "fructose_100g" : 4.5225, + "galactose_100g" : 0, + "glucose_100g" : 2.4375, + "iodine_100g" : 7.5e-08, + "iron_100g" : 6e-05, + "lactose_100g" : 0, + "magnesium_100g" : 0.0032475, + "maltose_100g" : 0, + "manganese_100g" : 2.8705e-05, + "pantothenic-acid_100g" : 5.325e-05, + "phosphorus_100g" : 0.00825, + "phylloquinone_100g" : 4.5e-07, + "polyols_100g" : 0.4425, + "potassium_100g" : 0.0676825, + "proteins_100g" : 0.2025, + "salt_100g" : 0.0019, + "saturated-fat_100g" : 0.01575, + "selenium_100g" : 2.375e-07, + "sodium_100g" : 0.0006, + "starch_100g" : 0, + "sucrose_100g" : 0.615, + "sugars_100g" : 7.575, + "vitamin-a_100g" : 0, + "vitamin-b12_100g" : 0, + "vitamin-b1_100g" : 1.425e-05, + "vitamin-b2_100g" : 2.1e-05, + "vitamin-b6_100g" : 2.775e-05, + "vitamin-b9_100g" : 0, + "vitamin-c_100g" : 0.003, + "vitamin-d_100g" : 0, + "vitamin-e_100g" : 3.75e-05, + "vitamin-pp_100g" : 6.825e-05, + "water_100g" : 90.025, + "zinc_100g" : 4.025e-05 + }, "nutriscore" : { "2021" : { "category_available" : 1, "data" : { - "energy" : null, - "fiber" : 0, - "fruits_vegetables_nuts_colza_walnut_olive_oils" : 0, + "energy" : 155.25, + "energy_points" : 0, + "energy_value" : 155.3, + "fiber" : 0.975, + "fiber_points" : 1, + "fiber_value" : 0.98, + "fruits_vegetables_nuts_colza_walnut_olive_oils" : 50, + "fruits_vegetables_nuts_colza_walnut_olive_oils_points" : 1, + "fruits_vegetables_nuts_colza_walnut_olive_oils_value" : 50, "is_beverage" : 0, "is_cheese" : 0, "is_fat" : 0, "is_water" : 0, - "proteins" : null, - "saturated_fat" : null, - "sodium" : null, - "sugars" : null + "negative_points" : 1, + "positive_points" : 2, + "proteins" : 0.2025, + "proteins_points" : 0, + "proteins_value" : 0.2, + "saturated_fat" : 0.01575, + "saturated_fat_points" : 0, + "saturated_fat_value" : 0, + "sodium" : 0.6, + "sodium_points" : 0, + "sodium_value" : 0.6, + "sugars" : 7.575, + "sugars_points" : 1, + "sugars_value" : 7.58 }, - "grade" : "unknown", - "nutrients_available" : 0, + "grade" : "a", + "nutrients_available" : 1, "nutriscore_applicable" : 1, - "nutriscore_computed" : 0 + "nutriscore_computed" : 1, + "score" : -1 }, "2023" : { "category_available" : 1, "data" : { - "energy" : null, - "fiber" : 0, - "fruits_vegetables_legumes" : 0, + "count_proteins" : 1, + "count_proteins_reason" : "negative_points_less_than_11", + "energy" : 155.25, + "energy_points" : 0, + "fiber" : 0.975, + "fiber_points" : 0, + "fruits_vegetables_legumes" : 50, + "fruits_vegetables_legumes_points" : 1, "is_beverage" : 0, "is_cheese" : 0, "is_fat_oil_nuts_seeds" : 0, "is_water" : 0, - "proteins" : null, - "salt" : null, - "saturated_fat" : null, - "sugars" : null + "negative_nutrients" : [ + "energy", + "sugars", + "saturated_fat", + "salt", + "sweeteners" + ], + "negative_points" : 2, + "positive_nutrients" : [ + "fruits_vegetables_legumes", + "fiber", + "proteins" + ], + "positive_points" : 1, + "proteins" : 0.2025, + "proteins_points" : 0, + "salt" : 0.0019, + "salt_points" : 0, + "saturated_fat" : 0.01575, + "saturated_fat_points" : 0, + "sugars" : 7.575, + "sugars_points" : 2 }, - "grade" : "unknown", - "nutrients_available" : 0, + "grade" : "b", + "nutrients_available" : 1, "nutriscore_applicable" : 1, - "nutriscore_computed" : 0 + "nutriscore_computed" : 1, + "score" : 1 } }, "nutriscore_2021_tags" : [ - "unknown" + "a" ], "nutriscore_2023_tags" : [ - "unknown" + "b" ], - "nutriscore_grade" : "unknown", + "nutriscore_data" : { + "energy" : 155.25, + "energy_points" : 0, + "energy_value" : 155.3, + "fiber" : 0.975, + "fiber_points" : 1, + "fiber_value" : 0.98, + "fruits_vegetables_nuts_colza_walnut_olive_oils" : 50, + "fruits_vegetables_nuts_colza_walnut_olive_oils_points" : 1, + "fruits_vegetables_nuts_colza_walnut_olive_oils_value" : 50, + "grade" : "a", + "is_beverage" : 0, + "is_cheese" : 0, + "is_fat" : 0, + "is_water" : 0, + "negative_points" : 1, + "positive_points" : 2, + "proteins" : 0.2025, + "proteins_points" : 0, + "proteins_value" : 0.2, + "saturated_fat" : 0.01575, + "saturated_fat_points" : 0, + "saturated_fat_value" : 0, + "score" : -1, + "sodium" : 0.6, + "sodium_points" : 0, + "sodium_value" : 0.6, + "sugars" : 7.575, + "sugars_points" : 1, + "sugars_value" : 7.58 + }, + "nutriscore_grade" : "a", + "nutriscore_score" : -1, + "nutriscore_score_opposite" : 1, "nutriscore_tags" : [ - "unknown" + "a" ], "nutriscore_version" : "2021", "nutrition_data_per" : "100g", "nutrition_data_prepared_per" : "100g", - "nutrition_grade_fr" : "unknown", - "nutrition_grades" : "unknown", + "nutrition_grade_fr" : "a", + "nutrition_grades" : "a", "nutrition_grades_tags" : [ - "unknown" + "a" ], "nutrition_score_beverage" : 0, "nutrition_score_debug" : "missing energy_100g - missing fat_100g - missing saturated-fat_100g - missing sugars_100g - missing sodium_100g - missing proteins_100g", - "nutrition_score_warning_no_fiber" : 1, - "nutrition_score_warning_no_fruits_vegetables_nuts" : 1, + "nutrition_score_warning_fruits_vegetables_nuts_estimate_from_ingredients" : 1, + "nutrition_score_warning_fruits_vegetables_nuts_estimate_from_ingredients_value" : 50, + "nutrition_score_warning_nutriments_estimated" : 1, "origin_en" : "China", + "other_nutritional_substances_tags" : [], "packaging_materials_tags" : [], "packaging_recycling_tags" : [], "packaging_shapes_tags" : [], @@ -3175,11 +3620,11 @@ "rev" : 1, "serving_quantity" : 10, "serving_size" : "10 g", - "states" : "en:to-be-completed, en:nutrition-facts-to-be-completed, en:ingredients-to-be-completed, en:expiration-date-to-be-completed, en:packaging-code-to-be-completed, en:characteristics-to-be-completed, en:origins-to-be-completed, en:categories-completed, en:brands-to-be-completed, en:packaging-to-be-completed, en:quantity-completed, en:product-name-to-be-completed, en:photos-to-be-uploaded", + "states" : "en:to-be-completed, en:nutrition-facts-completed, en:ingredients-completed, en:expiration-date-to-be-completed, en:packaging-code-to-be-completed, en:characteristics-to-be-completed, en:origins-to-be-completed, en:categories-completed, en:brands-to-be-completed, en:packaging-to-be-completed, en:quantity-completed, en:product-name-to-be-completed, en:photos-to-be-uploaded", "states_hierarchy" : [ "en:to-be-completed", - "en:nutrition-facts-to-be-completed", - "en:ingredients-to-be-completed", + "en:nutrition-facts-completed", + "en:ingredients-completed", "en:expiration-date-to-be-completed", "en:packaging-code-to-be-completed", "en:characteristics-to-be-completed", @@ -3193,8 +3638,8 @@ ], "states_tags" : [ "en:to-be-completed", - "en:nutrition-facts-to-be-completed", - "en:ingredients-to-be-completed", + "en:nutrition-facts-completed", + "en:ingredients-completed", "en:expiration-date-to-be-completed", "en:packaging-code-to-be-completed", "en:characteristics-to-be-completed", @@ -3208,11 +3653,13 @@ ], "traces" : "", "traces_from_ingredients" : "", - "traces_from_user" : "(es) ", + "traces_from_user" : "(en) ", "traces_hierarchy" : [], "traces_tags" : [], + "unknown_ingredients_n" : 0, "unknown_nutrients_tags" : [], "url" : "http://world.openfoodfacts.localhost/product/200000000045/vegan-breakfast-cereals-without-palm-oil", + "vitamins_tags" : [], "weighers_tags" : [] }, { @@ -3778,6 +4225,7 @@ "en:fruit", "en:water" ], + "ingredients_lc" : "en", "ingredients_n" : 2, "ingredients_n_tags" : [ "2", diff --git a/tests/integration/expected_test_results/search_v1/search-tags-categories-without-ingredients-from-palm-oil.json b/tests/integration/expected_test_results/search_v1/search-tags-categories-without-ingredients-from-palm-oil.json index c750fb6a0f816..b31a8bdb0bedf 100644 --- a/tests/integration/expected_test_results/search_v1/search-tags-categories-without-ingredients-from-palm-oil.json +++ b/tests/integration/expected_test_results/search_v1/search-tags-categories-without-ingredients-from-palm-oil.json @@ -1,9 +1,913 @@ { - "count" : 1, + "count" : 2, "page" : 1, - "page_count" : 1, + "page_count" : 2, "page_size" : 24, "products" : [ + { + "_id" : "200000000045", + "_keywords" : [ + "breakfast", + "cereal" + ], + "added_countries_tags" : [], + "additives_n" : 0, + "additives_old_n" : 0, + "additives_old_tags" : [], + "additives_original_tags" : [], + "additives_tags" : [], + "allergens" : "", + "allergens_from_ingredients" : "", + "allergens_from_user" : "(en) ", + "allergens_hierarchy" : [], + "allergens_tags" : [], + "amino_acids_tags" : [], + "categories" : "breakfast cereals", + "categories_hierarchy" : [ + "en:plant-based-foods-and-beverages", + "en:plant-based-foods", + "en:breakfasts", + "en:cereals-and-potatoes", + "en:cereals-and-their-products", + "en:breakfast-cereals" + ], + "categories_lc" : "en", + "categories_properties" : { + "agribalyse_proxy_food_code:en" : "32135", + "ciqual_food_code:en" : "32003" + }, + "categories_properties_tags" : [ + "all-products", + "categories-known", + "agribalyse-food-code-unknown", + "agribalyse-proxy-food-code-32135", + "agribalyse-proxy-food-code-known", + "ciqual-food-code-32003", + "ciqual-food-code-known", + "agribalyse-known", + "agribalyse-32135" + ], + "categories_tags" : [ + "en:plant-based-foods-and-beverages", + "en:plant-based-foods", + "en:breakfasts", + "en:cereals-and-potatoes", + "en:cereals-and-their-products", + "en:breakfast-cereals" + ], + "checkers_tags" : [], + "code" : "200000000045", + "codes_tags" : [ + "code-12", + "200000000xxx", + "20000000xxxx", + "2000000xxxxx", + "200000xxxxxx", + "20000xxxxxxx", + "2000xxxxxxxx", + "200xxxxxxxxx", + "20xxxxxxxxxx", + "2xxxxxxxxxxx" + ], + "complete" : 0, + "completeness" : 0.4, + "correctors_tags" : [], + "created_t" : "--ignore--", + "creator" : "tests", + "data_quality_bugs_tags" : [], + "data_quality_errors_tags" : [], + "data_quality_info_tags" : [ + "en:no-packaging-data", + "en:ingredients-percent-analysis-ok", + "en:ecoscore-extended-data-not-computed", + "en:food-groups-1-known", + "en:food-groups-2-known", + "en:food-groups-3-unknown" + ], + "data_quality_tags" : [ + "en:no-packaging-data", + "en:ingredients-percent-analysis-ok", + "en:ecoscore-extended-data-not-computed", + "en:food-groups-1-known", + "en:food-groups-2-known", + "en:food-groups-3-unknown", + "en:ecoscore-origins-of-ingredients-origins-are-100-percent-unknown", + "en:ecoscore-packaging-packaging-data-missing", + "en:ecoscore-production-system-no-label" + ], + "data_quality_warnings_tags" : [ + "en:ecoscore-origins-of-ingredients-origins-are-100-percent-unknown", + "en:ecoscore-packaging-packaging-data-missing", + "en:ecoscore-production-system-no-label" + ], + "ecoscore_data" : { + "adjustments" : { + "origins_of_ingredients" : { + "aggregated_origins" : [ + { + "epi_score" : 0, + "origin" : "en:unknown", + "percent" : 100, + "transportation_score" : null + } + ], + "epi_score" : 0, + "epi_value" : -5, + "origins_from_origins_field" : [ + "en:unknown" + ], + "transportation_score" : 0, + "transportation_scores" : { + "ad" : 0, + "al" : 0, + "at" : 0, + "ax" : 0, + "ba" : 0, + "be" : 0, + "bg" : 0, + "ch" : 0, + "cy" : 0, + "cz" : 0, + "de" : 0, + "dk" : 0, + "dz" : 0, + "ee" : 0, + "eg" : 0, + "es" : 0, + "fi" : 0, + "fo" : 0, + "fr" : 0, + "gg" : 0, + "gi" : 0, + "gr" : 0, + "hr" : 0, + "hu" : 0, + "ie" : 0, + "il" : 0, + "im" : 0, + "is" : 0, + "it" : 0, + "je" : 0, + "lb" : 0, + "li" : 0, + "lt" : 0, + "lu" : 0, + "lv" : 0, + "ly" : 0, + "ma" : 0, + "mc" : 0, + "md" : 0, + "me" : 0, + "mk" : 0, + "mt" : 0, + "nl" : 0, + "no" : 0, + "pl" : 0, + "ps" : 0, + "pt" : 0, + "ro" : 0, + "rs" : 0, + "se" : 0, + "si" : 0, + "sj" : 0, + "sk" : 0, + "sm" : 0, + "sy" : 0, + "tn" : 0, + "tr" : 0, + "ua" : 0, + "uk" : 0, + "us" : 0, + "va" : 0, + "world" : 0, + "xk" : 0 + }, + "transportation_value" : 0, + "transportation_values" : { + "ad" : 0, + "al" : 0, + "at" : 0, + "ax" : 0, + "ba" : 0, + "be" : 0, + "bg" : 0, + "ch" : 0, + "cy" : 0, + "cz" : 0, + "de" : 0, + "dk" : 0, + "dz" : 0, + "ee" : 0, + "eg" : 0, + "es" : 0, + "fi" : 0, + "fo" : 0, + "fr" : 0, + "gg" : 0, + "gi" : 0, + "gr" : 0, + "hr" : 0, + "hu" : 0, + "ie" : 0, + "il" : 0, + "im" : 0, + "is" : 0, + "it" : 0, + "je" : 0, + "lb" : 0, + "li" : 0, + "lt" : 0, + "lu" : 0, + "lv" : 0, + "ly" : 0, + "ma" : 0, + "mc" : 0, + "md" : 0, + "me" : 0, + "mk" : 0, + "mt" : 0, + "nl" : 0, + "no" : 0, + "pl" : 0, + "ps" : 0, + "pt" : 0, + "ro" : 0, + "rs" : 0, + "se" : 0, + "si" : 0, + "sj" : 0, + "sk" : 0, + "sm" : 0, + "sy" : 0, + "tn" : 0, + "tr" : 0, + "ua" : 0, + "uk" : 0, + "us" : 0, + "va" : 0, + "world" : 0, + "xk" : 0 + }, + "value" : -5, + "values" : { + "ad" : -5, + "al" : -5, + "at" : -5, + "ax" : -5, + "ba" : -5, + "be" : -5, + "bg" : -5, + "ch" : -5, + "cy" : -5, + "cz" : -5, + "de" : -5, + "dk" : -5, + "dz" : -5, + "ee" : -5, + "eg" : -5, + "es" : -5, + "fi" : -5, + "fo" : -5, + "fr" : -5, + "gg" : -5, + "gi" : -5, + "gr" : -5, + "hr" : -5, + "hu" : -5, + "ie" : -5, + "il" : -5, + "im" : -5, + "is" : -5, + "it" : -5, + "je" : -5, + "lb" : -5, + "li" : -5, + "lt" : -5, + "lu" : -5, + "lv" : -5, + "ly" : -5, + "ma" : -5, + "mc" : -5, + "md" : -5, + "me" : -5, + "mk" : -5, + "mt" : -5, + "nl" : -5, + "no" : -5, + "pl" : -5, + "ps" : -5, + "pt" : -5, + "ro" : -5, + "rs" : -5, + "se" : -5, + "si" : -5, + "sj" : -5, + "sk" : -5, + "sm" : -5, + "sy" : -5, + "tn" : -5, + "tr" : -5, + "ua" : -5, + "uk" : -5, + "us" : -5, + "va" : -5, + "world" : -5, + "xk" : -5 + }, + "warning" : "origins_are_100_percent_unknown" + }, + "packaging" : { + "non_recyclable_and_non_biodegradable_materials" : 1, + "value" : -15, + "warning" : "packaging_data_missing" + }, + "production_system" : { + "labels" : [], + "value" : 0, + "warning" : "no_label" + }, + "threatened_species" : {} + }, + "agribalyse" : { + "agribalyse_proxy_food_code" : "32135", + "co2_agriculture" : 2.2396004, + "co2_consumption" : 0, + "co2_distribution" : 0.019530673, + "co2_packaging" : 0.28159592, + "co2_processing" : 0.77051126, + "co2_total" : 3.564111983, + "co2_transportation" : 0.25287373, + "code" : "32135", + "dqr" : "4.03", + "ef_agriculture" : 0.50064279, + "ef_consumption" : 0, + "ef_distribution" : 0.0048315303, + "ef_packaging" : 0.023715692, + "ef_processing" : 0.078716079, + "ef_total" : 0.6323498093, + "ef_transportation" : 0.024443718, + "is_beverage" : 0, + "name_en" : "Breakfast cereals, mix of puffed or extruded cereals, fortified with vitamins and chemical elements", + "name_fr" : "Multi-céréales soufflées ou extrudées, enrichies en vitamines et minéraux", + "score" : 45, + "version" : "3.1" + }, + "grade" : "d", + "grades" : { + "ad" : "d", + "al" : "d", + "at" : "d", + "ax" : "d", + "ba" : "d", + "be" : "d", + "bg" : "d", + "ch" : "d", + "cy" : "d", + "cz" : "d", + "de" : "d", + "dk" : "d", + "dz" : "d", + "ee" : "d", + "eg" : "d", + "es" : "d", + "fi" : "d", + "fo" : "d", + "fr" : "d", + "gg" : "d", + "gi" : "d", + "gr" : "d", + "hr" : "d", + "hu" : "d", + "ie" : "d", + "il" : "d", + "im" : "d", + "is" : "d", + "it" : "d", + "je" : "d", + "lb" : "d", + "li" : "d", + "lt" : "d", + "lu" : "d", + "lv" : "d", + "ly" : "d", + "ma" : "d", + "mc" : "d", + "md" : "d", + "me" : "d", + "mk" : "d", + "mt" : "d", + "nl" : "d", + "no" : "d", + "pl" : "d", + "ps" : "d", + "pt" : "d", + "ro" : "d", + "rs" : "d", + "se" : "d", + "si" : "d", + "sj" : "d", + "sk" : "d", + "sm" : "d", + "sy" : "d", + "tn" : "d", + "tr" : "d", + "ua" : "d", + "uk" : "d", + "us" : "d", + "va" : "d", + "world" : "d", + "xk" : "d" + }, + "missing" : { + "labels" : 1, + "origins" : 1, + "packagings" : 1 + }, + "missing_data_warning" : 1, + "missing_key_data" : 1, + "score" : 25, + "scores" : { + "ad" : 25, + "al" : 25, + "at" : 25, + "ax" : 25, + "ba" : 25, + "be" : 25, + "bg" : 25, + "ch" : 25, + "cy" : 25, + "cz" : 25, + "de" : 25, + "dk" : 25, + "dz" : 25, + "ee" : 25, + "eg" : 25, + "es" : 25, + "fi" : 25, + "fo" : 25, + "fr" : 25, + "gg" : 25, + "gi" : 25, + "gr" : 25, + "hr" : 25, + "hu" : 25, + "ie" : 25, + "il" : 25, + "im" : 25, + "is" : 25, + "it" : 25, + "je" : 25, + "lb" : 25, + "li" : 25, + "lt" : 25, + "lu" : 25, + "lv" : 25, + "ly" : 25, + "ma" : 25, + "mc" : 25, + "md" : 25, + "me" : 25, + "mk" : 25, + "mt" : 25, + "nl" : 25, + "no" : 25, + "pl" : 25, + "ps" : 25, + "pt" : 25, + "ro" : 25, + "rs" : 25, + "se" : 25, + "si" : 25, + "sj" : 25, + "sk" : 25, + "sm" : 25, + "sy" : 25, + "tn" : 25, + "tr" : 25, + "ua" : 25, + "uk" : 25, + "us" : 25, + "va" : 25, + "world" : 25, + "xk" : 25 + }, + "status" : "known" + }, + "ecoscore_grade" : "d", + "ecoscore_score" : 25, + "ecoscore_tags" : [ + "d" + ], + "editors_tags" : [ + "tests" + ], + "entry_dates_tags" : "--ignore--", + "food_groups" : "en:breakfast-cereals", + "food_groups_tags" : [ + "en:cereals-and-potatoes", + "en:breakfast-cereals" + ], + "generic_name_en" : "Tester", + "id" : "200000000045", + "informers_tags" : [ + "tests" + ], + "ingredients" : [ + { + "ciqual_food_code" : "13050", + "id" : "en:apple", + "percent_estimate" : 75, + "percent_max" : 100, + "percent_min" : 50, + "rank" : 1, + "text" : "apple", + "vegan" : "yes", + "vegetarian" : "yes" + }, + { + "ciqual_food_code" : "18066", + "id" : "en:water", + "percent_estimate" : 25, + "percent_max" : 50, + "percent_min" : 0, + "rank" : 2, + "text" : "water", + "vegan" : "yes", + "vegetarian" : "yes" + } + ], + "ingredients_analysis" : {}, + "ingredients_analysis_tags" : [ + "en:palm-oil-free", + "en:vegan", + "en:vegetarian" + ], + "ingredients_from_or_that_may_be_from_palm_oil_n" : 0, + "ingredients_from_palm_oil_n" : 0, + "ingredients_from_palm_oil_tags" : [], + "ingredients_hierarchy" : [ + "en:apple", + "en:fruit", + "en:water" + ], + "ingredients_lc" : "en", + "ingredients_n" : 2, + "ingredients_n_tags" : [ + "2", + "1-10" + ], + "ingredients_original_tags" : [ + "en:apple", + "en:water" + ], + "ingredients_percent_analysis" : 1, + "ingredients_tags" : [ + "en:apple", + "en:fruit", + "en:water" + ], + "ingredients_text" : "apple, water", + "ingredients_text_en" : "apple, water", + "ingredients_text_with_allergens" : "apple, water", + "ingredients_text_with_allergens_en" : "apple, water", + "ingredients_that_may_be_from_palm_oil_n" : 0, + "ingredients_that_may_be_from_palm_oil_tags" : [], + "ingredients_with_specified_percent_n" : 0, + "ingredients_with_specified_percent_sum" : 0, + "ingredients_with_unspecified_percent_n" : 2, + "ingredients_with_unspecified_percent_sum" : 100, + "ingredients_without_ciqual_codes" : [], + "ingredients_without_ciqual_codes_n" : 0, + "interface_version_created" : "20150316.jqm2", + "interface_version_modified" : "20150316.jqm2", + "known_ingredients_n" : 3, + "lang" : "es", + "languages" : { + "en:english" : 5 + }, + "languages_codes" : { + "en" : 5 + }, + "languages_hierarchy" : [ + "en:english" + ], + "languages_tags" : [ + "en:english", + "en:1" + ], + "last_edit_dates_tags" : "--ignore--", + "last_editor" : "tests", + "last_modified_by" : "tests", + "last_modified_t" : "--ignore--", + "lc" : "es", + "link" : "http://world.openfoodfacts.org/", + "main_countries_tags" : [], + "minerals_tags" : [], + "misc_tags" : [ + "en:nutrition-not-enough-data-to-compute-nutrition-score", + "en:nutriscore-missing-nutrition-data", + "en:nutriscore-missing-nutrition-data-energy", + "en:nutriscore-missing-nutrition-data-fat", + "en:nutriscore-missing-nutrition-data-saturated-fat", + "en:nutriscore-missing-nutrition-data-sugars", + "en:nutriscore-missing-nutrition-data-sodium", + "en:nutriscore-missing-nutrition-data-proteins", + "en:nutrition-no-fiber", + "en:nutriscore-using-estimated-nutrition-facts", + "en:nutriscore-computed", + "en:nutrition-fruits-vegetables-nuts-estimate-from-ingredients", + "en:nutrition-all-nutriscore-values-known", + "en:nutriscore-2021-different-from-2023", + "en:nutriscore-2021-better-than-2023", + "en:nutriscore-2021-a-2023-b", + "en:packagings-number-of-components-0", + "en:packagings-not-complete", + "en:packagings-empty", + "en:ecoscore-extended-data-not-computed", + "en:ecoscore-missing-data-warning", + "en:ecoscore-missing-data-labels", + "en:ecoscore-missing-data-origins", + "en:ecoscore-missing-data-packagings", + "en:ecoscore-missing-data-no-packagings", + "en:ecoscore-computed", + "en:ecoscore-changed", + "en:ecoscore-grade-changed", + "en:main-countries-new-product" + ], + "nova_group" : 1, + "nova_group_debug" : "", + "nova_groups" : "1", + "nova_groups_markers" : {}, + "nova_groups_tags" : [ + "en:1-unprocessed-or-minimally-processed-foods" + ], + "nucleotides_tags" : [], + "nutrient_levels" : {}, + "nutrient_levels_tags" : [], + "nutriments" : { + "fruits-vegetables-nuts-estimate-from-ingredients_100g" : 50, + "fruits-vegetables-nuts-estimate-from-ingredients_serving" : 50, + "nova-group" : 1, + "nova-group_100g" : 1, + "nova-group_serving" : 1, + "nutrition-score-fr" : -1, + "nutrition-score-fr_100g" : -1 + }, + "nutriments_estimated" : { + "alcohol_100g" : 0, + "beta-carotene_100g" : 1.275e-05, + "calcium_100g" : 0.0055325, + "carbohydrates_100g" : 8.025, + "cholesterol_100g" : 0, + "copper_100g" : 2.75e-05, + "energy-kcal_100g" : 36.675, + "energy-kj_100g" : 155.25, + "energy_100g" : 155.25, + "fat_100g" : 0.0975, + "fiber_100g" : 0.975, + "fructose_100g" : 4.5225, + "galactose_100g" : 0, + "glucose_100g" : 2.4375, + "iodine_100g" : 7.5e-08, + "iron_100g" : 6e-05, + "lactose_100g" : 0, + "magnesium_100g" : 0.0032475, + "maltose_100g" : 0, + "manganese_100g" : 2.8705e-05, + "pantothenic-acid_100g" : 5.325e-05, + "phosphorus_100g" : 0.00825, + "phylloquinone_100g" : 4.5e-07, + "polyols_100g" : 0.4425, + "potassium_100g" : 0.0676825, + "proteins_100g" : 0.2025, + "salt_100g" : 0.0019, + "saturated-fat_100g" : 0.01575, + "selenium_100g" : 2.375e-07, + "sodium_100g" : 0.0006, + "starch_100g" : 0, + "sucrose_100g" : 0.615, + "sugars_100g" : 7.575, + "vitamin-a_100g" : 0, + "vitamin-b12_100g" : 0, + "vitamin-b1_100g" : 1.425e-05, + "vitamin-b2_100g" : 2.1e-05, + "vitamin-b6_100g" : 2.775e-05, + "vitamin-b9_100g" : 0, + "vitamin-c_100g" : 0.003, + "vitamin-d_100g" : 0, + "vitamin-e_100g" : 3.75e-05, + "vitamin-pp_100g" : 6.825e-05, + "water_100g" : 90.025, + "zinc_100g" : 4.025e-05 + }, + "nutriscore" : { + "2021" : { + "category_available" : 1, + "data" : { + "energy" : 155.25, + "energy_points" : 0, + "energy_value" : 155.3, + "fiber" : 0.975, + "fiber_points" : 1, + "fiber_value" : 0.98, + "fruits_vegetables_nuts_colza_walnut_olive_oils" : 50, + "fruits_vegetables_nuts_colza_walnut_olive_oils_points" : 1, + "fruits_vegetables_nuts_colza_walnut_olive_oils_value" : 50, + "is_beverage" : 0, + "is_cheese" : 0, + "is_fat" : 0, + "is_water" : 0, + "negative_points" : 1, + "positive_points" : 2, + "proteins" : 0.2025, + "proteins_points" : 0, + "proteins_value" : 0.2, + "saturated_fat" : 0.01575, + "saturated_fat_points" : 0, + "saturated_fat_value" : 0, + "sodium" : 0.6, + "sodium_points" : 0, + "sodium_value" : 0.6, + "sugars" : 7.575, + "sugars_points" : 1, + "sugars_value" : 7.58 + }, + "grade" : "a", + "nutrients_available" : 1, + "nutriscore_applicable" : 1, + "nutriscore_computed" : 1, + "score" : -1 + }, + "2023" : { + "category_available" : 1, + "data" : { + "count_proteins" : 1, + "count_proteins_reason" : "negative_points_less_than_11", + "energy" : 155.25, + "energy_points" : 0, + "fiber" : 0.975, + "fiber_points" : 0, + "fruits_vegetables_legumes" : 50, + "fruits_vegetables_legumes_points" : 1, + "is_beverage" : 0, + "is_cheese" : 0, + "is_fat_oil_nuts_seeds" : 0, + "is_water" : 0, + "negative_nutrients" : [ + "energy", + "sugars", + "saturated_fat", + "salt", + "sweeteners" + ], + "negative_points" : 2, + "positive_nutrients" : [ + "fruits_vegetables_legumes", + "fiber", + "proteins" + ], + "positive_points" : 1, + "proteins" : 0.2025, + "proteins_points" : 0, + "salt" : 0.0019, + "salt_points" : 0, + "saturated_fat" : 0.01575, + "saturated_fat_points" : 0, + "sugars" : 7.575, + "sugars_points" : 2 + }, + "grade" : "b", + "nutrients_available" : 1, + "nutriscore_applicable" : 1, + "nutriscore_computed" : 1, + "score" : 1 + } + }, + "nutriscore_2021_tags" : [ + "a" + ], + "nutriscore_2023_tags" : [ + "b" + ], + "nutriscore_data" : { + "energy" : 155.25, + "energy_points" : 0, + "energy_value" : 155.3, + "fiber" : 0.975, + "fiber_points" : 1, + "fiber_value" : 0.98, + "fruits_vegetables_nuts_colza_walnut_olive_oils" : 50, + "fruits_vegetables_nuts_colza_walnut_olive_oils_points" : 1, + "fruits_vegetables_nuts_colza_walnut_olive_oils_value" : 50, + "grade" : "a", + "is_beverage" : 0, + "is_cheese" : 0, + "is_fat" : 0, + "is_water" : 0, + "negative_points" : 1, + "positive_points" : 2, + "proteins" : 0.2025, + "proteins_points" : 0, + "proteins_value" : 0.2, + "saturated_fat" : 0.01575, + "saturated_fat_points" : 0, + "saturated_fat_value" : 0, + "score" : -1, + "sodium" : 0.6, + "sodium_points" : 0, + "sodium_value" : 0.6, + "sugars" : 7.575, + "sugars_points" : 1, + "sugars_value" : 7.58 + }, + "nutriscore_grade" : "a", + "nutriscore_score" : -1, + "nutriscore_score_opposite" : 1, + "nutriscore_tags" : [ + "a" + ], + "nutriscore_version" : "2021", + "nutrition_data_per" : "100g", + "nutrition_data_prepared_per" : "100g", + "nutrition_grade_fr" : "a", + "nutrition_grades" : "a", + "nutrition_grades_tags" : [ + "a" + ], + "nutrition_score_beverage" : 0, + "nutrition_score_debug" : "missing energy_100g - missing fat_100g - missing saturated-fat_100g - missing sugars_100g - missing sodium_100g - missing proteins_100g", + "nutrition_score_warning_fruits_vegetables_nuts_estimate_from_ingredients" : 1, + "nutrition_score_warning_fruits_vegetables_nuts_estimate_from_ingredients_value" : 50, + "nutrition_score_warning_nutriments_estimated" : 1, + "origin_en" : "China", + "other_nutritional_substances_tags" : [], + "packaging_materials_tags" : [], + "packaging_recycling_tags" : [], + "packaging_shapes_tags" : [], + "packaging_text_en" : "no", + "packagings" : [], + "packagings_materials" : {}, + "photographers_tags" : [], + "pnns_groups_1" : "Cereals and potatoes", + "pnns_groups_1_tags" : [ + "cereals-and-potatoes", + "known" + ], + "pnns_groups_2" : "Breakfast cereals", + "pnns_groups_2_tags" : [ + "breakfast-cereals", + "known" + ], + "popularity_key" : 0, + "product_name_en" : "Vegan breakfast cereals without palm oil", + "product_quantity" : 100, + "quantity" : "100 g", + "removed_countries_tags" : [], + "rev" : 1, + "serving_quantity" : 10, + "serving_size" : "10 g", + "states" : "en:to-be-completed, en:nutrition-facts-completed, en:ingredients-completed, en:expiration-date-to-be-completed, en:packaging-code-to-be-completed, en:characteristics-to-be-completed, en:origins-to-be-completed, en:categories-completed, en:brands-to-be-completed, en:packaging-to-be-completed, en:quantity-completed, en:product-name-to-be-completed, en:photos-to-be-uploaded", + "states_hierarchy" : [ + "en:to-be-completed", + "en:nutrition-facts-completed", + "en:ingredients-completed", + "en:expiration-date-to-be-completed", + "en:packaging-code-to-be-completed", + "en:characteristics-to-be-completed", + "en:origins-to-be-completed", + "en:categories-completed", + "en:brands-to-be-completed", + "en:packaging-to-be-completed", + "en:quantity-completed", + "en:product-name-to-be-completed", + "en:photos-to-be-uploaded" + ], + "states_tags" : [ + "en:to-be-completed", + "en:nutrition-facts-completed", + "en:ingredients-completed", + "en:expiration-date-to-be-completed", + "en:packaging-code-to-be-completed", + "en:characteristics-to-be-completed", + "en:origins-to-be-completed", + "en:categories-completed", + "en:brands-to-be-completed", + "en:packaging-to-be-completed", + "en:quantity-completed", + "en:product-name-to-be-completed", + "en:photos-to-be-uploaded" + ], + "traces" : "", + "traces_from_ingredients" : "", + "traces_from_user" : "(en) ", + "traces_hierarchy" : [], + "traces_tags" : [], + "unknown_ingredients_n" : 0, + "unknown_nutrients_tags" : [], + "url" : "http://world.openfoodfacts.localhost/product/200000000045/vegan-breakfast-cereals-without-palm-oil", + "vitamins_tags" : [], + "weighers_tags" : [] + }, { "_id" : "200000000046", "_keywords" : [ @@ -567,6 +1471,7 @@ "en:fruit", "en:water" ], + "ingredients_lc" : "en", "ingredients_n" : 2, "ingredients_n_tags" : [ "2", diff --git a/tests/integration/expected_test_results/search_v1/search-without-ingredients-from-palm-oil.json b/tests/integration/expected_test_results/search_v1/search-without-ingredients-from-palm-oil.json index ee8febf7bf8ef..1e691dac19b0e 100644 --- a/tests/integration/expected_test_results/search_v1/search-without-ingredients-from-palm-oil.json +++ b/tests/integration/expected_test_results/search_v1/search-without-ingredients-from-palm-oil.json @@ -1,7 +1,7 @@ { - "count" : 4, + "count" : 6, "page" : 1, - "page_count" : 4, + "page_count" : 6, "page_size" : 24, "products" : [ { @@ -471,6 +471,7 @@ "en:vegetable-oil-and-fat", "en:palm-oil-and-fat" ], + "ingredients_lc" : "en", "ingredients_n" : 4, "ingredients_n_tags" : [ "4", @@ -1122,6 +1123,7 @@ "en:fruit", "en:rice" ], + "ingredients_lc" : "en", "ingredients_n" : 2, "ingredients_n_tags" : [ "2", @@ -1775,6 +1777,7 @@ "en:dairy", "en:egg" ], + "ingredients_lc" : "en", "ingredients_n" : 3, "ingredients_n_tags" : [ "3", @@ -2006,6 +2009,1659 @@ "vitamins_tags" : [], "weighers_tags" : [] }, + { + "_id" : "200000000039", + "_keywords" : [ + "snack" + ], + "added_countries_tags" : [], + "additives_n" : 0, + "additives_old_n" : 0, + "additives_old_tags" : [], + "additives_original_tags" : [], + "additives_tags" : [], + "allergens" : "", + "allergens_from_ingredients" : "", + "allergens_from_user" : "(en) ", + "allergens_hierarchy" : [], + "allergens_tags" : [], + "amino_acids_tags" : [], + "categories" : "snacks", + "categories_hierarchy" : [ + "en:snacks" + ], + "categories_lc" : "en", + "categories_properties" : {}, + "categories_properties_tags" : [ + "all-products", + "categories-known", + "agribalyse-food-code-unknown", + "agribalyse-proxy-food-code-unknown", + "ciqual-food-code-unknown", + "agribalyse-unknown" + ], + "categories_tags" : [ + "en:snacks" + ], + "checkers_tags" : [], + "code" : "200000000039", + "codes_tags" : [ + "code-12", + "200000000xxx", + "20000000xxxx", + "2000000xxxxx", + "200000xxxxxx", + "20000xxxxxxx", + "2000xxxxxxxx", + "200xxxxxxxxx", + "20xxxxxxxxxx", + "2xxxxxxxxxxx" + ], + "complete" : 0, + "completeness" : 0.4, + "correctors_tags" : [], + "created_t" : "--ignore--", + "creator" : "tests", + "data_quality_bugs_tags" : [], + "data_quality_errors_tags" : [], + "data_quality_info_tags" : [ + "en:no-packaging-data", + "en:ingredients-percent-analysis-ok", + "en:ecoscore-extended-data-not-computed", + "en:food-groups-1-unknown", + "en:food-groups-2-unknown", + "en:food-groups-3-unknown" + ], + "data_quality_tags" : [ + "en:no-packaging-data", + "en:ingredients-percent-analysis-ok", + "en:ecoscore-extended-data-not-computed", + "en:food-groups-1-unknown", + "en:food-groups-2-unknown", + "en:food-groups-3-unknown", + "en:ecoscore-origins-of-ingredients-origins-are-100-percent-unknown", + "en:ecoscore-packaging-packaging-data-missing", + "en:ecoscore-production-system-no-label" + ], + "data_quality_warnings_tags" : [ + "en:ecoscore-origins-of-ingredients-origins-are-100-percent-unknown", + "en:ecoscore-packaging-packaging-data-missing", + "en:ecoscore-production-system-no-label" + ], + "ecoscore_data" : { + "adjustments" : { + "origins_of_ingredients" : { + "aggregated_origins" : [ + { + "epi_score" : 0, + "origin" : "en:unknown", + "percent" : 100, + "transportation_score" : null + } + ], + "epi_score" : 0, + "epi_value" : -5, + "origins_from_origins_field" : [ + "en:unknown" + ], + "transportation_score" : 0, + "transportation_scores" : { + "ad" : 0, + "al" : 0, + "at" : 0, + "ax" : 0, + "ba" : 0, + "be" : 0, + "bg" : 0, + "ch" : 0, + "cy" : 0, + "cz" : 0, + "de" : 0, + "dk" : 0, + "dz" : 0, + "ee" : 0, + "eg" : 0, + "es" : 0, + "fi" : 0, + "fo" : 0, + "fr" : 0, + "gg" : 0, + "gi" : 0, + "gr" : 0, + "hr" : 0, + "hu" : 0, + "ie" : 0, + "il" : 0, + "im" : 0, + "is" : 0, + "it" : 0, + "je" : 0, + "lb" : 0, + "li" : 0, + "lt" : 0, + "lu" : 0, + "lv" : 0, + "ly" : 0, + "ma" : 0, + "mc" : 0, + "md" : 0, + "me" : 0, + "mk" : 0, + "mt" : 0, + "nl" : 0, + "no" : 0, + "pl" : 0, + "ps" : 0, + "pt" : 0, + "ro" : 0, + "rs" : 0, + "se" : 0, + "si" : 0, + "sj" : 0, + "sk" : 0, + "sm" : 0, + "sy" : 0, + "tn" : 0, + "tr" : 0, + "ua" : 0, + "uk" : 0, + "us" : 0, + "va" : 0, + "world" : 0, + "xk" : 0 + }, + "transportation_value" : 0, + "transportation_values" : { + "ad" : 0, + "al" : 0, + "at" : 0, + "ax" : 0, + "ba" : 0, + "be" : 0, + "bg" : 0, + "ch" : 0, + "cy" : 0, + "cz" : 0, + "de" : 0, + "dk" : 0, + "dz" : 0, + "ee" : 0, + "eg" : 0, + "es" : 0, + "fi" : 0, + "fo" : 0, + "fr" : 0, + "gg" : 0, + "gi" : 0, + "gr" : 0, + "hr" : 0, + "hu" : 0, + "ie" : 0, + "il" : 0, + "im" : 0, + "is" : 0, + "it" : 0, + "je" : 0, + "lb" : 0, + "li" : 0, + "lt" : 0, + "lu" : 0, + "lv" : 0, + "ly" : 0, + "ma" : 0, + "mc" : 0, + "md" : 0, + "me" : 0, + "mk" : 0, + "mt" : 0, + "nl" : 0, + "no" : 0, + "pl" : 0, + "ps" : 0, + "pt" : 0, + "ro" : 0, + "rs" : 0, + "se" : 0, + "si" : 0, + "sj" : 0, + "sk" : 0, + "sm" : 0, + "sy" : 0, + "tn" : 0, + "tr" : 0, + "ua" : 0, + "uk" : 0, + "us" : 0, + "va" : 0, + "world" : 0, + "xk" : 0 + }, + "value" : -5, + "values" : { + "ad" : -5, + "al" : -5, + "at" : -5, + "ax" : -5, + "ba" : -5, + "be" : -5, + "bg" : -5, + "ch" : -5, + "cy" : -5, + "cz" : -5, + "de" : -5, + "dk" : -5, + "dz" : -5, + "ee" : -5, + "eg" : -5, + "es" : -5, + "fi" : -5, + "fo" : -5, + "fr" : -5, + "gg" : -5, + "gi" : -5, + "gr" : -5, + "hr" : -5, + "hu" : -5, + "ie" : -5, + "il" : -5, + "im" : -5, + "is" : -5, + "it" : -5, + "je" : -5, + "lb" : -5, + "li" : -5, + "lt" : -5, + "lu" : -5, + "lv" : -5, + "ly" : -5, + "ma" : -5, + "mc" : -5, + "md" : -5, + "me" : -5, + "mk" : -5, + "mt" : -5, + "nl" : -5, + "no" : -5, + "pl" : -5, + "ps" : -5, + "pt" : -5, + "ro" : -5, + "rs" : -5, + "se" : -5, + "si" : -5, + "sj" : -5, + "sk" : -5, + "sm" : -5, + "sy" : -5, + "tn" : -5, + "tr" : -5, + "ua" : -5, + "uk" : -5, + "us" : -5, + "va" : -5, + "world" : -5, + "xk" : -5 + }, + "warning" : "origins_are_100_percent_unknown" + }, + "packaging" : { + "non_recyclable_and_non_biodegradable_materials" : 1, + "value" : -15, + "warning" : "packaging_data_missing" + }, + "production_system" : { + "labels" : [], + "value" : 0, + "warning" : "no_label" + }, + "threatened_species" : { + "ingredient" : "en:palm-oil", + "value" : -10 + } + }, + "agribalyse" : { + "warning" : "missing_agribalyse_match" + }, + "missing" : { + "agb_category" : 1, + "labels" : 1, + "origins" : 1, + "packagings" : 1 + }, + "missing_agribalyse_match_warning" : 1, + "missing_key_data" : 1, + "scores" : {}, + "status" : "unknown" + }, + "ecoscore_grade" : "unknown", + "ecoscore_tags" : [ + "unknown" + ], + "editors_tags" : [ + "tests" + ], + "entry_dates_tags" : "--ignore--", + "food_groups_tags" : [], + "generic_name_en" : "Tester", + "id" : "200000000039", + "informers_tags" : [ + "tests" + ], + "ingredients" : [ + { + "ciqual_food_code" : "13050", + "id" : "en:apple", + "percent_estimate" : 66.6666666666667, + "percent_max" : 100, + "percent_min" : 33.3333333333333, + "rank" : 1, + "text" : "apple", + "vegan" : "yes", + "vegetarian" : "yes" + }, + { + "ciqual_food_code" : "18066", + "id" : "en:water", + "percent_estimate" : 16.6666666666667, + "percent_max" : 50, + "percent_min" : 0, + "rank" : 2, + "text" : "water", + "vegan" : "yes", + "vegetarian" : "yes" + }, + { + "ciqual_food_code" : "16129", + "from_palm_oil" : "yes", + "id" : "en:palm-oil", + "percent_estimate" : 16.6666666666667, + "percent_max" : 33.3333333333333, + "percent_min" : 0, + "rank" : 3, + "text" : "palm oil", + "vegan" : "yes", + "vegetarian" : "yes" + } + ], + "ingredients_analysis" : { + "en:palm-oil" : [ + "en:palm-oil" + ] + }, + "ingredients_analysis_tags" : [ + "en:palm-oil", + "en:vegan", + "en:vegetarian" + ], + "ingredients_from_or_that_may_be_from_palm_oil_n" : 0, + "ingredients_from_palm_oil_n" : 0, + "ingredients_from_palm_oil_tags" : [], + "ingredients_hierarchy" : [ + "en:apple", + "en:fruit", + "en:water", + "en:palm-oil", + "en:oil-and-fat", + "en:vegetable-oil-and-fat", + "en:palm-oil-and-fat" + ], + "ingredients_lc" : "en", + "ingredients_n" : 3, + "ingredients_n_tags" : [ + "3", + "1-10" + ], + "ingredients_original_tags" : [ + "en:apple", + "en:water", + "en:palm-oil" + ], + "ingredients_percent_analysis" : 1, + "ingredients_tags" : [ + "en:apple", + "en:fruit", + "en:water", + "en:palm-oil", + "en:oil-and-fat", + "en:vegetable-oil-and-fat", + "en:palm-oil-and-fat" + ], + "ingredients_text" : "apple, water, palm oil", + "ingredients_text_en" : "apple, water, palm oil", + "ingredients_text_with_allergens" : "apple, water, palm oil", + "ingredients_text_with_allergens_en" : "apple, water, palm oil", + "ingredients_that_may_be_from_palm_oil_n" : 0, + "ingredients_that_may_be_from_palm_oil_tags" : [], + "ingredients_with_specified_percent_n" : 0, + "ingredients_with_specified_percent_sum" : 0, + "ingredients_with_unspecified_percent_n" : 3, + "ingredients_with_unspecified_percent_sum" : 100, + "ingredients_without_ciqual_codes" : [], + "ingredients_without_ciqual_codes_n" : 0, + "interface_version_created" : "20150316.jqm2", + "interface_version_modified" : "20150316.jqm2", + "known_ingredients_n" : 7, + "lang" : "es", + "languages" : { + "en:english" : 4 + }, + "languages_codes" : { + "en" : 4 + }, + "languages_hierarchy" : [ + "en:english" + ], + "languages_tags" : [ + "en:english", + "en:1" + ], + "last_edit_dates_tags" : "--ignore--", + "last_editor" : "tests", + "last_modified_by" : "tests", + "last_modified_t" : "--ignore--", + "lc" : "es", + "link" : "http://world.openfoodfacts.org/", + "main_countries_tags" : [], + "minerals_tags" : [], + "misc_tags" : [ + "en:nutrition-not-enough-data-to-compute-nutrition-score", + "en:nutriscore-missing-nutrition-data", + "en:nutriscore-missing-nutrition-data-energy", + "en:nutriscore-missing-nutrition-data-fat", + "en:nutriscore-missing-nutrition-data-saturated-fat", + "en:nutriscore-missing-nutrition-data-sugars", + "en:nutriscore-missing-nutrition-data-sodium", + "en:nutriscore-missing-nutrition-data-proteins", + "en:nutrition-no-fiber", + "en:nutriscore-using-estimated-nutrition-facts", + "en:nutriscore-computed", + "en:nutrition-fruits-vegetables-nuts-estimate-from-ingredients", + "en:nutrition-all-nutriscore-values-known", + "en:nutriscore-2021-same-as-2023", + "en:nutriscore-2021-d-2023-d", + "en:packagings-number-of-components-0", + "en:packagings-not-complete", + "en:packagings-empty", + "en:ecoscore-extended-data-not-computed", + "en:ecoscore-not-computed", + "en:main-countries-new-product" + ], + "nova_group" : 1, + "nova_group_debug" : "", + "nova_groups" : "1", + "nova_groups_markers" : {}, + "nova_groups_tags" : [ + "en:1-unprocessed-or-minimally-processed-foods" + ], + "nucleotides_tags" : [], + "nutrient_levels" : {}, + "nutrient_levels_tags" : [], + "nutriments" : { + "fruits-vegetables-nuts-estimate-from-ingredients_100g" : 33.3333333333333, + "fruits-vegetables-nuts-estimate-from-ingredients_serving" : 33.3333333333333, + "nova-group" : 1, + "nova-group_100g" : 1, + "nova-group_serving" : 1, + "nutrition-score-fr" : 11, + "nutrition-score-fr_100g" : 11 + }, + "nutriments_estimated" : { + "alcohol_100g" : 0, + "beta-carotene_100g" : 1.13333333333333e-05, + "calcium_100g" : 0.00452166666666667, + "carbohydrates_100g" : 7.13333333333333, + "cholesterol_100g" : 0, + "copper_100g" : 2.35e-05, + "energy-kcal_100g" : 182.6, + "energy-kj_100g" : 754.666666666666, + "energy_100g" : 754.666666666666, + "fat_100g" : 16.7533333333333, + "fiber_100g" : 0.866666666666667, + "fructose_100g" : 4.02, + "galactose_100g" : 0, + "glucose_100g" : 2.16666666666667, + "iodine_100g" : 9.66666666666666e-07, + "iron_100g" : 5.33333333333333e-05, + "lactose_100g" : 0, + "magnesium_100g" : 0.00283166666666667, + "maltose_100g" : 0, + "manganese_100g" : 2.5595e-05, + "pantothenic-acid_100g" : 4.73333333333333e-05, + "phosphorus_100g" : 0.00733333333333333, + "phylloquinone_100g" : 1.73333333333333e-06, + "polyols_100g" : 0.393333333333333, + "potassium_100g" : 0.0601216666666667, + "proteins_100g" : 0.18, + "salt_100g" : 0.00126666666666667, + "saturated-fat_100g" : 8.23066666666666, + "selenium_100g" : 1.43333333333333e-06, + "sodium_100g" : 0.0004, + "starch_100g" : 0, + "sucrose_100g" : 0.546666666666667, + "sugars_100g" : 6.73333333333333, + "vitamin-a_100g" : 0, + "vitamin-b12_100g" : 0, + "vitamin-b1_100g" : 1.26666666666667e-05, + "vitamin-b2_100g" : 1.86666666666667e-05, + "vitamin-b6_100g" : 2.46666666666667e-05, + "vitamin-b9_100g" : 0, + "vitamin-c_100g" : 0.00266666666666667, + "vitamin-d_100g" : 0, + "vitamin-e_100g" : 0.00268333333333333, + "vitamin-pp_100g" : 6.06666666666667e-05, + "water_100g" : 74.4666666666667, + "zinc_100g" : 3.51666666666667e-05 + }, + "nutriscore" : { + "2021" : { + "category_available" : 1, + "data" : { + "energy" : 754.666666666666, + "energy_points" : 2, + "energy_value" : 754.7, + "fiber" : 0.866666666666667, + "fiber_points" : 0, + "fiber_value" : 0.87, + "fruits_vegetables_nuts_colza_walnut_olive_oils" : 33.3333333333333, + "fruits_vegetables_nuts_colza_walnut_olive_oils_points" : 0, + "fruits_vegetables_nuts_colza_walnut_olive_oils_value" : 33.3, + "is_beverage" : 0, + "is_cheese" : 0, + "is_fat" : 0, + "is_water" : 0, + "negative_points" : 11, + "positive_points" : 0, + "proteins" : 0.18, + "proteins_points" : 0, + "proteins_value" : 0.18, + "saturated_fat" : 8.23066666666666, + "saturated_fat_points" : 8, + "saturated_fat_value" : 8.2, + "sodium" : 0.4, + "sodium_points" : 0, + "sodium_value" : 0.4, + "sugars" : 6.73333333333333, + "sugars_points" : 1, + "sugars_value" : 6.73 + }, + "grade" : "d", + "nutrients_available" : 1, + "nutriscore_applicable" : 1, + "nutriscore_computed" : 1, + "score" : 11 + }, + "2023" : { + "category_available" : 1, + "data" : { + "count_proteins" : 0, + "count_proteins_reason" : "negative_points_more_than_11", + "energy" : 754.666666666666, + "energy_points" : 2, + "fiber" : 0.866666666666667, + "fiber_points" : 0, + "fruits_vegetables_legumes" : 33.3333333333333, + "fruits_vegetables_legumes_points" : 0, + "is_beverage" : 0, + "is_cheese" : 0, + "is_fat_oil_nuts_seeds" : 0, + "is_water" : 0, + "negative_nutrients" : [ + "energy", + "sugars", + "saturated_fat", + "salt", + "sweeteners" + ], + "negative_points" : 11, + "positive_nutrients" : [ + "fruits_vegetables_legumes", + "fiber" + ], + "positive_points" : 0, + "proteins" : 0.18, + "proteins_points" : 0, + "salt" : 0.00126666666666667, + "salt_points" : 0, + "saturated_fat" : 8.23066666666666, + "saturated_fat_points" : 8, + "sugars" : 6.73333333333333, + "sugars_points" : 1 + }, + "grade" : "d", + "nutrients_available" : 1, + "nutriscore_applicable" : 1, + "nutriscore_computed" : 1, + "score" : 11 + } + }, + "nutriscore_2021_tags" : [ + "d" + ], + "nutriscore_2023_tags" : [ + "d" + ], + "nutriscore_data" : { + "energy" : 754.666666666666, + "energy_points" : 2, + "energy_value" : 754.7, + "fiber" : 0.866666666666667, + "fiber_points" : 0, + "fiber_value" : 0.87, + "fruits_vegetables_nuts_colza_walnut_olive_oils" : 33.3333333333333, + "fruits_vegetables_nuts_colza_walnut_olive_oils_points" : 0, + "fruits_vegetables_nuts_colza_walnut_olive_oils_value" : 33.3, + "grade" : "d", + "is_beverage" : 0, + "is_cheese" : 0, + "is_fat" : 0, + "is_water" : 0, + "negative_points" : 11, + "positive_points" : 0, + "proteins" : 0.18, + "proteins_points" : 0, + "proteins_value" : 0.18, + "saturated_fat" : 8.23066666666666, + "saturated_fat_points" : 8, + "saturated_fat_value" : 8.2, + "score" : 11, + "sodium" : 0.4, + "sodium_points" : 0, + "sodium_value" : 0.4, + "sugars" : 6.73333333333333, + "sugars_points" : 1, + "sugars_value" : 6.73 + }, + "nutriscore_grade" : "d", + "nutriscore_score" : 11, + "nutriscore_score_opposite" : -11, + "nutriscore_tags" : [ + "d" + ], + "nutriscore_version" : "2021", + "nutrition_data_per" : "100g", + "nutrition_data_prepared_per" : "100g", + "nutrition_grade_fr" : "d", + "nutrition_grades" : "d", + "nutrition_grades_tags" : [ + "d" + ], + "nutrition_score_beverage" : 0, + "nutrition_score_debug" : "missing energy_100g - missing fat_100g - missing saturated-fat_100g - missing sugars_100g - missing sodium_100g - missing proteins_100g", + "nutrition_score_warning_fruits_vegetables_nuts_estimate_from_ingredients" : 1, + "nutrition_score_warning_fruits_vegetables_nuts_estimate_from_ingredients_value" : 33.3333333333333, + "nutrition_score_warning_nutriments_estimated" : 1, + "origin_en" : "spain", + "other_nutritional_substances_tags" : [], + "packaging_materials_tags" : [], + "packaging_recycling_tags" : [], + "packaging_shapes_tags" : [], + "packagings" : [], + "packagings_materials" : {}, + "photographers_tags" : [], + "pnns_groups_1" : "unknown", + "pnns_groups_1_tags" : [ + "unknown", + "missing-association" + ], + "pnns_groups_2" : "unknown", + "pnns_groups_2_tags" : [ + "unknown", + "missing-association" + ], + "popularity_key" : 0, + "product_name_en" : "Vegan Test Snack with palm oil", + "product_quantity" : 100, + "quantity" : "100 g", + "removed_countries_tags" : [], + "rev" : 1, + "serving_quantity" : 10, + "serving_size" : "10 g", + "states" : "en:to-be-completed, en:nutrition-facts-completed, en:ingredients-completed, en:expiration-date-to-be-completed, en:packaging-code-to-be-completed, en:characteristics-to-be-completed, en:origins-to-be-completed, en:categories-completed, en:brands-to-be-completed, en:packaging-to-be-completed, en:quantity-completed, en:product-name-to-be-completed, en:photos-to-be-uploaded", + "states_hierarchy" : [ + "en:to-be-completed", + "en:nutrition-facts-completed", + "en:ingredients-completed", + "en:expiration-date-to-be-completed", + "en:packaging-code-to-be-completed", + "en:characteristics-to-be-completed", + "en:origins-to-be-completed", + "en:categories-completed", + "en:brands-to-be-completed", + "en:packaging-to-be-completed", + "en:quantity-completed", + "en:product-name-to-be-completed", + "en:photos-to-be-uploaded" + ], + "states_tags" : [ + "en:to-be-completed", + "en:nutrition-facts-completed", + "en:ingredients-completed", + "en:expiration-date-to-be-completed", + "en:packaging-code-to-be-completed", + "en:characteristics-to-be-completed", + "en:origins-to-be-completed", + "en:categories-completed", + "en:brands-to-be-completed", + "en:packaging-to-be-completed", + "en:quantity-completed", + "en:product-name-to-be-completed", + "en:photos-to-be-uploaded" + ], + "traces" : "", + "traces_from_ingredients" : "", + "traces_from_user" : "(en) ", + "traces_hierarchy" : [], + "traces_tags" : [], + "unknown_ingredients_n" : 0, + "unknown_nutrients_tags" : [], + "url" : "http://world.openfoodfacts.localhost/product/200000000039/vegan-test-snack-with-palm-oil", + "vitamins_tags" : [], + "weighers_tags" : [] + }, + { + "_id" : "200000000045", + "_keywords" : [ + "breakfast", + "cereal" + ], + "added_countries_tags" : [], + "additives_n" : 0, + "additives_old_n" : 0, + "additives_old_tags" : [], + "additives_original_tags" : [], + "additives_tags" : [], + "allergens" : "", + "allergens_from_ingredients" : "", + "allergens_from_user" : "(en) ", + "allergens_hierarchy" : [], + "allergens_tags" : [], + "amino_acids_tags" : [], + "categories" : "breakfast cereals", + "categories_hierarchy" : [ + "en:plant-based-foods-and-beverages", + "en:plant-based-foods", + "en:breakfasts", + "en:cereals-and-potatoes", + "en:cereals-and-their-products", + "en:breakfast-cereals" + ], + "categories_lc" : "en", + "categories_properties" : { + "agribalyse_proxy_food_code:en" : "32135", + "ciqual_food_code:en" : "32003" + }, + "categories_properties_tags" : [ + "all-products", + "categories-known", + "agribalyse-food-code-unknown", + "agribalyse-proxy-food-code-32135", + "agribalyse-proxy-food-code-known", + "ciqual-food-code-32003", + "ciqual-food-code-known", + "agribalyse-known", + "agribalyse-32135" + ], + "categories_tags" : [ + "en:plant-based-foods-and-beverages", + "en:plant-based-foods", + "en:breakfasts", + "en:cereals-and-potatoes", + "en:cereals-and-their-products", + "en:breakfast-cereals" + ], + "checkers_tags" : [], + "code" : "200000000045", + "codes_tags" : [ + "code-12", + "200000000xxx", + "20000000xxxx", + "2000000xxxxx", + "200000xxxxxx", + "20000xxxxxxx", + "2000xxxxxxxx", + "200xxxxxxxxx", + "20xxxxxxxxxx", + "2xxxxxxxxxxx" + ], + "complete" : 0, + "completeness" : 0.4, + "correctors_tags" : [], + "created_t" : "--ignore--", + "creator" : "tests", + "data_quality_bugs_tags" : [], + "data_quality_errors_tags" : [], + "data_quality_info_tags" : [ + "en:no-packaging-data", + "en:ingredients-percent-analysis-ok", + "en:ecoscore-extended-data-not-computed", + "en:food-groups-1-known", + "en:food-groups-2-known", + "en:food-groups-3-unknown" + ], + "data_quality_tags" : [ + "en:no-packaging-data", + "en:ingredients-percent-analysis-ok", + "en:ecoscore-extended-data-not-computed", + "en:food-groups-1-known", + "en:food-groups-2-known", + "en:food-groups-3-unknown", + "en:ecoscore-origins-of-ingredients-origins-are-100-percent-unknown", + "en:ecoscore-packaging-packaging-data-missing", + "en:ecoscore-production-system-no-label" + ], + "data_quality_warnings_tags" : [ + "en:ecoscore-origins-of-ingredients-origins-are-100-percent-unknown", + "en:ecoscore-packaging-packaging-data-missing", + "en:ecoscore-production-system-no-label" + ], + "ecoscore_data" : { + "adjustments" : { + "origins_of_ingredients" : { + "aggregated_origins" : [ + { + "epi_score" : 0, + "origin" : "en:unknown", + "percent" : 100, + "transportation_score" : null + } + ], + "epi_score" : 0, + "epi_value" : -5, + "origins_from_origins_field" : [ + "en:unknown" + ], + "transportation_score" : 0, + "transportation_scores" : { + "ad" : 0, + "al" : 0, + "at" : 0, + "ax" : 0, + "ba" : 0, + "be" : 0, + "bg" : 0, + "ch" : 0, + "cy" : 0, + "cz" : 0, + "de" : 0, + "dk" : 0, + "dz" : 0, + "ee" : 0, + "eg" : 0, + "es" : 0, + "fi" : 0, + "fo" : 0, + "fr" : 0, + "gg" : 0, + "gi" : 0, + "gr" : 0, + "hr" : 0, + "hu" : 0, + "ie" : 0, + "il" : 0, + "im" : 0, + "is" : 0, + "it" : 0, + "je" : 0, + "lb" : 0, + "li" : 0, + "lt" : 0, + "lu" : 0, + "lv" : 0, + "ly" : 0, + "ma" : 0, + "mc" : 0, + "md" : 0, + "me" : 0, + "mk" : 0, + "mt" : 0, + "nl" : 0, + "no" : 0, + "pl" : 0, + "ps" : 0, + "pt" : 0, + "ro" : 0, + "rs" : 0, + "se" : 0, + "si" : 0, + "sj" : 0, + "sk" : 0, + "sm" : 0, + "sy" : 0, + "tn" : 0, + "tr" : 0, + "ua" : 0, + "uk" : 0, + "us" : 0, + "va" : 0, + "world" : 0, + "xk" : 0 + }, + "transportation_value" : 0, + "transportation_values" : { + "ad" : 0, + "al" : 0, + "at" : 0, + "ax" : 0, + "ba" : 0, + "be" : 0, + "bg" : 0, + "ch" : 0, + "cy" : 0, + "cz" : 0, + "de" : 0, + "dk" : 0, + "dz" : 0, + "ee" : 0, + "eg" : 0, + "es" : 0, + "fi" : 0, + "fo" : 0, + "fr" : 0, + "gg" : 0, + "gi" : 0, + "gr" : 0, + "hr" : 0, + "hu" : 0, + "ie" : 0, + "il" : 0, + "im" : 0, + "is" : 0, + "it" : 0, + "je" : 0, + "lb" : 0, + "li" : 0, + "lt" : 0, + "lu" : 0, + "lv" : 0, + "ly" : 0, + "ma" : 0, + "mc" : 0, + "md" : 0, + "me" : 0, + "mk" : 0, + "mt" : 0, + "nl" : 0, + "no" : 0, + "pl" : 0, + "ps" : 0, + "pt" : 0, + "ro" : 0, + "rs" : 0, + "se" : 0, + "si" : 0, + "sj" : 0, + "sk" : 0, + "sm" : 0, + "sy" : 0, + "tn" : 0, + "tr" : 0, + "ua" : 0, + "uk" : 0, + "us" : 0, + "va" : 0, + "world" : 0, + "xk" : 0 + }, + "value" : -5, + "values" : { + "ad" : -5, + "al" : -5, + "at" : -5, + "ax" : -5, + "ba" : -5, + "be" : -5, + "bg" : -5, + "ch" : -5, + "cy" : -5, + "cz" : -5, + "de" : -5, + "dk" : -5, + "dz" : -5, + "ee" : -5, + "eg" : -5, + "es" : -5, + "fi" : -5, + "fo" : -5, + "fr" : -5, + "gg" : -5, + "gi" : -5, + "gr" : -5, + "hr" : -5, + "hu" : -5, + "ie" : -5, + "il" : -5, + "im" : -5, + "is" : -5, + "it" : -5, + "je" : -5, + "lb" : -5, + "li" : -5, + "lt" : -5, + "lu" : -5, + "lv" : -5, + "ly" : -5, + "ma" : -5, + "mc" : -5, + "md" : -5, + "me" : -5, + "mk" : -5, + "mt" : -5, + "nl" : -5, + "no" : -5, + "pl" : -5, + "ps" : -5, + "pt" : -5, + "ro" : -5, + "rs" : -5, + "se" : -5, + "si" : -5, + "sj" : -5, + "sk" : -5, + "sm" : -5, + "sy" : -5, + "tn" : -5, + "tr" : -5, + "ua" : -5, + "uk" : -5, + "us" : -5, + "va" : -5, + "world" : -5, + "xk" : -5 + }, + "warning" : "origins_are_100_percent_unknown" + }, + "packaging" : { + "non_recyclable_and_non_biodegradable_materials" : 1, + "value" : -15, + "warning" : "packaging_data_missing" + }, + "production_system" : { + "labels" : [], + "value" : 0, + "warning" : "no_label" + }, + "threatened_species" : {} + }, + "agribalyse" : { + "agribalyse_proxy_food_code" : "32135", + "co2_agriculture" : 2.2396004, + "co2_consumption" : 0, + "co2_distribution" : 0.019530673, + "co2_packaging" : 0.28159592, + "co2_processing" : 0.77051126, + "co2_total" : 3.564111983, + "co2_transportation" : 0.25287373, + "code" : "32135", + "dqr" : "4.03", + "ef_agriculture" : 0.50064279, + "ef_consumption" : 0, + "ef_distribution" : 0.0048315303, + "ef_packaging" : 0.023715692, + "ef_processing" : 0.078716079, + "ef_total" : 0.6323498093, + "ef_transportation" : 0.024443718, + "is_beverage" : 0, + "name_en" : "Breakfast cereals, mix of puffed or extruded cereals, fortified with vitamins and chemical elements", + "name_fr" : "Multi-céréales soufflées ou extrudées, enrichies en vitamines et minéraux", + "score" : 45, + "version" : "3.1" + }, + "grade" : "d", + "grades" : { + "ad" : "d", + "al" : "d", + "at" : "d", + "ax" : "d", + "ba" : "d", + "be" : "d", + "bg" : "d", + "ch" : "d", + "cy" : "d", + "cz" : "d", + "de" : "d", + "dk" : "d", + "dz" : "d", + "ee" : "d", + "eg" : "d", + "es" : "d", + "fi" : "d", + "fo" : "d", + "fr" : "d", + "gg" : "d", + "gi" : "d", + "gr" : "d", + "hr" : "d", + "hu" : "d", + "ie" : "d", + "il" : "d", + "im" : "d", + "is" : "d", + "it" : "d", + "je" : "d", + "lb" : "d", + "li" : "d", + "lt" : "d", + "lu" : "d", + "lv" : "d", + "ly" : "d", + "ma" : "d", + "mc" : "d", + "md" : "d", + "me" : "d", + "mk" : "d", + "mt" : "d", + "nl" : "d", + "no" : "d", + "pl" : "d", + "ps" : "d", + "pt" : "d", + "ro" : "d", + "rs" : "d", + "se" : "d", + "si" : "d", + "sj" : "d", + "sk" : "d", + "sm" : "d", + "sy" : "d", + "tn" : "d", + "tr" : "d", + "ua" : "d", + "uk" : "d", + "us" : "d", + "va" : "d", + "world" : "d", + "xk" : "d" + }, + "missing" : { + "labels" : 1, + "origins" : 1, + "packagings" : 1 + }, + "missing_data_warning" : 1, + "missing_key_data" : 1, + "score" : 25, + "scores" : { + "ad" : 25, + "al" : 25, + "at" : 25, + "ax" : 25, + "ba" : 25, + "be" : 25, + "bg" : 25, + "ch" : 25, + "cy" : 25, + "cz" : 25, + "de" : 25, + "dk" : 25, + "dz" : 25, + "ee" : 25, + "eg" : 25, + "es" : 25, + "fi" : 25, + "fo" : 25, + "fr" : 25, + "gg" : 25, + "gi" : 25, + "gr" : 25, + "hr" : 25, + "hu" : 25, + "ie" : 25, + "il" : 25, + "im" : 25, + "is" : 25, + "it" : 25, + "je" : 25, + "lb" : 25, + "li" : 25, + "lt" : 25, + "lu" : 25, + "lv" : 25, + "ly" : 25, + "ma" : 25, + "mc" : 25, + "md" : 25, + "me" : 25, + "mk" : 25, + "mt" : 25, + "nl" : 25, + "no" : 25, + "pl" : 25, + "ps" : 25, + "pt" : 25, + "ro" : 25, + "rs" : 25, + "se" : 25, + "si" : 25, + "sj" : 25, + "sk" : 25, + "sm" : 25, + "sy" : 25, + "tn" : 25, + "tr" : 25, + "ua" : 25, + "uk" : 25, + "us" : 25, + "va" : 25, + "world" : 25, + "xk" : 25 + }, + "status" : "known" + }, + "ecoscore_grade" : "d", + "ecoscore_score" : 25, + "ecoscore_tags" : [ + "d" + ], + "editors_tags" : [ + "tests" + ], + "entry_dates_tags" : "--ignore--", + "food_groups" : "en:breakfast-cereals", + "food_groups_tags" : [ + "en:cereals-and-potatoes", + "en:breakfast-cereals" + ], + "generic_name_en" : "Tester", + "id" : "200000000045", + "informers_tags" : [ + "tests" + ], + "ingredients" : [ + { + "ciqual_food_code" : "13050", + "id" : "en:apple", + "percent_estimate" : 75, + "percent_max" : 100, + "percent_min" : 50, + "rank" : 1, + "text" : "apple", + "vegan" : "yes", + "vegetarian" : "yes" + }, + { + "ciqual_food_code" : "18066", + "id" : "en:water", + "percent_estimate" : 25, + "percent_max" : 50, + "percent_min" : 0, + "rank" : 2, + "text" : "water", + "vegan" : "yes", + "vegetarian" : "yes" + } + ], + "ingredients_analysis" : {}, + "ingredients_analysis_tags" : [ + "en:palm-oil-free", + "en:vegan", + "en:vegetarian" + ], + "ingredients_from_or_that_may_be_from_palm_oil_n" : 0, + "ingredients_from_palm_oil_n" : 0, + "ingredients_from_palm_oil_tags" : [], + "ingredients_hierarchy" : [ + "en:apple", + "en:fruit", + "en:water" + ], + "ingredients_lc" : "en", + "ingredients_n" : 2, + "ingredients_n_tags" : [ + "2", + "1-10" + ], + "ingredients_original_tags" : [ + "en:apple", + "en:water" + ], + "ingredients_percent_analysis" : 1, + "ingredients_tags" : [ + "en:apple", + "en:fruit", + "en:water" + ], + "ingredients_text" : "apple, water", + "ingredients_text_en" : "apple, water", + "ingredients_text_with_allergens" : "apple, water", + "ingredients_text_with_allergens_en" : "apple, water", + "ingredients_that_may_be_from_palm_oil_n" : 0, + "ingredients_that_may_be_from_palm_oil_tags" : [], + "ingredients_with_specified_percent_n" : 0, + "ingredients_with_specified_percent_sum" : 0, + "ingredients_with_unspecified_percent_n" : 2, + "ingredients_with_unspecified_percent_sum" : 100, + "ingredients_without_ciqual_codes" : [], + "ingredients_without_ciqual_codes_n" : 0, + "interface_version_created" : "20150316.jqm2", + "interface_version_modified" : "20150316.jqm2", + "known_ingredients_n" : 3, + "lang" : "es", + "languages" : { + "en:english" : 5 + }, + "languages_codes" : { + "en" : 5 + }, + "languages_hierarchy" : [ + "en:english" + ], + "languages_tags" : [ + "en:english", + "en:1" + ], + "last_edit_dates_tags" : "--ignore--", + "last_editor" : "tests", + "last_modified_by" : "tests", + "last_modified_t" : "--ignore--", + "lc" : "es", + "link" : "http://world.openfoodfacts.org/", + "main_countries_tags" : [], + "minerals_tags" : [], + "misc_tags" : [ + "en:nutrition-not-enough-data-to-compute-nutrition-score", + "en:nutriscore-missing-nutrition-data", + "en:nutriscore-missing-nutrition-data-energy", + "en:nutriscore-missing-nutrition-data-fat", + "en:nutriscore-missing-nutrition-data-saturated-fat", + "en:nutriscore-missing-nutrition-data-sugars", + "en:nutriscore-missing-nutrition-data-sodium", + "en:nutriscore-missing-nutrition-data-proteins", + "en:nutrition-no-fiber", + "en:nutriscore-using-estimated-nutrition-facts", + "en:nutriscore-computed", + "en:nutrition-fruits-vegetables-nuts-estimate-from-ingredients", + "en:nutrition-all-nutriscore-values-known", + "en:nutriscore-2021-different-from-2023", + "en:nutriscore-2021-better-than-2023", + "en:nutriscore-2021-a-2023-b", + "en:packagings-number-of-components-0", + "en:packagings-not-complete", + "en:packagings-empty", + "en:ecoscore-extended-data-not-computed", + "en:ecoscore-missing-data-warning", + "en:ecoscore-missing-data-labels", + "en:ecoscore-missing-data-origins", + "en:ecoscore-missing-data-packagings", + "en:ecoscore-missing-data-no-packagings", + "en:ecoscore-computed", + "en:ecoscore-changed", + "en:ecoscore-grade-changed", + "en:main-countries-new-product" + ], + "nova_group" : 1, + "nova_group_debug" : "", + "nova_groups" : "1", + "nova_groups_markers" : {}, + "nova_groups_tags" : [ + "en:1-unprocessed-or-minimally-processed-foods" + ], + "nucleotides_tags" : [], + "nutrient_levels" : {}, + "nutrient_levels_tags" : [], + "nutriments" : { + "fruits-vegetables-nuts-estimate-from-ingredients_100g" : 50, + "fruits-vegetables-nuts-estimate-from-ingredients_serving" : 50, + "nova-group" : 1, + "nova-group_100g" : 1, + "nova-group_serving" : 1, + "nutrition-score-fr" : -1, + "nutrition-score-fr_100g" : -1 + }, + "nutriments_estimated" : { + "alcohol_100g" : 0, + "beta-carotene_100g" : 1.275e-05, + "calcium_100g" : 0.0055325, + "carbohydrates_100g" : 8.025, + "cholesterol_100g" : 0, + "copper_100g" : 2.75e-05, + "energy-kcal_100g" : 36.675, + "energy-kj_100g" : 155.25, + "energy_100g" : 155.25, + "fat_100g" : 0.0975, + "fiber_100g" : 0.975, + "fructose_100g" : 4.5225, + "galactose_100g" : 0, + "glucose_100g" : 2.4375, + "iodine_100g" : 7.5e-08, + "iron_100g" : 6e-05, + "lactose_100g" : 0, + "magnesium_100g" : 0.0032475, + "maltose_100g" : 0, + "manganese_100g" : 2.8705e-05, + "pantothenic-acid_100g" : 5.325e-05, + "phosphorus_100g" : 0.00825, + "phylloquinone_100g" : 4.5e-07, + "polyols_100g" : 0.4425, + "potassium_100g" : 0.0676825, + "proteins_100g" : 0.2025, + "salt_100g" : 0.0019, + "saturated-fat_100g" : 0.01575, + "selenium_100g" : 2.375e-07, + "sodium_100g" : 0.0006, + "starch_100g" : 0, + "sucrose_100g" : 0.615, + "sugars_100g" : 7.575, + "vitamin-a_100g" : 0, + "vitamin-b12_100g" : 0, + "vitamin-b1_100g" : 1.425e-05, + "vitamin-b2_100g" : 2.1e-05, + "vitamin-b6_100g" : 2.775e-05, + "vitamin-b9_100g" : 0, + "vitamin-c_100g" : 0.003, + "vitamin-d_100g" : 0, + "vitamin-e_100g" : 3.75e-05, + "vitamin-pp_100g" : 6.825e-05, + "water_100g" : 90.025, + "zinc_100g" : 4.025e-05 + }, + "nutriscore" : { + "2021" : { + "category_available" : 1, + "data" : { + "energy" : 155.25, + "energy_points" : 0, + "energy_value" : 155.3, + "fiber" : 0.975, + "fiber_points" : 1, + "fiber_value" : 0.98, + "fruits_vegetables_nuts_colza_walnut_olive_oils" : 50, + "fruits_vegetables_nuts_colza_walnut_olive_oils_points" : 1, + "fruits_vegetables_nuts_colza_walnut_olive_oils_value" : 50, + "is_beverage" : 0, + "is_cheese" : 0, + "is_fat" : 0, + "is_water" : 0, + "negative_points" : 1, + "positive_points" : 2, + "proteins" : 0.2025, + "proteins_points" : 0, + "proteins_value" : 0.2, + "saturated_fat" : 0.01575, + "saturated_fat_points" : 0, + "saturated_fat_value" : 0, + "sodium" : 0.6, + "sodium_points" : 0, + "sodium_value" : 0.6, + "sugars" : 7.575, + "sugars_points" : 1, + "sugars_value" : 7.58 + }, + "grade" : "a", + "nutrients_available" : 1, + "nutriscore_applicable" : 1, + "nutriscore_computed" : 1, + "score" : -1 + }, + "2023" : { + "category_available" : 1, + "data" : { + "count_proteins" : 1, + "count_proteins_reason" : "negative_points_less_than_11", + "energy" : 155.25, + "energy_points" : 0, + "fiber" : 0.975, + "fiber_points" : 0, + "fruits_vegetables_legumes" : 50, + "fruits_vegetables_legumes_points" : 1, + "is_beverage" : 0, + "is_cheese" : 0, + "is_fat_oil_nuts_seeds" : 0, + "is_water" : 0, + "negative_nutrients" : [ + "energy", + "sugars", + "saturated_fat", + "salt", + "sweeteners" + ], + "negative_points" : 2, + "positive_nutrients" : [ + "fruits_vegetables_legumes", + "fiber", + "proteins" + ], + "positive_points" : 1, + "proteins" : 0.2025, + "proteins_points" : 0, + "salt" : 0.0019, + "salt_points" : 0, + "saturated_fat" : 0.01575, + "saturated_fat_points" : 0, + "sugars" : 7.575, + "sugars_points" : 2 + }, + "grade" : "b", + "nutrients_available" : 1, + "nutriscore_applicable" : 1, + "nutriscore_computed" : 1, + "score" : 1 + } + }, + "nutriscore_2021_tags" : [ + "a" + ], + "nutriscore_2023_tags" : [ + "b" + ], + "nutriscore_data" : { + "energy" : 155.25, + "energy_points" : 0, + "energy_value" : 155.3, + "fiber" : 0.975, + "fiber_points" : 1, + "fiber_value" : 0.98, + "fruits_vegetables_nuts_colza_walnut_olive_oils" : 50, + "fruits_vegetables_nuts_colza_walnut_olive_oils_points" : 1, + "fruits_vegetables_nuts_colza_walnut_olive_oils_value" : 50, + "grade" : "a", + "is_beverage" : 0, + "is_cheese" : 0, + "is_fat" : 0, + "is_water" : 0, + "negative_points" : 1, + "positive_points" : 2, + "proteins" : 0.2025, + "proteins_points" : 0, + "proteins_value" : 0.2, + "saturated_fat" : 0.01575, + "saturated_fat_points" : 0, + "saturated_fat_value" : 0, + "score" : -1, + "sodium" : 0.6, + "sodium_points" : 0, + "sodium_value" : 0.6, + "sugars" : 7.575, + "sugars_points" : 1, + "sugars_value" : 7.58 + }, + "nutriscore_grade" : "a", + "nutriscore_score" : -1, + "nutriscore_score_opposite" : 1, + "nutriscore_tags" : [ + "a" + ], + "nutriscore_version" : "2021", + "nutrition_data_per" : "100g", + "nutrition_data_prepared_per" : "100g", + "nutrition_grade_fr" : "a", + "nutrition_grades" : "a", + "nutrition_grades_tags" : [ + "a" + ], + "nutrition_score_beverage" : 0, + "nutrition_score_debug" : "missing energy_100g - missing fat_100g - missing saturated-fat_100g - missing sugars_100g - missing sodium_100g - missing proteins_100g", + "nutrition_score_warning_fruits_vegetables_nuts_estimate_from_ingredients" : 1, + "nutrition_score_warning_fruits_vegetables_nuts_estimate_from_ingredients_value" : 50, + "nutrition_score_warning_nutriments_estimated" : 1, + "origin_en" : "China", + "other_nutritional_substances_tags" : [], + "packaging_materials_tags" : [], + "packaging_recycling_tags" : [], + "packaging_shapes_tags" : [], + "packaging_text_en" : "no", + "packagings" : [], + "packagings_materials" : {}, + "photographers_tags" : [], + "pnns_groups_1" : "Cereals and potatoes", + "pnns_groups_1_tags" : [ + "cereals-and-potatoes", + "known" + ], + "pnns_groups_2" : "Breakfast cereals", + "pnns_groups_2_tags" : [ + "breakfast-cereals", + "known" + ], + "popularity_key" : 0, + "product_name_en" : "Vegan breakfast cereals without palm oil", + "product_quantity" : 100, + "quantity" : "100 g", + "removed_countries_tags" : [], + "rev" : 1, + "serving_quantity" : 10, + "serving_size" : "10 g", + "states" : "en:to-be-completed, en:nutrition-facts-completed, en:ingredients-completed, en:expiration-date-to-be-completed, en:packaging-code-to-be-completed, en:characteristics-to-be-completed, en:origins-to-be-completed, en:categories-completed, en:brands-to-be-completed, en:packaging-to-be-completed, en:quantity-completed, en:product-name-to-be-completed, en:photos-to-be-uploaded", + "states_hierarchy" : [ + "en:to-be-completed", + "en:nutrition-facts-completed", + "en:ingredients-completed", + "en:expiration-date-to-be-completed", + "en:packaging-code-to-be-completed", + "en:characteristics-to-be-completed", + "en:origins-to-be-completed", + "en:categories-completed", + "en:brands-to-be-completed", + "en:packaging-to-be-completed", + "en:quantity-completed", + "en:product-name-to-be-completed", + "en:photos-to-be-uploaded" + ], + "states_tags" : [ + "en:to-be-completed", + "en:nutrition-facts-completed", + "en:ingredients-completed", + "en:expiration-date-to-be-completed", + "en:packaging-code-to-be-completed", + "en:characteristics-to-be-completed", + "en:origins-to-be-completed", + "en:categories-completed", + "en:brands-to-be-completed", + "en:packaging-to-be-completed", + "en:quantity-completed", + "en:product-name-to-be-completed", + "en:photos-to-be-uploaded" + ], + "traces" : "", + "traces_from_ingredients" : "", + "traces_from_user" : "(en) ", + "traces_hierarchy" : [], + "traces_tags" : [], + "unknown_ingredients_n" : 0, + "unknown_nutrients_tags" : [], + "url" : "http://world.openfoodfacts.localhost/product/200000000045/vegan-breakfast-cereals-without-palm-oil", + "vitamins_tags" : [], + "weighers_tags" : [] + }, { "_id" : "200000000046", "_keywords" : [ @@ -2569,6 +4225,7 @@ "en:fruit", "en:water" ], + "ingredients_lc" : "en", "ingredients_n" : 2, "ingredients_n_tags" : [ "2", diff --git a/tests/unit/expected_test_results/attributes/en-attributes.json b/tests/unit/expected_test_results/attributes/en-attributes.json index 0067d2cf06100..cd339395a269f 100644 --- a/tests/unit/expected_test_results/attributes/en-attributes.json +++ b/tests/unit/expected_test_results/attributes/en-attributes.json @@ -1003,6 +1003,7 @@ "en:e102", "en:e120" ], + "ingredients_lc" : "en", "ingredients_n" : 11, "ingredients_n_tags" : [ "11", diff --git a/tests/unit/expected_test_results/attributes/en-ecoscore-score-at-20-threshold.json b/tests/unit/expected_test_results/attributes/en-ecoscore-score-at-20-threshold.json index 45d94e4a8f833..d2520f07d0caa 100644 --- a/tests/unit/expected_test_results/attributes/en-ecoscore-score-at-20-threshold.json +++ b/tests/unit/expected_test_results/attributes/en-ecoscore-score-at-20-threshold.json @@ -780,6 +780,7 @@ ], "food_groups_tags" : [], "ingredients_from_palm_oil_tags" : [], + "ingredients_lc" : "en", "ingredients_text" : "", "ingredients_that_may_be_from_palm_oil_tags" : [], "languages" : {}, diff --git a/tests/unit/expected_test_results/attributes/en-maybe-vegan.json b/tests/unit/expected_test_results/attributes/en-maybe-vegan.json index 55040db970069..818bea8c4df97 100644 --- a/tests/unit/expected_test_results/attributes/en-maybe-vegan.json +++ b/tests/unit/expected_test_results/attributes/en-maybe-vegan.json @@ -681,6 +681,7 @@ "en:palm-oil-and-fat", "en:enzyme" ], + "ingredients_lc" : "en", "ingredients_n" : 3, "ingredients_n_tags" : [ "3", diff --git a/tests/unit/expected_test_results/attributes/en-no-ingredients.json b/tests/unit/expected_test_results/attributes/en-no-ingredients.json index 2623b64d8939d..967317df19da4 100644 --- a/tests/unit/expected_test_results/attributes/en-no-ingredients.json +++ b/tests/unit/expected_test_results/attributes/en-no-ingredients.json @@ -779,6 +779,7 @@ "en:milk-and-dairy-products", "en:cheese" ], + "ingredients_lc" : "en", "languages" : {}, "languages_codes" : {}, "languages_hierarchy" : [], diff --git a/tests/unit/expected_test_results/attributes/en-nova-groups-markers.json b/tests/unit/expected_test_results/attributes/en-nova-groups-markers.json index db5e2efe88981..02cb3fc898ecf 100644 --- a/tests/unit/expected_test_results/attributes/en-nova-groups-markers.json +++ b/tests/unit/expected_test_results/attributes/en-nova-groups-markers.json @@ -896,6 +896,7 @@ "en:corn-syrup", "en:glucose-fructose-syrup" ], + "ingredients_lc" : "en", "ingredients_n" : 7, "ingredients_n_tags" : [ "7", diff --git a/tests/unit/expected_test_results/attributes/en-nutriscore.json b/tests/unit/expected_test_results/attributes/en-nutriscore.json index c3e386967d423..dd70f9654d2b8 100644 --- a/tests/unit/expected_test_results/attributes/en-nutriscore.json +++ b/tests/unit/expected_test_results/attributes/en-nutriscore.json @@ -808,6 +808,7 @@ "ingredients_hierarchy" : [ "en:fruit" ], + "ingredients_lc" : "en", "ingredients_n" : 1, "ingredients_n_tags" : [ "1", diff --git a/tests/unit/expected_test_results/attributes/en-unknown-ingredients.json b/tests/unit/expected_test_results/attributes/en-unknown-ingredients.json index 92173dc0c45ef..2b93e8435586f 100644 --- a/tests/unit/expected_test_results/attributes/en-unknown-ingredients.json +++ b/tests/unit/expected_test_results/attributes/en-unknown-ingredients.json @@ -816,6 +816,7 @@ "ingredients_hierarchy" : [ "en:some-ingredient-that-we-do-not-recognize" ], + "ingredients_lc" : "en", "ingredients_n" : 1, "ingredients_n_tags" : [ "1", diff --git a/tests/unit/expected_test_results/attributes/fr-palm-kernel-fat.json b/tests/unit/expected_test_results/attributes/fr-palm-kernel-fat.json index f264047395125..d175b76004d19 100644 --- a/tests/unit/expected_test_results/attributes/fr-palm-kernel-fat.json +++ b/tests/unit/expected_test_results/attributes/fr-palm-kernel-fat.json @@ -653,6 +653,7 @@ "en:vegetable-oil-and-fat", "en:palm-kernel-oil-and-fat" ], + "ingredients_lc" : "fr", "ingredients_n" : 1, "ingredients_n_tags" : [ "1", diff --git a/tests/unit/expected_test_results/attributes/fr-palm-oil-free.json b/tests/unit/expected_test_results/attributes/fr-palm-oil-free.json index 85b28e8e91bb4..addb6a7cedd23 100644 --- a/tests/unit/expected_test_results/attributes/fr-palm-oil-free.json +++ b/tests/unit/expected_test_results/attributes/fr-palm-oil-free.json @@ -675,6 +675,7 @@ "en:disaccharide", "en:chocolate" ], + "ingredients_lc" : "fr", "ingredients_n" : 4, "ingredients_n_tags" : [ "4", diff --git a/tests/unit/expected_test_results/attributes/fr-palm-oil.json b/tests/unit/expected_test_results/attributes/fr-palm-oil.json index 7d3f106dacd60..9e2c9b8ca609a 100644 --- a/tests/unit/expected_test_results/attributes/fr-palm-oil.json +++ b/tests/unit/expected_test_results/attributes/fr-palm-oil.json @@ -666,6 +666,7 @@ "en:vegetable-oil-and-fat", "en:palm-oil-and-fat" ], + "ingredients_lc" : "fr", "ingredients_n" : 2, "ingredients_n_tags" : [ "2", diff --git a/tests/unit/expected_test_results/attributes/fr-vegetable-oils.json b/tests/unit/expected_test_results/attributes/fr-vegetable-oils.json index 23cb5a7f23b27..2d95d393e54eb 100644 --- a/tests/unit/expected_test_results/attributes/fr-vegetable-oils.json +++ b/tests/unit/expected_test_results/attributes/fr-vegetable-oils.json @@ -670,6 +670,7 @@ "en:vegetable-oil-and-fat", "en:salt" ], + "ingredients_lc" : "fr", "ingredients_n" : 3, "ingredients_n_tags" : [ "3",