diff --git a/cgi/export_products.pl b/cgi/export_products.pl index 46f06f8d5a335..5cba4221a9952 100755 --- a/cgi/export_products.pl +++ b/cgi/export_products.pl @@ -74,7 +74,7 @@ if ($action eq "display") { - my $template_data_ref = {lang => \&lang,}; + my $template_data_ref = {}; # Query filters @@ -95,25 +95,10 @@ } } - # Number of products matching the optional query - my $count = count_products({}, $query_ref); - # Number of products matching the query with changes that have not yet been imported $query_ref->{states_tags} = "en:to-be-exported"; - my $count_to_be_exported = count_products({}, $query_ref); - - $template_data_ref->{count} = $count; - $template_data_ref->{count_to_be_exported} = $count_to_be_exported; - - if ($count == 0) { - $template_data_ref->{n_products_will_be_exported} = lang("no_products_to_export"); - } - elsif ($count == 1) { - $template_data_ref->{n_products_will_be_exported} = lang("one_product_will_be_exported"); - } - else { - $template_data_ref->{n_products_will_be_exported} = sprintf(lang("n_products_will_be_exported"), $count); - } + $template_data_ref->{count_to_be_exported} = count_products({}, $query_ref); + $template_data_ref->{count_obsolete_to_be_exported} = count_products({}, $query_ref, 1); my $export_photos_value = ""; my $replace_selected_photos_value = ""; diff --git a/lib/ProductOpener/Display.pm b/lib/ProductOpener/Display.pm index 60ee9e5014360..d8cbdf48b0d2c 100644 --- a/lib/ProductOpener/Display.pm +++ b/lib/ProductOpener/Display.pm @@ -1027,15 +1027,10 @@ sub display_index_for_producer ($request_ref) { } # Display a message if some product updates have not been published yet + # Updates can also be on obsolete products - my $count = count_products($request_ref, {states_tags => "en:to-be-exported"}); - - if ($count == 1) { - $template_data_ref->{products_to_be_exported} = lang("one_product_will_be_exported"); - } - elsif ($count > 1) { - $template_data_ref->{products_to_be_exported} = sprintf(lang("n_products_will_be_exported"), $count); - } + $template_data_ref->{count_to_be_exported} = count_products({}, {states_tags => "en:to-be-exported"}); + $template_data_ref->{count_obsolete_to_be_exported} = count_products({}, {states_tags => "en:to-be-exported"}, 1); my $html; @@ -4369,7 +4364,7 @@ sub add_country_and_owner_filters_to_query ($request_ref, $query_ref) { return; } -sub count_products ($request_ref, $query_ref) { +sub count_products ($request_ref, $query_ref, $obsolete = 0) { add_country_and_owner_filters_to_query($request_ref, $query_ref); @@ -4379,8 +4374,7 @@ sub count_products ($request_ref, $query_ref) { $log->debug("Counting MongoDB documents for query", {query => $query_ref}) if $log->is_debug(); $count = execute_query( sub { - return get_products_collection({obsolete => request_param($request_ref, "obsolete")}) - ->count_documents($query_ref); + return get_products_collection({obsolete => $obsolete})->count_documents($query_ref); } ); }; diff --git a/lib/ProductOpener/Export.pm b/lib/ProductOpener/Export.pm index 42f61c83d7cec..e28f2bf1ed117 100644 --- a/lib/ProductOpener/Export.pm +++ b/lib/ProductOpener/Export.pm @@ -159,6 +159,10 @@ for front, ingredients and nutrition in all languages. This option is used in particular for exporting from the producers platform and importing to the public database. +=head4 include_obsolete_products - optional - Also export obsolete products + +Obsolete products are in the products_obsolete collection. + =head4 Return value Count of the exported documents. @@ -186,196 +190,222 @@ sub export_csv ($args_ref) { $log->debug("export_csv - start", {args_ref => $args_ref}) if $log->is_debug(); - my $count = get_products_collection()->count_documents($query_ref); - - $log->debug("export_csv - documents to export", {count => $count}) if $log->is_debug(); - - my $cursor = get_products_collection()->find($query_ref); - $cursor->immortal(1); + # We have products in 2 MongoDB collections: + # - products: current products + # - products_obsolete: obsolete products (withdrawn from the market) - # First pass - go through products to see which fields are populated, - # unless the fields to export are specified with the fields parameter. + my @collections = ("products"); # products collection + if ($args_ref->{include_obsolete_products}) { + push @collections, {"products_obsolete"}; + } + # Create a list of the fields that we will export my @sorted_populated_fields; my %other_images = (); - if (not defined $fields_ref) { + # We will have one cursor for each collection + # We store cursors because we will iterate them twice + my %cursors = (); + + if (defined $fields_ref) { + # The fields to export are specified by the fields parameter + @sorted_populated_fields = @{$fields_ref}; + } + else { + + # First pass - go through products to see which fields are populated, + # unless the fields to export are specified with the fields parameter. # %populated_fields will contain the field name as the key, # and a sort key as the value so that the CSV columns are in the order of $options{import_export_fields_groups} my %populated_fields = (); - while (my $product_ref = $cursor->next) { + # Loop on collections + foreach my $collection (@collections) { - # Possible fields to export are listed in $options{import_export_fields_groups} + my $obsolete = ($collection eq "products_obsolete") ? 1 : 0; - my @fields_groups = @{$options{import_export_fields_groups}}; + my $count = get_products_collection({obsolete => $obsolete})->count_documents($query_ref); - # Add fields computed by OFF if requested - if (($export_computed_fields) and (defined $options{off_export_fields_groups})) { - push @fields_groups, @{$options{off_export_fields_groups}}; - } + $log->debug("export_csv - documents to export", {count => $count, collection => $collection}) + if $log->is_debug(); - my $group_number = 0; + $cursors{$collection} = get_products_collection({obsolete => $obsolete})->find($query_ref); + $cursors{$collection}->immortal(1); - foreach my $group_ref (@fields_groups) { + while (my $product_ref = $cursors{$collection}->next) { - $group_number++; - my $item_number = 0; + # Possible fields to export are listed in $options{import_export_fields_groups} - my $group_id = $group_ref->[0]; + my @fields_groups = @{$options{import_export_fields_groups}}; - if (($group_id eq "nutrition") or ($group_id eq "nutrition_other")) { + # Add fields computed by OFF if requested + if (($export_computed_fields) and (defined $options{off_export_fields_groups})) { + push @fields_groups, @{$options{off_export_fields_groups}}; + } - if ($group_id eq "nutrition") { - foreach my $field ("no_nutrition_data", "nutrition_data_per", "nutrition_data_prepared_per") { - $item_number++; - if ((defined $product_ref->{$field}) and ($product_ref->{$field} ne "")) { - $populated_fields{$field} = sprintf("%08d", $group_number * 1000 + $item_number); - } - } - } + my $group_number = 0; - next if not defined $product_ref->{nutriments}; + foreach my $group_ref (@fields_groups) { - # Go through the nutriment table - foreach my $nutriment (@{$nutriments_tables{europe}}) { + $group_number++; + my $item_number = 0; - next if $nutriment =~ /^\#/; - my $nid = $nutriment; + my $group_id = $group_ref->[0]; - # %Food::nutriments_tables ids have an ending - for nutrients that are not displayed by default + if (($group_id eq "nutrition") or ($group_id eq "nutrition_other")) { if ($group_id eq "nutrition") { - if ($nid =~ /-$/) { - next; + foreach my $field ("no_nutrition_data", "nutrition_data_per", "nutrition_data_prepared_per") + { + $item_number++; + if ((defined $product_ref->{$field}) and ($product_ref->{$field} ne "")) { + $populated_fields{$field} = sprintf("%08d", $group_number * 1000 + $item_number); + } } } - else { - if ($nid !~ /-$/) { - next; + + next if not defined $product_ref->{nutriments}; + + # Go through the nutriment table + foreach my $nutriment (@{$nutriments_tables{europe}}) { + + next if $nutriment =~ /^\#/; + my $nid = $nutriment; + + # %Food::nutriments_tables ids have an ending - for nutrients that are not displayed by default + + if ($group_id eq "nutrition") { + if ($nid =~ /-$/) { + next; + } + } + else { + if ($nid !~ /-$/) { + next; + } } - } - $item_number++; - my $field_sort_key = sprintf("%08d", $group_number * 1000 + $item_number); + $item_number++; + my $field_sort_key = sprintf("%08d", $group_number * 1000 + $item_number); - $nid =~ s/^(-|!)+//g; - $nid =~ s/-$//g; + $nid =~ s/^(-|!)+//g; + $nid =~ s/-$//g; - # Order of the fields: sugars_value, sugars_unit, sugars_prepared_value, sugars_prepared_unit + # Order of the fields: sugars_value, sugars_unit, sugars_prepared_value, sugars_prepared_unit - if ( (defined $product_ref->{nutriments}{$nid . "_value"}) - and ($product_ref->{nutriments}{$nid . "_value"} ne "")) - { - $populated_fields{$nid . "_value"} = $field_sort_key . "_1"; - $populated_fields{$nid . "_unit"} = $field_sort_key . "_2"; - } - if ( (defined $product_ref->{nutriments}{$nid . "_prepared_value"}) - and ($product_ref->{nutriments}{$nid . "_prepared_value"} ne "")) - { - $populated_fields{$nid . "_prepared_value"} = $field_sort_key . "_3"; - $populated_fields{$nid . "_prepared_unit"} = $field_sort_key . "_4"; + if ( (defined $product_ref->{nutriments}{$nid . "_value"}) + and ($product_ref->{nutriments}{$nid . "_value"} ne "")) + { + $populated_fields{$nid . "_value"} = $field_sort_key . "_1"; + $populated_fields{$nid . "_unit"} = $field_sort_key . "_2"; + } + if ( (defined $product_ref->{nutriments}{$nid . "_prepared_value"}) + and ($product_ref->{nutriments}{$nid . "_prepared_value"} ne "")) + { + $populated_fields{$nid . "_prepared_value"} = $field_sort_key . "_3"; + $populated_fields{$nid . "_prepared_unit"} = $field_sort_key . "_4"; + } } } - } - elsif ($group_id eq "packaging") { - # packaging data will be exported in the CSV file in columns named like packaging_1_number_of_units - if (defined $product_ref->{packagings}) { - my $i = 0; # number of the packaging component - foreach my $packaging_ref (@{$product_ref->{packagings}}) { - $i++; - my $j = 0; # number of the field - foreach my $field ( - qw(number_of_units shape material recycling quantity_per_unit weight_specified weight_measured) - ) - { - $j++; - if (defined $packaging_ref->{$field}) { - # Generate a sort key so that the packaging fields in the CSV file are in this order: - # - all fields for packaging component 1, then all fields for packaging component 2 - # - number_of_units, shape, material etc. (same a for loop above) - my $field_sort_key = sprintf("%08d", $group_number * 1000 + $i * 10 + $j); - $populated_fields{"packaging_" . $i . "_" . $field} = $field_sort_key; + elsif ($group_id eq "packaging") { + # packaging data will be exported in the CSV file in columns named like packaging_1_number_of_units + if (defined $product_ref->{packagings}) { + my $i = 0; # number of the packaging component + foreach my $packaging_ref (@{$product_ref->{packagings}}) { + $i++; + my $j = 0; # number of the field + foreach my $field ( + qw(number_of_units shape material recycling quantity_per_unit weight_specified weight_measured) + ) + { + $j++; + if (defined $packaging_ref->{$field}) { + # Generate a sort key so that the packaging fields in the CSV file are in this order: + # - all fields for packaging component 1, then all fields for packaging component 2 + # - number_of_units, shape, material etc. (same a for loop above) + my $field_sort_key = sprintf("%08d", $group_number * 1000 + $i * 10 + $j); + $populated_fields{"packaging_" . $i . "_" . $field} = $field_sort_key; + } } } } } - } - elsif ($group_id eq "images") { - if ($args_ref->{include_images_paths}) { - if (defined $product_ref->{images}) { - include_image_paths($product_ref, \%populated_fields, \%other_images); + elsif ($group_id eq "images") { + if ($args_ref->{include_images_paths}) { + if (defined $product_ref->{images}) { + include_image_paths($product_ref, \%populated_fields, \%other_images); + } } } - } - else { + else { - foreach my $field (@{$group_ref->[1]}) { + foreach my $field (@{$group_ref->[1]}) { - # Prefix fields that are not primary data, but that are computed by OFF, with the "off:" prefix - my $group_prefix = ""; - if ($group_id eq "off") { - $group_prefix = "off:"; - } + # Prefix fields that are not primary data, but that are computed by OFF, with the "off:" prefix + my $group_prefix = ""; + if ($group_id eq "off") { + $group_prefix = "off:"; + } - $item_number++; - my $field_sort_key = sprintf("%08d", $group_number * 1000 + $item_number); + $item_number++; + my $field_sort_key = sprintf("%08d", $group_number * 1000 + $item_number); - if ($field =~ /_value_unit$/) { - # Column can contain value + unit, value, or unit for a specific field - $field = $`; - } + if ($field =~ /_value_unit$/) { + # Column can contain value + unit, value, or unit for a specific field + $field = $`; + } - if (defined $tags_fields{$field}) { - if ( (defined $product_ref->{$field . "_tags"}) - and (scalar @{$product_ref->{$field . "_tags"}} > 0)) - { - # Export the tags field in the main language of the product - $populated_fields{$group_prefix . $field} = $field_sort_key; - # Also possibly export the canonicalized tags - if ($export_canonicalized_tags_fields) { - $populated_fields{$group_prefix . $field . "_tags"} = $field_sort_key . "_tags"; + if (defined $tags_fields{$field}) { + if ( (defined $product_ref->{$field . "_tags"}) + and (scalar @{$product_ref->{$field . "_tags"}} > 0)) + { + # Export the tags field in the main language of the product + $populated_fields{$group_prefix . $field} = $field_sort_key; + # Also possibly export the canonicalized tags + if ($export_canonicalized_tags_fields) { + $populated_fields{$group_prefix . $field . "_tags"} = $field_sort_key . "_tags"; + } } } - } - elsif (defined $language_fields{$field}) { - if (defined $product_ref->{languages_codes}) { - foreach my $l (keys %{$product_ref->{languages_codes}}) { - if ( (defined $product_ref->{$field . "_$l"}) - and ($product_ref->{$field . "_$l"} ne "")) - { - # Add language code to sort key - $populated_fields{$group_prefix . $field . "_$l"} = $field_sort_key . "_$l"; + elsif (defined $language_fields{$field}) { + if (defined $product_ref->{languages_codes}) { + foreach my $l (keys %{$product_ref->{languages_codes}}) { + if ( (defined $product_ref->{$field . "_$l"}) + and ($product_ref->{$field . "_$l"} ne "")) + { + # Add language code to sort key + $populated_fields{$group_prefix . $field . "_$l"} = $field_sort_key . "_$l"; + } } } } - } - else { - my $key = $field; - # Special case for ecoscore_data.adjustments.origins_of_ingredients.value - # which is only present if the Eco-Score fields have been localized (done only once after) - # we check for .values (with an s) instead - if ($field eq "ecoscore_data.adjustments.origins_of_ingredients.value") { - $key = $key . "s"; - } - # Allow returning fields that are not at the root of the product structure - # e.g. ecoscore_data.agribalyse.score -> $product_ref->{ecoscore_data}{agribalyse}{score} - if (deep_exists($product_ref, split(/\./, $key))) { - $populated_fields{$group_prefix . $field} = $field_sort_key; + else { + my $key = $field; + # Special case for ecoscore_data.adjustments.origins_of_ingredients.value + # which is only present if the Eco-Score fields have been localized (done only once after) + # we check for .values (with an s) instead + if ($field eq "ecoscore_data.adjustments.origins_of_ingredients.value") { + $key = $key . "s"; + } + # Allow returning fields that are not at the root of the product structure + # e.g. ecoscore_data.agribalyse.score -> $product_ref->{ecoscore_data}{agribalyse}{score} + if (deep_exists($product_ref, split(/\./, $key))) { + $populated_fields{$group_prefix . $field} = $field_sort_key; + } } } } } - } - # Source specific fields in the sources_fields hash - if (defined $product_ref->{sources_fields}) { - foreach my $source_id (sort keys %{$product_ref->{sources_fields}}) { - foreach my $field (sort keys %{$product_ref->{sources_fields}{$source_id}}) { - $populated_fields{"sources_fields:${source_id}:$field"} - = sprintf("%08d", 10 * 1000) . "_${source_id}:$field"; + # Source specific fields in the sources_fields hash + if (defined $product_ref->{sources_fields}) { + foreach my $source_id (sort keys %{$product_ref->{sources_fields}}) { + foreach my $field (sort keys %{$product_ref->{sources_fields}{$source_id}}) { + $populated_fields{"sources_fields:${source_id}:$field"} + = sprintf("%08d", 10 * 1000) . "_${source_id}:$field"; + } } } } @@ -390,10 +420,6 @@ sub export_csv ($args_ref) { push @sorted_populated_fields, "obsolete"; } } - else { - # The fields to export are specified by the fields parameter - @sorted_populated_fields = @{$fields_ref}; - } # Extra fields such as Nova or Nutri-Score that do not originate from users or producers but are computed if (defined $extra_fields_ref) { @@ -462,177 +488,184 @@ sub export_csv ($args_ref) { $csv->print($filehandle, \@sorted_populated_fields); } - $cursor->reset(); - my $j = 0; # Row number - while (my $product_ref = $cursor->next) { + # Go through the products and products_obsolete collections again - $j++; - my @values = (); + foreach my $collection (@collections) { - my $added_images_urls = 0; - my $product_path = product_path($product_ref); + $cursors{$collection}->reset(); - my $scans_ref; + while (my $product_ref = $cursors{$collection}->next) { - # If an ecoscore_* field is requested, we will localize all the Eco-Score fields once - my $ecoscore_localized = 0; + $j++; + my @values = (); - foreach my $field (@sorted_populated_fields) { + my $added_images_urls = 0; + my $product_path = product_path($product_ref); - my $nutriment_field = 0; + my $scans_ref; - my $value; + # If an ecoscore_* field is requested, we will localize all the Eco-Score fields once + my $ecoscore_localized = 0; - # Remove the off: prefix for fields computed by OFF, as we don't have the prefix in the product structure - $field =~ s/^off://; + foreach my $field (@sorted_populated_fields) { - # Localize the Eco-Score fields that depend on the country of the request - if (($field =~ /^ecoscore/) and (not $ecoscore_localized)) { - localize_ecoscore($export_cc, $product_ref); - $ecoscore_localized = 1; - } + my $nutriment_field = 0; - # Scans must be loaded separately - if ($field =~ /^scans_(\d\d\d\d)_(.*)_(\w+)$/) { + my $value; - my ($scan_year, $scan_field, $scan_cc) = ($1, $2, $3); + # Remove the off: prefix for fields computed by OFF, as we don't have the prefix in the product structure + $field =~ s/^off://; - if (not defined $scans_ref) { - # Load the scan data - $scans_ref = retrieve_json("$data_root/products/$product_path/scans.json"); + # Localize the Eco-Score fields that depend on the country of the request + if (($field =~ /^ecoscore/) and (not $ecoscore_localized)) { + localize_ecoscore($export_cc, $product_ref); + $ecoscore_localized = 1; } - if (not defined $scans_ref) { - $scans_ref = {}; + + # Scans must be loaded separately + if ($field =~ /^scans_(\d\d\d\d)_(.*)_(\w+)$/) { + + my ($scan_year, $scan_field, $scan_cc) = ($1, $2, $3); + + if (not defined $scans_ref) { + # Load the scan data + $scans_ref = retrieve_json("$data_root/products/$product_path/scans.json"); + } + if (not defined $scans_ref) { + $scans_ref = {}; + } + if ( (defined $scans_ref->{$scan_year}) + and (defined $scans_ref->{$scan_year}{$scan_field}) + and (defined $scans_ref->{$scan_year}{$scan_field}{$scan_cc})) + { + $value = $scans_ref->{$scan_year}{$scan_field}{$scan_cc}; + } + else { + $value = ""; + } } - if ( (defined $scans_ref->{$scan_year}) - and (defined $scans_ref->{$scan_year}{$scan_field}) - and (defined $scans_ref->{$scan_year}{$scan_field}{$scan_cc})) - { - $value = $scans_ref->{$scan_year}{$scan_field}{$scan_cc}; + # Source specific fields + elsif ($field =~ /^sources_fields:([a-z0-9-]+):/) { + my $source_id = $1; + my $source_field = $'; + if ( (defined $product_ref->{sources_fields}) + and (defined $product_ref->{sources_fields}{$source_id}) + and (defined $product_ref->{sources_fields}{$source_id}{$source_field})) + { + $value = $product_ref->{sources_fields}{$source_id}{$source_field}; + } } else { - $value = ""; - } - } - # Source specific fields - elsif ($field =~ /^sources_fields:([a-z0-9-]+):/) { - my $source_id = $1; - my $source_field = $'; - if ( (defined $product_ref->{sources_fields}) - and (defined $product_ref->{sources_fields}{$source_id}) - and (defined $product_ref->{sources_fields}{$source_id}{$source_field})) - { - $value = $product_ref->{sources_fields}{$source_id}{$source_field}; - } - } - else { - foreach my $suffix ("_value", "_unit", "_prepared_value", "_prepared_unit") { - if ($field =~ /$suffix$/) { - my $nid = $`; - if (defined $product_ref->{nutriments}) { - $value = $product_ref->{nutriments}{$nid . $suffix}; + foreach my $suffix ("_value", "_unit", "_prepared_value", "_prepared_unit") { + if ($field =~ /$suffix$/) { + my $nid = $`; + if (defined $product_ref->{nutriments}) { + $value = $product_ref->{nutriments}{$nid . $suffix}; + } + $nutriment_field = 1; + last; } - $nutriment_field = 1; - last; } - } - if (not $nutriment_field) { + if (not $nutriment_field) { - # If we export image fields, we first need to generate the paths to images + # If we export image fields, we first need to generate the paths to images - if (($field =~ /^image_(.*)_(url|json)/) and (not $added_images_urls)) { - add_images_urls_to_product($product_ref, $lc); - $added_images_urls = 1; - } + if (($field =~ /^image_(.*)_(url|json)/) and (not $added_images_urls)) { + add_images_urls_to_product($product_ref, $lc); + $added_images_urls = 1; + } - if ($field =~ /^image_(.*)_file/) { - # File path for the image on the server, used for exporting from producers platform to public database + if ($field =~ /^image_(.*)_file/) { + # File path for the image on the server, used for exporting from producers platform to public database - my $imagefield = $1; + my $imagefield = $1; - if ((defined $product_ref->{images}) and (defined $product_ref->{images}{$imagefield})) { - $value - = "$www_root/images/products/" - . $product_path . "/" - . $product_ref->{images}{$imagefield}{imgid} . ".jpg"; - } - elsif (defined $other_images{$product_ref->{code} . "." . $imagefield}) { - $value - = "$www_root/images/products/" - . $product_path . "/" - . $other_images{$product_ref->{code} . "." . $imagefield}{imgid} . ".jpg"; + if ((defined $product_ref->{images}) and (defined $product_ref->{images}{$imagefield})) { + $value + = "$www_root/images/products/" + . $product_path . "/" + . $product_ref->{images}{$imagefield}{imgid} . ".jpg"; + } + elsif (defined $other_images{$product_ref->{code} . "." . $imagefield}) { + $value + = "$www_root/images/products/" + . $product_path . "/" + . $other_images{$product_ref->{code} . "." . $imagefield}{imgid} . ".jpg"; + } } - } - elsif ($field =~ /^image_(.*)_(x1|y1|x2|y2|angle|normalize|white_magic|coordinates_image_size)/) { - # Coordinates for image cropping - my $imagefield = $1; - my $coord = $2; + elsif ($field =~ /^image_(.*)_(x1|y1|x2|y2|angle|normalize|white_magic|coordinates_image_size)/) + { + # Coordinates for image cropping + my $imagefield = $1; + my $coord = $2; - if ((defined $product_ref->{images}) and (defined $product_ref->{images}{$imagefield})) { - $value = $product_ref->{images}{$imagefield}{$coord}; + if ((defined $product_ref->{images}) and (defined $product_ref->{images}{$imagefield})) { + $value = $product_ref->{images}{$imagefield}{$coord}; + } } - } - elsif ($field =~ /^image_(ingredients|nutrition|packaging)_json$/) { - if (defined $product_ref->{"image_$1_url"}) { - $value = $product_ref->{"image_$1_url"}; - $value =~ s/\.(\d+)\.jpg/.json/; + elsif ($field =~ /^image_(ingredients|nutrition|packaging)_json$/) { + if (defined $product_ref->{"image_$1_url"}) { + $value = $product_ref->{"image_$1_url"}; + $value =~ s/\.(\d+)\.jpg/.json/; + } } - } - elsif ($field =~ /^image_(.*)_full_url$/) { - if (defined $product_ref->{"image_$1_url"}) { - $value = $product_ref->{"image_$1_url"}; - $value =~ s/\.(\d+)\.jpg/.full.jpg/; + elsif ($field =~ /^image_(.*)_full_url$/) { + if (defined $product_ref->{"image_$1_url"}) { + $value = $product_ref->{"image_$1_url"}; + $value =~ s/\.(\d+)\.jpg/.full.jpg/; + } } - } - elsif (($field =~ /_tags$/) and (defined $product_ref->{$field})) { - $value = join(",", @{$product_ref->{$field}}); - } - elsif ((defined $taxonomy_fields{$field}) and (defined $product_ref->{$field . "_hierarchy"})) { - # we do not know the language of the current value of $product_ref->{$field} - # so regenerate it in the main language of the product - # Note: some fields like nova_groups and food_groups do not have a _hierarchy subfield, - # but they are not entered directly, but computed from other fields, so we can take their values as is. - $value = list_taxonomy_tags_in_language($product_ref->{lc}, $field, - $product_ref->{$field . "_hierarchy"}); - } - # packagings field of the form packaging_2_number_of_units - elsif ($field =~ /^packaging_(\d+)_(.*)$/) { - my $index = $1 - 1; - my $property = $2; - $value = deep_get($product_ref, ("packagings", $index, $property)); - } - # Allow returning fields that are not at the root of the product structure - # e.g. ecoscore_data.agribalyse.score -> $product_ref->{ecoscore_data}{agribalyse}{score} - elsif ($field =~ /\./) { - $value = deep_get($product_ref, split(/\./, $field)); - } - # Fields like "obsolete" : output 1 for true values or 0 - elsif ($field eq "obsolete") { - if ((defined $product_ref->{$field}) and ($product_ref->{$field})) { - $value = 1; + elsif (($field =~ /_tags$/) and (defined $product_ref->{$field})) { + $value = join(",", @{$product_ref->{$field}}); + } + elsif ((defined $taxonomy_fields{$field}) and (defined $product_ref->{$field . "_hierarchy"})) { + # we do not know the language of the current value of $product_ref->{$field} + # so regenerate it in the main language of the product + # Note: some fields like nova_groups and food_groups do not have a _hierarchy subfield, + # but they are not entered directly, but computed from other fields, so we can take their values as is. + $value = list_taxonomy_tags_in_language($product_ref->{lc}, $field, + $product_ref->{$field . "_hierarchy"}); + } + # packagings field of the form packaging_2_number_of_units + elsif ($field =~ /^packaging_(\d+)_(.*)$/) { + my $index = $1 - 1; + my $property = $2; + $value = deep_get($product_ref, ("packagings", $index, $property)); + } + # Allow returning fields that are not at the root of the product structure + # e.g. ecoscore_data.agribalyse.score -> $product_ref->{ecoscore_data}{agribalyse}{score} + elsif ($field =~ /\./) { + $value = deep_get($product_ref, split(/\./, $field)); + } + # Fields like "obsolete" : output 1 for true values or 0 + elsif ($field eq "obsolete") { + if ((defined $product_ref->{$field}) and ($product_ref->{$field})) { + $value = 1; + } + else { + $value = 0; + } } else { - $value = 0; + $value = $product_ref->{$field}; } } - else { - $value = $product_ref->{$field}; - } } + + push @values, $value; } - push @values, $value; - } + if ($format eq "xlsx") { + $worksheet->write_row($j, 0, \@values); + } + else { + $csv->print($filehandle, \@values); + } - if ($format eq "xlsx") { - $worksheet->write_row($j, 0, \@values); - } - else { - $csv->print($filehandle, \@values); } } diff --git a/lib/ProductOpener/Producers.pm b/lib/ProductOpener/Producers.pm index 71defa573aa2d..6b335919aaa78 100644 --- a/lib/ProductOpener/Producers.pm +++ b/lib/ProductOpener/Producers.pm @@ -1804,6 +1804,7 @@ sub export_and_import_to_public_database ($args_ref) { $args_ref->{csv_file} = $exported_file; $args_ref->{export_id} = $export_id; $args_ref->{comment} = "Import from producers platform"; + $args_ref->{include_obsolete_products} = 1; $args_ref->{include_images_paths} = 1; # Export file paths to images $args_ref->{exported_t} = $started_t; diff --git a/po/common/common.pot b/po/common/common.pot index 76fa492cb8672..1535960cfe7a4 100644 --- a/po/common/common.pot +++ b/po/common/common.pot @@ -4429,11 +4429,6 @@ msgctxt "edit_link_in_search" msgid "Add an edit link in search results" msgstr "Add an edit link in search results" -# leave the %d, it will be replaced by a number -msgctxt "n_products_will_be_exported" -msgid "%d products will be exported." -msgstr "%d products will be exported." - msgctxt "ciqual_food_name" msgid "CIQUAL food name" msgstr "CIQUAL food name" @@ -4758,10 +4753,6 @@ msgctxt "export_product_page" msgid "Export product to public database" msgstr "Export product to public database" -msgctxt "one_product_will_be_exported" -msgid "1 product will be exported." -msgstr "1 product will be exported." - msgctxt "no_products_to_export" msgid "No products to export." msgstr "No products to export." @@ -5260,6 +5251,10 @@ msgctxt "number_of_products_with_changes_since_last_export" msgid "Number of products with changes since last export" msgstr "Number of products with changes since last export" +msgctxt "number_of_products_withdrawn_from_the_market_since_last_export" +msgid "Number of products withdrawn from the market since last export" +msgstr "Number of products withdrawn from the market since last export" + msgctxt "only_export_products_with_changes" msgid "Only export products with changes" msgstr "Only export products with changes" diff --git a/po/common/en.po b/po/common/en.po index 2525c2e9d0a03..060e2dcbe54d9 100644 --- a/po/common/en.po +++ b/po/common/en.po @@ -4434,11 +4434,6 @@ msgctxt "brand_owner_example" msgid "The Coca Cola Company" msgstr "The Coca Cola Company" -# leave the %d, it will be replaced by a number -msgctxt "n_products_will_be_exported" -msgid "%d products will be exported." -msgstr "%d products will be exported." - msgctxt "categories_properties" msgid "Categories properties" msgstr "Categories properties" @@ -4762,10 +4757,6 @@ msgctxt "export_product_page" msgid "Export product to public database" msgstr "Export product to public database" -msgctxt "one_product_will_be_exported" -msgid "1 product will be exported." -msgstr "1 product will be exported." - msgctxt "no_products_to_export" msgid "No products to export." msgstr "No products to export." @@ -5293,6 +5284,10 @@ msgctxt "number_of_products_with_changes_since_last_export" msgid "Number of products with changes since last export" msgstr "Number of products with changes since last export" +msgctxt "number_of_products_withdrawn_from_the_market_since_last_export" +msgid "Number of products withdrawn from the market since last export" +msgstr "Number of products withdrawn from the market since last export" + msgctxt "only_export_products_with_changes" msgid "Only export products with changes" msgstr "Only export products with changes" diff --git a/templates/web/common/includes/producers_platform_front_page.tt.html b/templates/web/common/includes/producers_platform_front_page.tt.html index 80d898fd68746..6917df94aff25 100644 --- a/templates/web/common/includes/producers_platform_front_page.tt.html +++ b/templates/web/common/includes/producers_platform_front_page.tt.html @@ -30,19 +30,31 @@

[% lang("your_products") %]

- [% IF products_to_be_exported.defined %] -

- [% lang("some_product_updates_have_not_been_published_on_the_public_database") %] -
- [% products_to_be_exported %] -

+ [% IF count_to_be_exported + count_obsolete_to_be_exported > 0 %] +

[% lang("some_product_updates_have_not_been_published_on_the_public_database") %]

+ +
publish [% lang("export_product_data_photos") %]
- [% ELSE %]

[% lang("no_products_to_export") %]

[% END %] diff --git a/templates/web/pages/export_products/export_products.tt.html b/templates/web/pages/export_products/export_products.tt.html index c7fa9a82da0dc..a59a0951cb41c 100644 --- a/templates/web/pages/export_products/export_products.tt.html +++ b/templates/web/pages/export_products/export_products.tt.html @@ -16,41 +16,40 @@ [% END %] -

[% n_products_will_be_exported %]

-

[% lang('number_of_products_with_changes_since_last_export') %][% sep %]: [% count_to_be_exported %]

- - [% IF count > 0 %] - [% IF allow_submit %] - - - - - - - - [% IF admin %] - - - - [% END %] - [% END %] - - + + + [% IF allow_submit %] + + + + + + + + [% IF admin %] + + + [% END %] [% END %] - + + + \ No newline at end of file