From 41b5ad81c8c05ba20295197da10d69082d26706f Mon Sep 17 00:00:00 2001 From: Alex Garel Date: Thu, 23 Nov 2023 14:03:56 +0100 Subject: [PATCH] chore: Migration of Open Food Facts from off1 (bare metal) to off2 (proxmox) (#8827) - Migration of Open Food Facts (site and pro platform) from off1 (bare metal) to off2 (proxmox) - Modifications linked to moving off and off-pro to off2 server. - This includes a lot of path modifications: - some directories where removed from the repository and are created dynamically - we try to differentiate folders containing code (only this is in git), data, cache data and dist files - we control this by using a fixed set of base path (see Paths.pm) - Most of server configurations are now in the git repository - Import scripts where reworked See also: https://github.com/openfoodfacts/openfoodfacts-infrastructure/pull/243 Part of: - https://github.com/openfoodfacts/openfoodfacts-infrastructure/issues/182 --- .github/workflows/generate-doc.yml | 7 +- .github/workflows/pull_request.yml | 7 +- .github/workflows/release-please.yml | 1 + .gitignore | 42 +- Dockerfile | 33 +- Makefile | 25 +- build-cache/taxonomies/README.md | 7 - cgi/change_password.pl | 5 +- cgi/display.pl | 8 +- cgi/import_file_job_status.pl | 3 +- cgi/import_file_process.pl | 17 +- cgi/import_file_select_format.pl | 5 +- cgi/import_file_upload.pl | 10 +- cgi/login.pl | 3 +- cgi/product_image.pl | 3 +- cgi/product_image_rotate.pl | 5 +- cgi/product_image_upload.pl | 18 +- cgi/product_jqm_multilingual.pl | 5 +- cgi/product_multilingual.pl | 5 +- cgi/remove_products.pl | 23 +- cgi/reset_password.pl | 13 +- cgi/search.pl | 5 +- cgi/sucres_check.pl | 49 - cgi/sucres_random.pl | 53 - cgi/sugar_check.pl | 11 +- cgi/sugar_random.pl | 13 +- cgi/user.pl | 5 +- conf/apache-2.4/off-mpm_prefork.conf | 17 + conf/apache-2.4/off-ports.conf | 7 + conf/apache-2.4/off-pro-mpm_prefork.conf | 16 + conf/apache-2.4/off-pro-ports.conf | 7 + conf/apache-2.4/sites-available/off.conf | 4 +- conf/apache-2.4/sites-available/opf.conf | 2 +- conf/apache-2.4/sites-available/opff.conf | 3 +- conf/logrotate/apache2 | 25 + conf/nginx.conf | 27 +- conf/nginx/conf.d/log_format_realip.conf | 6 + .../sites-available/cestemballepresdechezvous | 104 - conf/nginx/sites-available/combiendesucres | 105 - conf/nginx/sites-available/howmuchsugar | 81 +- conf/nginx/sites-available/madenearme | 75 +- conf/nginx/sites-available/madenearme-uk | 104 - conf/nginx/sites-available/off | 178 +- conf/nginx/sites-available/off-pro | 200 +- .../{ => snippets}/expires-no-json-xml.conf | 0 conf/nginx/snippets/ssl-params-opff.conf | 22 - conf/nginx/snippets/ssl-params.conf | 17 - .../snippets/ssl.cestemballepresdechezvous.fr | 2 - conf/nginx/snippets/ssl.madenear.me | 2 - conf/nginx/snippets/ssl.madenear.me.uk | 2 - conf/nginx/snippets/ssl.openbeautyfacts.org | 4 - .../snippets/ssl.openbeautyfacts.org.2017 | 3 - conf/nginx/snippets/ssl.openfoodfacts.org | 8 - .../nginx/snippets/ssl.openfoodfacts.org.2016 | 3 - conf/nginx/snippets/ssl.openpetfoodfacts.org | 4 - conf/nginx/snippets/ssl.openproductsfacts.org | 4 - conf/off-log.conf | 19 + conf/off-minion_log.conf | 10 + conf/off-pro-log.conf | 10 + conf/off-pro-minion_log.conf | 10 + conf/systemd/apache2.service.d/override.conf | 5 + conf/systemd/cloud_vision_ocr@.service | 17 + conf/systemd/email-failures@.service | 9 + conf/systemd/gen_feeds@.service | 13 + conf/systemd/gen_feeds@.timer | 11 + conf/systemd/gen_feeds_daily@.service | 13 + conf/systemd/gen_feeds_daily@.timer | 11 + conf/systemd/madenearme_gen.service | 12 + conf/systemd/madenearme_gen.timer | 11 + conf/systemd/minion@.service | 18 + conf/systemd/nginx.service.d/override.conf | 2 + conf/systemd/producers_import.service | 13 + conf/systemd/producers_import.timer | 11 + .../well-known/off-apple-app-site-association | 10 + ...le-developer-merchantid-domain-association | 1 + cpanfile | 3 + cron/import_carrefour.sh | 26 - debug/.empty | 0 docker-compose.yml | 14 +- docker/dev.yml | 9 +- docker/docker-entrypoint.sh | 41 +- docker/prod.yml | 5 +- .../doc/perl => docs/assets}/simple.min.css | 0 docs/dev/explain-taxonomy-build-cache.md | 14 +- gulpfile.ts | 2 +- html/{data => }/data-fields.md | 0 html/{data => }/data-fields.txt | 0 html/files/doc/perl/a.txt | 1 - html/files/presentations/index.txt | 1 - html/files/robots.txt | 15 - html/images/products/.empty | 0 html/resources/README.md | 8 + .../files/app/ingredients-analysis.json | 0 .../files/app/tagline/tagline-off-ios.json | 0 .../files/knowledge_panel_test.json | 0 html/{ => resources}/files/tagline-obf.json | 0 .../files/tagline-off-android-v2.json | 0 .../files/tagline-off-ios-v2.json | 0 html/{ => resources}/files/tagline-off.json | 0 html/{ => resources}/files/tagline-opf.json | 0 html/{ => resources}/files/tagline-opff.json | 0 html/{ => resources}/files/tagline.txt | 0 lib/ProductOpener/APIProductRead.pm | 3 +- lib/ProductOpener/APITest.pm | 2 +- lib/ProductOpener/Attributes.pm | 68 +- lib/ProductOpener/Config2_docker.pm | 2 + lib/ProductOpener/Config2_sample.pm | 4 + lib/ProductOpener/Config_off.pm | 2 + lib/ProductOpener/Display.pm | 59 +- lib/ProductOpener/Export.pm | 34 +- lib/ProductOpener/Food.pm | 6 +- lib/ProductOpener/Images.pm | 98 +- lib/ProductOpener/Import.pm | 11 +- lib/ProductOpener/ImportConvert.pm | 3 +- lib/ProductOpener/Index.pm | 9 +- lib/ProductOpener/KnowledgePanels.pm | 10 +- lib/ProductOpener/Lang.pm | 9 +- lib/ProductOpener/Mail.pm | 7 +- lib/ProductOpener/MainCountries.pm | 5 +- lib/ProductOpener/Missions.pm | 19 +- lib/ProductOpener/Orgs.pm | 22 +- lib/ProductOpener/Packaging.pm | 5 +- lib/ProductOpener/PackagingStats.pm | 39 +- lib/ProductOpener/Paths.pm | 346 ++ lib/ProductOpener/Producers.pm | 34 +- lib/ProductOpener/Products.pm | 70 +- lib/ProductOpener/Routing.pm | 3 +- lib/ProductOpener/Store.pm | 3 +- lib/ProductOpener/Tags.pm | 41 +- lib/ProductOpener/TaxonomySuggestions.pm | 6 +- lib/ProductOpener/Test.pm | 32 +- lib/ProductOpener/URL.pm | 3 +- lib/ProductOpener/Users.pm | 39 +- lib/startup_apache2.pl | 13 +- logs/apache2/.empty | 0 logs/nginx/.empty | 0 producers.html | 381 -- scripts/agena3000/run_agena3000_import.sh | 31 - scripts/build_lang.pl | 7 +- scripts/compute_missions_for_user.pl | 5 +- scripts/convert_carrefour_data_off1.sh | 2 - scripts/convert_gs1_json_to_off_csv.pl | 1 + ...ries_nutriments_per_country_for_testing.pl | 6 +- scripts/deploy/verify-symlinks.sh | 194 + scripts/equadis-import/run_equadis_import.sh | 26 - scripts/export_battle_food.pl | 3 +- scripts/export_database.pl | 7 +- ...ducers_platform_data_to_public_database.sh | 70 +- scripts/export_products_data_and_images.pl | 9 +- scripts/export_tags_hierarchies.pl | 7 +- scripts/extract_images.pl | 3 +- scripts/extract_ingredients_test_set.pl | 3 +- .../extract_nutrition_images_and_crop_data.pl | 3 +- scripts/extract_nutrition_test_set.pl | 3 +- scripts/fix_non_normalized_codes.pl | 9 +- scripts/gen_feeds_daily_off.sh | 27 +- scripts/gen_pro_users_emails_list.pl | 5 +- scripts/gen_sucres.pl | 12 +- scripts/gen_sugar.pl | 12 +- scripts/gen_top_tags_per_country.pl | 238 +- scripts/gen_users_emails.pl | 5 +- scripts/gen_users_emails_list.pl | 5 +- scripts/gen_users_lists.pl | 7 +- scripts/gen_users_names.pl | 5 +- scripts/generate_madenearme_page.pl | 4 +- scripts/generate_madenearme_pages.sh | 9 + scripts/generate_perl_html_doc_from_pod.pl | 24 +- scripts/import_carrefour_pro_off1.sh | 4 - scripts/import_csv_file.pl | 3 +- .../imports/agena3000/run_agena3000_import.sh | 62 + .../carrefour/Nomenclature_OpenFoodFacts.csv | 5490 +++++++++++++++++ .../carrefour}/convert_carrefour_data.pl | 0 .../imports/carrefour/run_carrefour_import.sh | 76 + scripts/imports/equadis/run_equadis_import.sh | 51 + scripts/imports/imports_utils.sh | 39 + scripts/imports/producers_imports.sh | 11 + scripts/make_user_moderator.pl | 5 +- scripts/minion_producers.pl | 11 +- .../convert_gs1_xml_to_json_in_dir.js | 3 + scripts/obsolete/credit_product_to_creator.pl | 3 +- scripts/obsolete/fix_code_stored_as_number.pl | 3 +- .../obsolete/fix_countries_removed_by_yuka.pl | 3 +- scripts/obsolete/fix_leading_zeros.pl | 3 +- scripts/obsolete/fix_product.pl | 3 +- scripts/obsolete/fix_product2.pl | 3 +- .../run_codeonline_import.sh | 0 .../split_gs1_codeonline_json.pl | 0 .../stats_gs1_codeonline_json.pl | 0 .../fleary_michon/ExportOpenFoodFacts.php | 198 + .../fleary_michon/configOpenFoodFacts.php | 9 + .../delete_broken_image_files.pl | 28 + .../fleary_michon}/import_fleurymichon.pl | 0 .../fleary_michon}/import_fleurymichon.sh | 7 + .../obsolete/{ => imports}/import_barilla.sh | 0 .../{ => imports}/import_baskalia_pechalou.sh | 0 .../obsolete/{ => imports}/import_casino.sh | 0 .../obsolete/{ => imports}/import_foodrepo.sh | 0 .../obsolete/{ => imports}/import_harrys.sh | 0 scripts/obsolete/{ => imports}/import_iglo.sh | 0 scripts/obsolete/imports/import_ldc.sh | 3 + .../obsolete/{ => imports}/import_mxbot.sh | 0 .../obsolete/imports/import_ocr_nutriscore.sh | 3 + .../{ => imports}/import_openfood_ch.pl | 3 +- .../import_openfood_ch_name_translations.pl | 3 +- .../{ => imports}/import_saintelucie.sh | 0 .../obsolete/{ => imports}/import_sodebo.pl | 3 +- .../imports/import_stores_be_delhaize.sh | 2 + .../obsolete/{ => imports}/import_us_ndb.pl | 3 +- .../migrations}/copy_text_files.pl | 0 .../migrations}/delete_old_cropped_images.pl | 11 +- .../migrations}/delete_spam_users.pl | 11 +- .../remove_deleted_products_from_db.pl | 5 +- scripts/obsolete/test_additifs.pl | 5 +- .../update_all_products_all_fields.pl | 3 +- .../update_all_products_categories.pl | 3 +- scripts/obsolete/update_all_products_codes.pl | 3 +- .../obsolete/update_all_products_countries.pl | 3 +- .../update_all_products_countries_add.pl | 5 +- .../update_all_products_countries_fix.pl | 3 +- .../obsolete/update_all_products_creator.pl | 5 +- .../obsolete/update_all_products_emb_codes.pl | 3 +- .../obsolete/update_all_products_energy.pl | 3 +- ...update_all_products_from_dir_in_mongodb.pl | 5 +- ..._products_from_dir_remove_dotted_fields.pl | 7 +- .../obsolete/update_all_products_history.pl | 7 +- .../update_all_products_history_from_dir.pl | 9 +- .../update_all_products_history_fromdir.pl | 15 +- .../update_all_products_in_mongodb.pl | 3 +- .../update_all_products_ingredients.pl | 3 +- ...update_all_products_ingredients_classes.pl | 5 +- .../obsolete/update_all_products_labels.pl | 3 +- .../obsolete/update_all_products_lang_lc.pl | 3 +- .../update_all_products_language_fields.pl | 7 +- .../obsolete/update_all_products_languages.pl | 3 +- .../update_all_products_nutriments_fields.pl | 3 +- .../update_all_products_nutriments_typo.pl | 3 +- .../update_all_products_nutrition_score.pl | 3 +- .../update_all_products_packager_codes.pl | 3 +- ...l_products_periods_from_expiration_date.pl | 3 +- .../obsolete/update_all_products_sortkey.pl | 3 +- .../update_all_products_unknown_nutriments.pl | 3 +- .../update_all_products_zero_scans.pl | 3 +- scripts/obsolete/update_users.pl | 7 +- scripts/obsolete/upload_photos.pl | 6 +- scripts/obsolete/usda_ndb_gen_dl_scripts.pl | 45 + .../remove_all_private_products_for_owner.pl | 23 +- scripts/remove_products_without_code.pl | 3 +- scripts/reset_password_for_user.pl | 5 +- scripts/revert_changes_from_user.pl | 32 +- scripts/run_cloud_vision_ocr.pl | 5 +- scripts/run_ocr.py | 2 +- scripts/scanbot.pl | 19 +- .../remove_broken_entry_with_empty_email.pl | 5 +- scripts/tests/test_imports_utils.sh | 41 + scripts/update_all_products.pl | 27 +- ...update_all_products_from_dir_in_mongodb.pl | 9 +- scripts/update_recent_changes.pl | 3 +- scripts/update_top_translators.pl | 3 +- stop_words.txt | 4 + .../environment/ecoscore/ecoscore.tt.json | 2 +- .../ecoscore/ecoscore_not_applicable.tt.json | 2 +- .../ecoscore/ecoscore_unknown.tt.json | 2 +- .../environment/ecoscore/total.tt.json | 2 +- .../health/ingredients/nova.tt.json | 4 +- .../health/nutriscore/nutriscore.tt.json | 2 +- .../pages/product/includes/nutriscore.tt.html | 2 +- .../convert_and_import_excel_file.t | 25 +- tests/integration/create_user.t | 7 +- .../get-attribute-groups-fr.json | 56 +- .../get-attribute-groups.json | 56 +- .../get-fields-all-knowledge-panels.json | 8 +- ...attribute-groups-all-knowledge-panels.json | 120 +- .../get-knowledge-panels-fr.json | 8 +- .../get-knowledge-panels.json | 8 +- .../get-attribute-groups-fr.json | 56 +- .../get-attribute-groups.json | 56 +- .../get-fields-all-knowledge-panels.json | 8 +- ...attribute-groups-all-knowledge-panels.json | 120 +- .../get-knowledge-panels-fr.json | 8 +- .../get-knowledge-panels.json | 8 +- ...ted-attribute-groups-knowledge-panels.json | 62 +- .../data-quality.json | 6 +- .../no-data-quality.json | 6 +- tests/integration/export.t | 4 +- .../attributes/en-attributes.json | 56 +- .../en-ecoscore-score-at-20-threshold.json | 56 +- .../attributes/en-maybe-vegan.json | 56 +- .../attributes/en-no-ingredients.json | 56 +- .../attributes/en-nova-groups-markers.json | 56 +- .../attributes/en-nutriscore.json | 56 +- .../attributes/en-unknown-ingredients.json | 56 +- .../attributes/fr-palm-kernel-fat.json | 56 +- .../attributes/fr-palm-oil-free.json | 56 +- .../attributes/fr-palm-oil.json | 56 +- .../attributes/fr-vegetable-oils.json | 56 +- tests/unit/import_convert_carrefour_france.t | 2 +- tests/unit/paths.t | 68 + 297 files changed, 8872 insertions(+), 2771 deletions(-) delete mode 100644 build-cache/taxonomies/README.md delete mode 100755 cgi/sucres_check.pl delete mode 100755 cgi/sucres_random.pl create mode 100644 conf/apache-2.4/off-mpm_prefork.conf create mode 100644 conf/apache-2.4/off-ports.conf create mode 100644 conf/apache-2.4/off-pro-mpm_prefork.conf create mode 100644 conf/apache-2.4/off-pro-ports.conf create mode 100644 conf/logrotate/apache2 create mode 100644 conf/nginx/conf.d/log_format_realip.conf delete mode 100644 conf/nginx/sites-available/cestemballepresdechezvous delete mode 100644 conf/nginx/sites-available/combiendesucres delete mode 100644 conf/nginx/sites-available/madenearme-uk rename conf/nginx/{ => snippets}/expires-no-json-xml.conf (100%) delete mode 100644 conf/nginx/snippets/ssl-params-opff.conf delete mode 100644 conf/nginx/snippets/ssl-params.conf delete mode 100644 conf/nginx/snippets/ssl.cestemballepresdechezvous.fr delete mode 100644 conf/nginx/snippets/ssl.madenear.me delete mode 100644 conf/nginx/snippets/ssl.madenear.me.uk delete mode 100644 conf/nginx/snippets/ssl.openbeautyfacts.org delete mode 100644 conf/nginx/snippets/ssl.openbeautyfacts.org.2017 delete mode 100644 conf/nginx/snippets/ssl.openfoodfacts.org delete mode 100644 conf/nginx/snippets/ssl.openfoodfacts.org.2016 delete mode 100644 conf/nginx/snippets/ssl.openpetfoodfacts.org delete mode 100644 conf/nginx/snippets/ssl.openproductsfacts.org create mode 100644 conf/off-log.conf create mode 100644 conf/off-minion_log.conf create mode 100644 conf/off-pro-log.conf create mode 100644 conf/off-pro-minion_log.conf create mode 100644 conf/systemd/apache2.service.d/override.conf create mode 100644 conf/systemd/cloud_vision_ocr@.service create mode 100644 conf/systemd/email-failures@.service create mode 100644 conf/systemd/gen_feeds@.service create mode 100644 conf/systemd/gen_feeds@.timer create mode 100644 conf/systemd/gen_feeds_daily@.service create mode 100644 conf/systemd/gen_feeds_daily@.timer create mode 100644 conf/systemd/madenearme_gen.service create mode 100644 conf/systemd/madenearme_gen.timer create mode 100644 conf/systemd/minion@.service create mode 100644 conf/systemd/nginx.service.d/override.conf create mode 100644 conf/systemd/producers_import.service create mode 100644 conf/systemd/producers_import.timer create mode 100644 conf/well-known/off-apple-app-site-association create mode 100644 conf/well-known/off-apple-developer-merchantid-domain-association delete mode 100755 cron/import_carrefour.sh delete mode 100644 debug/.empty rename {html/files/doc/perl => docs/assets}/simple.min.css (100%) rename html/{data => }/data-fields.md (100%) rename html/{data => }/data-fields.txt (100%) delete mode 100644 html/files/doc/perl/a.txt delete mode 100644 html/files/presentations/index.txt delete mode 100644 html/files/robots.txt delete mode 100644 html/images/products/.empty create mode 100644 html/resources/README.md rename html/{ => resources}/files/app/ingredients-analysis.json (100%) rename html/{ => resources}/files/app/tagline/tagline-off-ios.json (100%) rename html/{ => resources}/files/knowledge_panel_test.json (100%) rename html/{ => resources}/files/tagline-obf.json (100%) rename html/{ => resources}/files/tagline-off-android-v2.json (100%) rename html/{ => resources}/files/tagline-off-ios-v2.json (100%) rename html/{ => resources}/files/tagline-off.json (100%) rename html/{ => resources}/files/tagline-opf.json (100%) rename html/{ => resources}/files/tagline-opff.json (100%) rename html/{ => resources}/files/tagline.txt (100%) create mode 100644 lib/ProductOpener/Paths.pm delete mode 100644 logs/apache2/.empty delete mode 100644 logs/nginx/.empty delete mode 100644 producers.html delete mode 100755 scripts/agena3000/run_agena3000_import.sh delete mode 100755 scripts/convert_carrefour_data_off1.sh create mode 100644 scripts/deploy/verify-symlinks.sh delete mode 100755 scripts/equadis-import/run_equadis_import.sh create mode 100644 scripts/generate_madenearme_pages.sh delete mode 100755 scripts/import_carrefour_pro_off1.sh create mode 100755 scripts/imports/agena3000/run_agena3000_import.sh create mode 100644 scripts/imports/carrefour/Nomenclature_OpenFoodFacts.csv rename scripts/{ => imports/carrefour}/convert_carrefour_data.pl (100%) create mode 100755 scripts/imports/carrefour/run_carrefour_import.sh create mode 100755 scripts/imports/equadis/run_equadis_import.sh create mode 100644 scripts/imports/imports_utils.sh create mode 100644 scripts/imports/producers_imports.sh rename scripts/{ => obsolete}/convert_gs1_xml_to_json_in_dir.js (88%) rename scripts/{ => obsolete/imports}/codeonline-import/run_codeonline_import.sh (100%) rename scripts/{ => obsolete/imports}/codeonline-import/split_gs1_codeonline_json.pl (100%) rename scripts/{ => obsolete/imports}/codeonline-import/stats_gs1_codeonline_json.pl (100%) create mode 100644 scripts/obsolete/imports/fleary_michon/ExportOpenFoodFacts.php create mode 100644 scripts/obsolete/imports/fleary_michon/configOpenFoodFacts.php create mode 100755 scripts/obsolete/imports/fleary_michon/delete_broken_image_files.pl rename scripts/{ => obsolete/imports/fleary_michon}/import_fleurymichon.pl (100%) rename {cron => scripts/obsolete/imports/fleary_michon}/import_fleurymichon.sh (73%) rename scripts/obsolete/{ => imports}/import_barilla.sh (100%) rename scripts/obsolete/{ => imports}/import_baskalia_pechalou.sh (100%) rename scripts/obsolete/{ => imports}/import_casino.sh (100%) rename scripts/obsolete/{ => imports}/import_foodrepo.sh (100%) rename scripts/obsolete/{ => imports}/import_harrys.sh (100%) rename scripts/obsolete/{ => imports}/import_iglo.sh (100%) create mode 100755 scripts/obsolete/imports/import_ldc.sh rename scripts/obsolete/{ => imports}/import_mxbot.sh (100%) create mode 100755 scripts/obsolete/imports/import_ocr_nutriscore.sh rename scripts/obsolete/{ => imports}/import_openfood_ch.pl (99%) rename scripts/obsolete/{ => imports}/import_openfood_ch_name_translations.pl (99%) rename scripts/obsolete/{ => imports}/import_saintelucie.sh (100%) rename scripts/obsolete/{ => imports}/import_sodebo.pl (99%) create mode 100755 scripts/obsolete/imports/import_stores_be_delhaize.sh rename scripts/obsolete/{ => imports}/import_us_ndb.pl (99%) rename scripts/{ => obsolete/migrations}/copy_text_files.pl (100%) rename scripts/{ => obsolete/migrations}/delete_old_cropped_images.pl (91%) rename scripts/{ => obsolete/migrations}/delete_spam_users.pl (86%) create mode 100755 scripts/obsolete/usda_ndb_gen_dl_scripts.pl create mode 100755 scripts/tests/test_imports_utils.sh create mode 100644 tests/unit/paths.t diff --git a/.github/workflows/generate-doc.yml b/.github/workflows/generate-doc.yml index 156aff4f4c147..847f6ec20dffb 100644 --- a/.github/workflows/generate-doc.yml +++ b/.github/workflows/generate-doc.yml @@ -7,7 +7,6 @@ on: - "docs/**" - ".github/workflows/generate-doc.yml" - "mkdocs.yml" - - "html/files/doc/perl/**" push: # on merge to main, build and publish branches: [ "main" ] @@ -38,10 +37,10 @@ jobs: - name: Run generate_perl_html_doc_from_pod.pl run: | - perl -CS -I lib scripts/generate_perl_html_doc_from_pod.pl && \ - # and copy to target directory rm -rf gh_pages/dev/ref-perl-pod && \ - mv html/files/doc/perl gh_pages/dev/ref-perl-pod + mkdir gh_pages/dev/ref-perl-pod && \ + cp docs/assets/simple.min.css gh_pages/dev/ref-perl-pod && \ + perl -CS -I lib scripts/generate_perl_html_doc_from_pod.pl gh_pages/dev/ref-perl-pod # DISABLED: in favor of rapidoc # generating OpenAPI documentation with redocly diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 58a3fa8eaca2f..fd6538b367d22 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -134,11 +134,16 @@ jobs: uses: ishworkh/docker-image-artifact-download@v1 with: image: "openfoodfacts-server/backend:dev" + - name: set right UID and GID in .envrc + run: | + rm -f .envrc + echo "export USER_UID=$(id -u)" >> .envrc + echo "export USER_GID=$(id -g)" >> .envrc - name: Test make dev run: | make dev make status - name: Test all is running - run: make livecheck + run: make livecheck || ( tail -n 300 logs/apache2/*error*log; docker-compose logs; false ) - name: test clean run: make hdown diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml index 8dbbdf4471073..bd76440344913 100644 --- a/.github/workflows/release-please.yml +++ b/.github/workflows/release-please.yml @@ -70,6 +70,7 @@ jobs: id=$(docker create $image_name) docker cp -a $id:/opt/product-opener/html/css/dist/ /tmp/frontend-dist/css/ docker cp -a $id:/opt/product-opener/html/images/icons/dist/ /tmp/frontend-dist/icons/ + docker cp -a $id:/opt/product-opener/html/images/attributes/dist/ /tmp/frontend-dist/attributes/ docker cp -a $id:/opt/product-opener/html/js/dist/ /tmp/frontend-dist/js/ docker rm -v $id # make a tar diff --git a/.gitignore b/.gitignore index a95a54f10eb21..e9227f0b69dce 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,37 @@ po/site-specific tests/unit/outputs/ tests/integration/outputs/ +# local configs, most of them are link to files in conf/ depending on instance +/html/.well-known/apple-* +/log.conf +/minion_log.conf + +# data dirs - we shall not mix data and git files, as it makes deployments/updates difficult +/build-cache +/debug +/deleted.images +/dist +/logs +/new_images +/orgs +/products +/tmp +/users +/imports +/lang +/html/dump +/html/files +/html/data +/html/exports +/deleted_private_products +/deleted_products +/deleted_products_images +/export_files + +# Images +/html/images/products + + # Local files .DS_Store? ._* @@ -46,13 +77,10 @@ html/bower_components local # Front build -html/css/dist -html/js/dist -html/images/icons/dist -html/images/attributes/*.svg - -# Images -html/images/products/* +/html/css/dist +/html/js/dist +/html/images/icons/dist +/html/images/attributes/dist # Don't store helm dependencies in our git repo docker/productopener/charts diff --git a/Dockerfile b/Dockerfile index 6e41735fa7dc1..a4e3f65f26e97 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,17 +17,27 @@ RUN --mount=type=cache,id=apt-cache,target=/var/cache/apt set -x && \ apache2 \ apt-utils \ cpanminus \ + # being able to build things g++ \ gcc \ less \ libapache2-mod-perl2 \ - # libexpat1-dev \ make \ gettext \ wget \ + # images processing imagemagick \ graphviz \ tesseract-ocr \ + # ftp client + lftp \ + # some compression utils + gzip \ + tar \ + unzip \ + zip \ + # useful to send mail + mailutils \ # perlmagick \ # # Packages from ./cpanfile: @@ -146,7 +156,9 @@ RUN --mount=type=cache,id=apt-cache,target=/var/cache/apt set -x && \ # gnu readline libreadline-dev \ # IO::AIO needed by Perl::LanguageServer - libperl-dev + libperl-dev \ + # needed to build Apache2::Connection::XForwardedFor + libapache2-mod-perl2-dev # Run www-data user as host user 'off' or developper uid ARG USER_UID @@ -166,7 +178,11 @@ WORKDIR /tmp COPY ./cpanfile* /tmp/ # Add ProductOpener runtime dependencies from cpan RUN --mount=type=cache,id=cpanm-cache,target=/root/.cpanm \ - cpanm $CPANMOPTS --notest --quiet --skip-satisfied --local-lib /tmp/local/ --installdeps . + # first install some dependencies that are not well handled + cpanm --notest --quiet --skip-satisfied --local-lib /tmp/local/ "Apache::Bootstrap" && \ + cpanm $CPANMOPTS --notest --quiet --skip-satisfied --local-lib /tmp/local/ --installdeps . \ + # in case of errors show build.log, but still, fail + || ( for f in /root/.cpanm/work/*/build.log;do echo $f"= start =============";cat $f; echo $f"= end ============="; done; false ) ###################### # backend production image stage @@ -189,20 +205,25 @@ RUN \ RUN \ mkdir -p var/run/apache2/ && \ chown www-data:www-data var/run/apache2/ && \ - for path in data html_data users products product_images orgs new_images logs tmp; do \ + for path in data html_data users products product_images orgs logs new_images deleted_products_images reverted_products deleted_private_products translate deleted_products deleted.images import_files tmp build-cache/taxonomies debug; do \ mkdir -p /mnt/podata/${path}; \ done && \ chown www-data:www-data -R /mnt/podata && \ # Create symlinks of data files that are indeed conf data in /mnt/podata (because we currently mix data and conf data) # NOTE: do not changes those links for they are in a volume, or handle migration in entry-point - for path in data-default external-data emb_codes ingredients madenearme packager-codes po taxonomies templates build-cache; do \ + for path in data-default external-data emb_codes ingredients madenearme packager-codes po taxonomies templates; do \ ln -sf /opt/product-opener/${path} /mnt/podata/${path}; \ done && \ # Create some necessary files to ensure permissions in volumes mkdir -p /opt/product-opener/html/data/ && \ mkdir -p /opt/product-opener/html/data/taxonomies/ && \ - mkdir -p /opt/product-opener/html/images/ && \ + mkdir -p /opt/product-opener/html/images/products && \ chown www-data:www-data -R /opt/product-opener/html/ && \ + # inter services directories (until we get a real solution) + for service in obf off opf opff; do \ + mkdir -p /srv/$service; \ + chown www-data:www-data -R /srv/$service; \ + done && \ # logs dir mkdir -p /var/log/apache2/ && \ chown www-data:www-data -R /var/log diff --git a/Makefile b/Makefile index 9a6361325f2ed..0e9a409a5625b 100644 --- a/Makefile +++ b/Makefile @@ -89,6 +89,11 @@ dev: hello build init_backend _up import_sample_data create_mongodb_indexes refr edit_etc_hosts: @grep -qxF -- "${HOSTS}" /etc/hosts || echo "${HOSTS}" >> /etc/hosts +create_folders: +# create some folders to avoid having them owned by root (when created by docker compose) + @echo "🥫 Creating folders before docker-compose use them." + mkdir -p logs/apache2 logs/nginx debug || ( whoami; ls -l . ; false ) + # TODO: Figure out events => actions and implement live reload # live_reload: # @echo "🥫 Installing when-changed …" @@ -119,7 +124,7 @@ _up: ${DOCKER_COMPOSE} up -d 2>&1 @echo "🥫 started service at http://openfoodfacts.localhost" -up: build _up +up: build create_folders _up down: @echo "🥫 Bringing down containers …" @@ -156,7 +161,7 @@ tail: @echo "🥫 Reading logs (Apache2, Nginx) …" tail -f logs/**/* -codecov_prepare: +codecov_prepare: create_folders @echo "🥫 Preparing to run code coverage…" mkdir -p cover_db ${DOCKER_COMPOSE_TEST} run --rm backend cover -delete @@ -173,13 +178,13 @@ coverage_txt: #----------# # Services # #----------# -build_lang: +build_lang: create_folders @echo "🥫 Rebuild language" # Run build_lang.pl # Languages may build taxonomies on-the-fly so include GITHUB_TOKEN so results can be cached ${DOCKER_COMPOSE} run --rm -e GITHUB_TOKEN=${GITHUB_TOKEN} backend perl -I/opt/product-opener/lib -I/opt/perl/local/lib/perl5 /opt/product-opener/scripts/build_lang.pl -build_lang_test: +build_lang_test: create_folders # Run build_lang.pl in test env ${DOCKER_COMPOSE_TEST} run --rm -e GITHUB_TOKEN=${GITHUB_TOKEN} backend perl -I/opt/product-opener/lib -I/opt/perl/local/lib/perl5 /opt/product-opener/scripts/build_lang.pl @@ -243,14 +248,14 @@ lint: lint_perltidy tests: build_lang_test unit_test integration_test # add COVER_OPTS='-e HARNESS_PERL_SWITCHES="-MDevel::Cover"' if you want to trigger code coverage report generation -unit_test: +unit_test: create_folders @echo "🥫 Running unit tests …" ${DOCKER_COMPOSE_TEST} up -d memcached postgres mongodb ${DOCKER_COMPOSE_TEST} run ${COVER_OPTS} -T --rm backend prove -l --jobs ${CPU_COUNT} -r tests/unit ${DOCKER_COMPOSE_TEST} stop @echo "🥫 unit tests success" -integration_test: +integration_test: create_folders @echo "🥫 Running integration tests …" # we launch the server and run tests within same container # we also need dynamicfront for some assets to exists @@ -268,14 +273,15 @@ test-stop: # usage: make test-unit test=test-name.t # you can add args= to pass options, like args="-d" to debug -test-unit: guard-test +test-unit: guard-test create_folders @echo "🥫 Running test: 'tests/unit/${test}' …" ${DOCKER_COMPOSE_TEST} up -d memcached postgres mongodb ${DOCKER_COMPOSE_TEST} run --rm backend perl ${args} tests/unit/${test} # usage: make test-int test=test-name.t # to update expected results: make test-int test="test-name.t --update-expected-results" -test-int: guard-test # usage: make test-int test=test-file.t +# you can add args= to pass options, like args="-d" to debug +test-int: guard-test create_folders @echo "🥫 Running test: 'tests/integration/${test}' …" ${DOCKER_COMPOSE_TEST} up -d memcached postgres mongodb backend dynamicfront incron minion ${DOCKER_COMPOSE_TEST} exec backend perl ${args} tests/integration/${test} @@ -386,6 +392,9 @@ create_external_volumes: # local data docker volume create --driver=local -o type=none -o o=bind -o device=${DOCKER_LOCAL_DATA}/data ${COMPOSE_PROJECT_NAME}_html_data docker volume create --driver=local -o type=none -o o=bind -o device=${DOCKER_LOCAL_DATA}/podata ${COMPOSE_PROJECT_NAME}_podata +# note for this one, it should be shared with pro instance in the future + docker volume create --driver=local -o type=none -o o=bind -o device=${DOCKER_LOCAL_DATA}/export_files ${COMPOSE_PROJECT_NAME}_export_files + create_external_networks: @echo "🥫 Creating external networks (production only) …" diff --git a/build-cache/taxonomies/README.md b/build-cache/taxonomies/README.md deleted file mode 100644 index ca7cee42e92c2..0000000000000 --- a/build-cache/taxonomies/README.md +++ /dev/null @@ -1,7 +0,0 @@ -Cached copies of taxonomy build results are stored here. - -If no local cache is available then https://github.com/openfoodfacts/openfoodfacts-build-cache is checked for a copy. - -If the taxonomy needs to be built then this will be uploaded back to the repo if the GITHUB_TOKEN environment variable is set. - -The token is a personal access token, created here: https://github.com/settings/tokens. Only the public_repo scope is needed. diff --git a/cgi/change_password.pl b/cgi/change_password.pl index 58467658fd40b..be418e117fbd9 100644 --- a/cgi/change_password.pl +++ b/cgi/change_password.pl @@ -25,6 +25,7 @@ use CGI::Carp qw(fatalsToBrowser); use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Display qw/:all/; use ProductOpener::Users qw/:all/; @@ -51,7 +52,7 @@ my @errors = (); if ($ENV{'REQUEST_METHOD'} eq 'POST') { - my $user_file = "$data_root/users/" . get_string_id_for_lang('no_language', $User_id) . '.sto'; + my $user_file = "$BASE_DIRS{USERS}/" . get_string_id_for_lang('no_language', $User_id) . '.sto'; my $user_ref = retrieve($user_file); if (not(defined $user_ref)) { push @errors, 'undefined user'; @@ -83,7 +84,7 @@ } else { $user_ref->{encrypted_password} = create_password_hash(encode_utf8(decode utf8 => single_param('password'))); - store("$data_root/users/$User_id.sto", $user_ref); + store("$BASE_DIRS{USERS}/$User_id.sto", $user_ref); $template_data_ref->{success} = 1; } } diff --git a/cgi/display.pl b/cgi/display.pl index 281c0badac447..aa0c09aef3228 100755 --- a/cgi/display.pl +++ b/cgi/display.pl @@ -185,7 +185,13 @@ display_properties($request_ref); } elsif (defined $request_ref->{text}) { - display_text($request_ref); + if ($request_ref->{text} =~ /^products_stats/) { + display_stats($request_ref); + } + else { + # note: this also displays the index or index-pro pages + display_text($request_ref); + } } elsif (defined $request_ref->{mission}) { display_mission($request_ref); diff --git a/cgi/import_file_job_status.pl b/cgi/import_file_job_status.pl index 48708ceb9a5a3..ff00f2e60f803 100755 --- a/cgi/import_file_job_status.pl +++ b/cgi/import_file_job_status.pl @@ -28,6 +28,7 @@ use CGI::Carp qw(fatalsToBrowser); use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Display qw/:all/; use ProductOpener::Users qw/:all/; @@ -75,7 +76,7 @@ } else { - $import_files_ref = retrieve("$data_root/import_files/${Owner_id}/import_files.sto"); + $import_files_ref = retrieve("$BASE_DIRS{IMPORT_FILES}/${Owner_id}/import_files.sto"); if ((not defined $import_files_ref) or (not defined $import_files_ref->{$file_id})) { $data{error} = "file_id_not_found"; diff --git a/cgi/import_file_process.pl b/cgi/import_file_process.pl index 516faadccd501..f1b18b031ebb5 100755 --- a/cgi/import_file_process.pl +++ b/cgi/import_file_process.pl @@ -28,6 +28,7 @@ use CGI::Carp qw(fatalsToBrowser); use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Display qw/:all/; use ProductOpener::Users qw/:all/; @@ -59,7 +60,7 @@ display_error_and_exit(lang("no_owner_defined"), 200); } -my $import_files_ref = retrieve("$data_root/import_files/${Owner_id}/import_files.sto"); +my $import_files_ref = retrieve("$BASE_DIRS{IMPORT_FILES}/${Owner_id}/import_files.sto"); if (not defined $import_files_ref) { $import_files_ref = {}; } @@ -73,7 +74,7 @@ if (defined $import_files_ref->{$file_id}) { $extension = $import_files_ref->{$file_id}{extension}; - $file = "$data_root/import_files/${Owner_id}/$file_id.$extension"; + $file = "$BASE_DIRS{IMPORT_FILES}/${Owner_id}/$file_id.$extension"; } else { $log->debug("File not found in import_files.sto", {file_id => $file_id}) if $log->is_debug(); @@ -86,7 +87,7 @@ # Store user columns to OFF fields matches so that they can be reused for the next imports -my $all_columns_fields_ref = retrieve("$data_root/import_files/${Owner_id}/all_columns_fields.sto"); +my $all_columns_fields_ref = retrieve("$BASE_DIRS{IMPORT_FILES}/${Owner_id}/all_columns_fields.sto"); if (not defined $all_columns_fields_ref) { $all_columns_fields_ref = {}; } @@ -136,7 +137,7 @@ store($columns_fields_file, $columns_fields_ref); -store("$data_root/import_files/${Owner_id}/all_columns_fields.sto", $all_columns_fields_ref); +store("$BASE_DIRS{IMPORT_FILES}/${Owner_id}/all_columns_fields.sto", $all_columns_fields_ref); # Default values: use the language and country of the interface my $default_values_ref = { @@ -144,13 +145,13 @@ countries => $cc, }; -my $results_ref = convert_file($default_values_ref, $file, $columns_fields_file, $converted_file); +$results_ref = convert_file($default_values_ref, $file, $columns_fields_file, $converted_file); $import_files_ref->{$file_id}{imports}{$import_id}{converted_t} = time(); if ($results_ref->{error}) { $import_files_ref->{$file_id}{imports}{$import_id}{convert_error} = $results_ref->{error}; - store("$data_root/import_files/${Owner_id}/import_files.sto", $import_files_ref); + store("$BASE_DIRS{IMPORT_FILES}/${Owner_id}/import_files.sto", $import_files_ref); display_error_and_exit($results_ref->{error}, 200); } @@ -162,7 +163,7 @@ file_id => $file_id, import_id => $import_id, comment => "Import from producers platform", - images_download_dir => "$data_root/import_files/${Owner_id}/downloaded_images", + images_download_dir => "$BASE_DIRS{IMPORT_FILES}/${Owner_id}/downloaded_images", }; if (defined $Org_id) { @@ -198,7 +199,7 @@ $import_files_ref->{$file_id}{imports}{$import_id}{job_id} = $job_id; -store("$data_root/import_files/${Owner_id}/import_files.sto", $import_files_ref); +store("$BASE_DIRS{IMPORT_FILES}/${Owner_id}/import_files.sto", $import_files_ref); $template_data_ref->{process_file_id} = $file_id; $template_data_ref->{process_import_id} = $import_id; diff --git a/cgi/import_file_select_format.pl b/cgi/import_file_select_format.pl index 09decd66fa0a8..a4968128fd8e7 100755 --- a/cgi/import_file_select_format.pl +++ b/cgi/import_file_select_format.pl @@ -28,6 +28,7 @@ use CGI::Carp qw(fatalsToBrowser); use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Display qw/:all/; use ProductOpener::Users qw/:all/; @@ -63,7 +64,7 @@ display_error_and_exit(lang("no_owner_defined"), 200); } -my $import_files_ref = retrieve("$data_root/import_files/${Owner_id}/import_files.sto"); +my $import_files_ref = retrieve("$BASE_DIRS{IMPORT_FILES}/${Owner_id}/import_files.sto"); if (not defined $import_files_ref) { $import_files_ref = {}; } @@ -78,7 +79,7 @@ if (defined $import_files_ref->{$file_id}) { $extension = $import_files_ref->{$file_id}{extension}; - $file = "$data_root/import_files/${Owner_id}/$file_id.$extension"; + $file = "$BASE_DIRS{IMPORT_FILES}/${Owner_id}/$file_id.$extension"; } else { $log->debug("File not found in import_files.sto", {file_id => $file_id}) if $log->is_debug(); diff --git a/cgi/import_file_upload.pl b/cgi/import_file_upload.pl index f1dd0d409d56e..3b5ba49508bf0 100755 --- a/cgi/import_file_upload.pl +++ b/cgi/import_file_upload.pl @@ -28,6 +28,7 @@ use CGI::Carp qw(fatalsToBrowser); use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Display qw/:all/; use ProductOpener::Users qw/:all/; @@ -80,10 +81,9 @@ $log->debug("processing upload form", {filename => $filename, file_id => $file_id, extension => $extension}) if $log->is_debug(); - (-e "$data_root/import_files") or mkdir("$data_root/import_files", 0755); - (-e "$data_root/import_files/${Owner_id}") or mkdir("$data_root/import_files/${Owner_id}", 0755); + ensure_dir_created("$BASE_DIRS{IMPORT_FILES}/${Owner_id}") or display_error_and_exit("Missing path", 503); - open(my $out, ">", "$data_root/import_files/${Owner_id}/$file_id.$extension"); + open(my $out, ">", "$BASE_DIRS{IMPORT_FILES}/${Owner_id}/$file_id.$extension"); while (my $chunk = <$file>) { print $out $chunk; } @@ -93,7 +93,7 @@ # Keep track of uploaded files attributes and status - my $import_files_ref = retrieve("$data_root/import_files/${Owner_id}/import_files.sto"); + my $import_files_ref = retrieve("$BASE_DIRS{IMPORT_FILES}/${Owner_id}/import_files.sto"); if (not defined $import_files_ref) { $import_files_ref = {}; } @@ -104,7 +104,7 @@ uploaded_t => $uploaded_t, }; - store("$data_root/import_files/${Owner_id}/import_files.sto", $import_files_ref); + store("$BASE_DIRS{IMPORT_FILES}/${Owner_id}/import_files.sto", $import_files_ref); } else { diff --git a/cgi/login.pl b/cgi/login.pl index e39624c870a6b..891d4e0a4b9ad 100644 --- a/cgi/login.pl +++ b/cgi/login.pl @@ -25,6 +25,7 @@ use CGI::Carp qw(fatalsToBrowser); use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Display qw/:all/; use ProductOpener::Users qw/:all/; @@ -56,7 +57,7 @@ my @errors = (); if ($ENV{'REQUEST_METHOD'} eq 'POST') { - my $user_file = "$data_root/users/" . get_string_id_for_lang('no_language', $User_id) . '.sto'; + my $user_file = "$BASE_DIRS{USERS}/" . get_string_id_for_lang('no_language', $User_id) . '.sto'; my $user_ref = retrieve($user_file); if (not(defined $user_ref)) { push @errors, 'undefined user'; diff --git a/cgi/product_image.pl b/cgi/product_image.pl index 1e6799882908e..a8d13b339c171 100644 --- a/cgi/product_image.pl +++ b/cgi/product_image.pl @@ -25,6 +25,7 @@ use CGI::Carp qw(fatalsToBrowser); use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Lang qw/:all/; @@ -103,7 +104,7 @@ } if (defined $product_ref->{images}{$id}{rev}) { - my $changes_ref = retrieve("$data_root/products/$path/changes.sto"); + my $changes_ref = retrieve("$BASE_DIRS{PRODUCTS}/$path/changes.sto"); if (not defined $changes_ref) { $changes_ref = []; } diff --git a/cgi/product_image_rotate.pl b/cgi/product_image_rotate.pl index a1b630499b7ca..ea9f040c3ef33 100755 --- a/cgi/product_image_rotate.pl +++ b/cgi/product_image_rotate.pl @@ -25,6 +25,7 @@ use CGI::Carp qw(fatalsToBrowser); use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Products qw/:all/; use ProductOpener::Display qw/:all/; @@ -61,10 +62,10 @@ } my $image = Image::Magick->new; -my $x = $image->Read("$www_root/images/products/$path/$imgid.${crop_size}.jpg"); +my $x = $image->Read("$BASE_DIRS{PRODUCTS_IMAGES}/$path/$imgid.${crop_size}.jpg"); if ("$x") { $log->error('could not read image', - {path => "$www_root/images/products/$path/$imgid.${crop_size}.jpg", status => $x}) + {path => "$BASE_DIRS{PRODUCTS_IMAGES}/$path/$imgid.${crop_size}.jpg", status => $x}) if $log->is_error(); ## no critic (ProhibitPostfixControls) $r->status(HTTP_NOT_FOUND); return OK; diff --git a/cgi/product_image_upload.pl b/cgi/product_image_upload.pl index 9391ded5974e8..02daef7786fe6 100755 --- a/cgi/product_image_upload.pl +++ b/cgi/product_image_upload.pl @@ -25,6 +25,7 @@ use CGI::Carp qw(fatalsToBrowser); use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; @@ -114,19 +115,19 @@ my $extension = lc($1); $tmp_filename = get_string_id_for_lang("no_language", remote_addr() . '_' . $`); - (-e "$data_root/tmp") or mkdir("$data_root/tmp", 0755); - open(my $out, ">", "$data_root/tmp/$tmp_filename.$extension"); + ensure_dir_created($BASE_DIRS{CACHE_TMP}) or display_error_and_exit("Missing path", 503); + open(my $out, ">", "$BASE_DIRS{CACHE_TMP}/$tmp_filename.$extension"); while (my $chunk = <$file>) { print $out $chunk; } close($out); - $code = scan_code("$data_root/tmp/$tmp_filename.$extension"); + $code = scan_code("$BASE_DIRS{CACHE_TMP}/$tmp_filename.$extension"); if (defined $code) { $code = normalize_code($code); $scanned_code = $code; } - $tmp_filename = "$data_root/tmp/$tmp_filename.$extension"; + $tmp_filename = "$BASE_DIRS{CACHE_TMP}/$tmp_filename.$extension"; } # If we have a previous code, use it @@ -173,13 +174,8 @@ my $interface_version = '20120622'; -# Create image directory if needed -if (!-e "$www_root/images") { - mkdir("$www_root/images", 0755); -} -if (!-e "$www_root/images/products") { - mkdir("$www_root/images/products", 0755); -} +# Check that the image directory exists +ensure_dir_created($BASE_DIRS{PRODUCTS_IMAGES}) or display_error_and_exit("Missing path", 503); if ($imagefield) { diff --git a/cgi/product_jqm_multilingual.pl b/cgi/product_jqm_multilingual.pl index 8483c14350db6..cb930aaae2d34 100755 --- a/cgi/product_jqm_multilingual.pl +++ b/cgi/product_jqm_multilingual.pl @@ -37,6 +37,7 @@ =head1 DESCRIPTION use CGI::Carp qw(fatalsToBrowser); use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; @@ -139,8 +140,8 @@ =head1 DESCRIPTION my @errors = (); # Store parameters for debug purposes - (-e "$data_root/debug") or mkdir("$data_root/debug", 0755); - open(my $out, ">", "$data_root/debug/product_jqm_multilingual." . time() . "." . $code); + ensure_dir_created($BASE_DIRS{CACHE_DEBUG}) or display_error_and_exit("Missing path", 503); + open(my $out, ">", "$BASE_DIRS{CACHE_DEBUG}/product_jqm_multilingual." . time() . "." . $code); print $out encode_json(Vars()); close $out; diff --git a/cgi/product_multilingual.pl b/cgi/product_multilingual.pl index c75e48fc428f4..4f50fd9c22c06 100755 --- a/cgi/product_multilingual.pl +++ b/cgi/product_multilingual.pl @@ -25,6 +25,7 @@ use CGI::Carp qw(fatalsToBrowser); use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; @@ -534,12 +535,12 @@ ($product_ref) foreach my $max ($thumb_size, $small_size, $display_size, "full") { my $from_file - = "$www_root/images/products/$path/" + = "$BASE_DIRS{PRODUCTS_IMAGES}/$path/" . $from_imageid . "." . $rev . "." . $max . ".jpg"; my $to_file - = "$www_root/images/products/$path/" + = "$BASE_DIRS{PRODUCTS_IMAGES}/$path/" . $to_imageid . "." . $rev . "." . $max . ".jpg"; diff --git a/cgi/remove_products.pl b/cgi/remove_products.pl index 85bb647898ab8..840bebe1ac3ae 100644 --- a/cgi/remove_products.pl +++ b/cgi/remove_products.pl @@ -28,6 +28,7 @@ use CGI::Carp qw(fatalsToBrowser); use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Display qw/:all/; use ProductOpener::Users qw/:all/; @@ -80,21 +81,19 @@ require File::Copy::Recursive; File::Copy::Recursive->import(qw( dirmove )); - my $deleted_dir = $data_root . "/deleted_private_products/" . $Owner_id . "." . time(); - (-e $data_root . "/deleted_private_products") or mkdir($data_root . "/deleted_private_products", oct(755)); + my $deleted_dir = $BASE_DIRS{DELETED_PRIVATE_PRODUCTS} . "/" . $Owner_id . "." . time(); + ensure_dir_created($BASE_DIRS{PRODUCTS_IMAGES}) or display_error_and_exit("Missing path", 503); $log->debug("Moving data to deleted dir", {owner => $Owner_id, deleted_dir => $deleted_dir}) if $log->is_debug(); - mkdir($deleted_dir, oct(755)); - - dirmove("$data_root/import_files/$Owner_id", "$deleted_dir/import_files") - or print STDERR "Could not move $data_root/import_files/$Owner_id to $deleted_dir/import_files : $!\n"; - dirmove("$data_root/export_files/$Owner_id", "$deleted_dir/export_files") - or print STDERR "Could not move $data_root/export_files/$Owner_id to $deleted_dir/export_files : $!\n"; - dirmove("$data_root/products/$Owner_id", "$deleted_dir/products") - or print STDERR "Could not move $data_root/products/$Owner_id to $deleted_dir/products : $!\n"; - dirmove("$www_root/images/products/$Owner_id", "$deleted_dir/images") - or print STDERR "Could not move $www_root/images/products/$Owner_id to $deleted_dir/images : $!\n"; + dirmove("$BASE_DIRS{IMPORT_FILES}/$Owner_id", "$deleted_dir/import_files") + or print STDERR "Could not move $BASE_DIRS{IMPORT_FILES}/$Owner_id to $deleted_dir/import_files : $!\n"; + dirmove("$BASE_DIRS{EXPORT_FILES}/$Owner_id", "$deleted_dir/export_files") + or print STDERR "Could not move $BASE_DIRS{EXPORT_FILES}/$Owner_id to $deleted_dir/export_files : $!\n"; + dirmove("$BASE_DIRS{PRODUCTS}/$Owner_id", "$deleted_dir/products") + or print STDERR "Could not move $BASE_DIRS{PRODUCTS}/$Owner_id to $deleted_dir/products : $!\n"; + dirmove("$BASE_DIRS{PRODUCTS_IMAGES}/$Owner_id", "$deleted_dir/images") + or print STDERR "Could not move $BASE_DIRS{PRODUCTS_IMAGES}/$Owner_id to $deleted_dir/images : $!\n"; } diff --git a/cgi/reset_password.pl b/cgi/reset_password.pl index 8cb9134224115..9dbccb89c12e6 100755 --- a/cgi/reset_password.pl +++ b/cgi/reset_password.pl @@ -25,6 +25,7 @@ use CGI::Carp qw(fatalsToBrowser); use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; @@ -69,7 +70,7 @@ # Is it an email? if ($id =~ /\@/) { - my $emails_ref = retrieve("$data_root/users/users_emails.sto"); + my $emails_ref = retrieve("$BASE_DIRS{USERS}/users_emails.sto"); if (not defined $emails_ref->{$id}) { # not found, try with lower case email $id = lc $id; @@ -83,7 +84,7 @@ } else { $id = get_string_id_for_lang("no_language", $id); - if (!-e "$data_root/users/$id.sto") { + if (!-e "$BASE_DIRS{USERS}/$id.sto") { push @errors, $Lang{error_reset_unknown_id}{$lang}; } else { @@ -142,14 +143,14 @@ foreach my $userid (@userids) { - my $user_ref = retrieve("$data_root/users/$userid.sto"); + my $user_ref = retrieve("$BASE_DIRS{USERS}/$userid.sto"); if (defined $user_ref) { $user_ref->{token_t} = time(); $user_ref->{token} = generate_token(64); $user_ref->{token_ip} = remote_addr(); - store("$data_root/users/$userid.sto", $user_ref); + store("$BASE_DIRS{USERS}/$userid.sto", $user_ref); my $url = format_subdomain($subdomain) @@ -167,7 +168,7 @@ } elsif ($type eq 'reset') { my $userid = get_string_id_for_lang("no_language", single_param('resetid')); - my $user_ref = retrieve("$data_root/users/$userid.sto"); + my $user_ref = retrieve("$BASE_DIRS{USERS}/$userid.sto"); $log->debug("resetting password", {userid => $userid}) if $log->is_debug(); @@ -190,7 +191,7 @@ delete $user_ref->{token}; - store("$data_root/users/$userid.sto", $user_ref); + store("$BASE_DIRS{USERS}/$userid.sto", $user_ref); } else { diff --git a/cgi/search.pl b/cgi/search.pl index fe61c7d76ec83..2daa2062065ef 100755 --- a/cgi/search.pl +++ b/cgi/search.pl @@ -26,6 +26,7 @@ use CGI qw/:cgi :form escapeHTML/; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; @@ -710,7 +711,7 @@ my $graph = single_param("graph") || ''; my $download = single_param("download") || ''; - open(my $OUT, ">>:encoding(UTF-8)", "$data_root/logs/search_log_debug"); + open(my $OUT, ">>:encoding(UTF-8)", "$BASE_DIRS{LOGS}/search_log_debug"); print $OUT remote_addr() . "\t" . time() . "\t" . decode utf8 => single_param('search_terms') . " - map: $map - graph: $graph - download: $download - page: $page\n"; close($OUT); @@ -824,7 +825,7 @@ } if (single_param('search_terms')) { - open(my $OUT, ">>:encoding(UTF-8)", "$data_root/logs/search_log"); + open(my $OUT, ">>:encoding(UTF-8)", "$BASE_DIRS{LOGS}/search_log"); print $OUT remote_addr() . "\t" . time() . "\t" . decode utf8 => single_param('search_terms') diff --git a/cgi/sucres_check.pl b/cgi/sucres_check.pl deleted file mode 100755 index 6979350200de1..0000000000000 --- a/cgi/sucres_check.pl +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/perl -w - -# This file is part of Product Opener. -# -# Product Opener -# Copyright (C) 2011-2023 Association Open Food Facts -# Contact: contact@openfoodfacts.org -# Address: 21 rue des Iles, 94100 Saint-Maur des Fossés, France -# -# Product Opener is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . - -use ProductOpener::PerlStandards; - -use CGI::Carp qw(fatalsToBrowser); -use CGI qw/:cgi :form escapeHTML/; -use Encode; -use JSON::PP; - -my $debug = 0; - -my $code = decode utf8 => single_param('code'); -my $product = decode utf8 => single_param('product'); -my $name = decode utf8 => single_param('name'); -my $answer = decode utf8 => single_param('answer'); -my $actual = decode utf8 => single_param('actual'); -my $points = decode utf8 => single_param('points'); - -open(my $OUT, ">>", "/srv/sucres/logs/sugar_log"); -print $OUT remote_addr() . "\t" - . time() . "\t" - . $product . "\t" - . $code . "\t" - . $actual . "\t" - . $answer . "\t" - . $points . "\n"; -close $OUT; - -print header(-type => 'text/html', -charset => 'utf-8'); diff --git a/cgi/sucres_random.pl b/cgi/sucres_random.pl deleted file mode 100755 index d366628bb8f0d..0000000000000 --- a/cgi/sucres_random.pl +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/perl -w - -# This file is part of Product Opener. -# -# Product Opener -# Copyright (C) 2011-2023 Association Open Food Facts -# Contact: contact@openfoodfacts.org -# Address: 21 rue des Iles, 94100 Saint-Maur des Fossés, France -# -# Product Opener is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . - -use ProductOpener::PerlStandards; - -use CGI::Carp qw(fatalsToBrowser); -use CGI qw/:cgi :form escapeHTML/; -use Encode; -use JSON::PP; -use Storable qw(lock_store lock_nstore lock_retrieve); -use Apache2::RequestRec (); -use Apache2::Const (); - -use List::Util qw(shuffle); -use Log::Any qw($log); - -my $ids_ref = lock_retrieve("/srv/sucres/data/products_ids.sto"); -my @ids = @$ids_ref; - -srand(); - -my @shuffle = shuffle(@ids); - -my $id = pop(@shuffle); - -$log->info("random ids sampled", {ids => scalar(@ids), id => $id}) if $log->is_info(); -my $r = shift; - -$r->headers_out->set(Location => "/$id"); -$r->headers_out->set(Pragma => "no-cache"); -$r->headers_out->set("Cache-control" => "no-cache"); -$r->status(302); -return 302; - diff --git a/cgi/sugar_check.pl b/cgi/sugar_check.pl index 04264dc7a4a7d..00c4f2a7f5a74 100755 --- a/cgi/sugar_check.pl +++ b/cgi/sugar_check.pl @@ -26,6 +26,12 @@ use CGI qw/:cgi :form escapeHTML/; use Encode; use JSON::PP; +use Digest::SHA1 qw(sha1_hex); + +use ProductOpener::Display qw/single_param/; +use ProductOpener::Paths qw/:all/; + +# this script is used by howmuchsugar to log user answers to sugar questions my $debug = 0; @@ -36,8 +42,9 @@ my $actual = decode utf8 => single_param('actual'); my $points = decode utf8 => single_param('points'); -open(my $OUT, ">>", "/srv/sugar/logs/sugar_log"); -print $OUT remote_addr() . "\t" +my $current_year = (localtime())[5] + 1900; +open(my $OUT, ">>", $BASE_DIRS{PRIVATE_DATA} . "/${current_year}_sugar_log"); +print $OUT sha1_hex(remote_addr()) . "\t" . time() . "\t" . $product . "\t" . $code . "\t" diff --git a/cgi/sugar_random.pl b/cgi/sugar_random.pl index 06fab260385a1..b4a85d1501f62 100755 --- a/cgi/sugar_random.pl +++ b/cgi/sugar_random.pl @@ -33,7 +33,17 @@ use List::Util qw(shuffle); use Log::Any qw($log); -my $ids_ref = lock_retrieve("/srv/sugar/data/products_ids.sto"); +use ProductOpener::Paths qw/:all/; + +# this script is used by howmuchsugar to redirect to a new product randomly + +my $r = shift; + +# read site name in apache provided header +my $lang = $r->headers_in->{"X-Site-Lang"} // 'en'; + +my $ids_ref = lock_retrieve($BASE_DIRS{PRIVATE_DATA} . "/sugar/$lang/products_ids.sto") + or die("Cannot open sugar/products_ids.sto"); my @ids = @$ids_ref; srand(); @@ -43,7 +53,6 @@ my $id = pop(@shuffle); $log->info("random ids sampled", {ids => scalar(@ids), id => $id}) if $log->is_info(); -my $r = shift; $r->headers_out->set(Location => "/$id"); $r->headers_out->set(Pragma => "no-cache"); diff --git a/cgi/user.pl b/cgi/user.pl index d0b91ff417720..6b5e3509bc9ff 100644 --- a/cgi/user.pl +++ b/cgi/user.pl @@ -23,6 +23,7 @@ use ProductOpener::PerlStandards; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; @@ -69,7 +70,7 @@ # The userid looks like an e-mail if ($admin and ($userid =~ /\@/)) { - my $emails_ref = retrieve("$data_root/users/users_emails.sto"); + my $emails_ref = retrieve("$BASE_DIRS{USERS}/users_emails.sto"); if (defined $emails_ref->{$userid}) { $userid = $emails_ref->{$userid}[0]; } @@ -87,7 +88,7 @@ my $user_ref = {}; if ($type =~ /^edit/) { - $user_ref = retrieve("$data_root/users/$userid.sto"); + $user_ref = retrieve("$BASE_DIRS{USERS}/$userid.sto"); if (not defined $user_ref) { display_error_and_exit($Lang{error_invalid_user}{$lang}, 404); } diff --git a/conf/apache-2.4/off-mpm_prefork.conf b/conf/apache-2.4/off-mpm_prefork.conf new file mode 100644 index 0000000000000..27ee9c64434ba --- /dev/null +++ b/conf/apache-2.4/off-mpm_prefork.conf @@ -0,0 +1,17 @@ +# prefork MPM +# StartServers: number of server processes to start +# MinSpareServers: minimum number of server processes which are kept spare +# MaxSpareServers: maximum number of server processes which are kept spare +# MaxRequestWorkers: maximum number of server processes allowed to start +# MaxConnectionsPerChild: maximum number of requests a server process serves + + + StartServers 5 + MinSpareServers 5 + MaxSpareServers 10 + MaxRequestWorkers 50 + ServerLimit 55 + MaxConnectionsPerChild 500 + + +# vim: syntax=apache ts=4 sw=4 sts=4 sr noet diff --git a/conf/apache-2.4/off-ports.conf b/conf/apache-2.4/off-ports.conf new file mode 100644 index 0000000000000..b3116f1893ab5 --- /dev/null +++ b/conf/apache-2.4/off-ports.conf @@ -0,0 +1,7 @@ +# If you just change the port or add more ports here, you will likely also +# have to change the VirtualHost statement in +# /etc/apache2/sites-enabled/000-default.conf + +Listen 8004 + +# vim: syntax=apache ts=4 sw=4 sts=4 sr noet diff --git a/conf/apache-2.4/off-pro-mpm_prefork.conf b/conf/apache-2.4/off-pro-mpm_prefork.conf new file mode 100644 index 0000000000000..2642e3bd407f1 --- /dev/null +++ b/conf/apache-2.4/off-pro-mpm_prefork.conf @@ -0,0 +1,16 @@ +# prefork MPM +# StartServers: number of server processes to start +# MinSpareServers: minimum number of server processes which are kept spare +# MaxSpareServers: maximum number of server processes which are kept spare +# MaxRequestWorkers: maximum number of server processes allowed to start +# MaxConnectionsPerChild: maximum number of requests a server process serves + + + StartServers 5 + MinSpareServers 5 + MaxSpareServers 10 + MaxRequestWorkers 150 + MaxConnectionsPerChild 0 + + +# vim: syntax=apache ts=4 sw=4 sts=4 sr noet diff --git a/conf/apache-2.4/off-pro-ports.conf b/conf/apache-2.4/off-pro-ports.conf new file mode 100644 index 0000000000000..65c945369d3e4 --- /dev/null +++ b/conf/apache-2.4/off-pro-ports.conf @@ -0,0 +1,7 @@ +# If you just change the port or add more ports here, you will likely also +# have to change the VirtualHost statement in +# /etc/apache2/sites-enabled/000-default.conf + +Listen 8014 + +# vim: syntax=apache ts=4 sw=4 sts=4 sr noet diff --git a/conf/apache-2.4/sites-available/off.conf b/conf/apache-2.4/sites-available/off.conf index 3776213f29a52..2360977cd5234 100644 --- a/conf/apache-2.4/sites-available/off.conf +++ b/conf/apache-2.4/sites-available/off.conf @@ -8,7 +8,7 @@ PerlWarn On PerlRequire /srv/off/lib/startup_apache2.pl # log the X-Forwarded-For IP address (the client ip) in access_log -LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" proxy +LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %T/%D" proxy SetHandler perl-script @@ -33,5 +33,5 @@ Require all granted -PerlPostReadRequestHandler My::ProxyRemoteAddr +PerlPostReadRequestHandler get_remote_proxy_address diff --git a/conf/apache-2.4/sites-available/opf.conf b/conf/apache-2.4/sites-available/opf.conf index 6e458ab81c674..8251fe5f24cc5 100644 --- a/conf/apache-2.4/sites-available/opf.conf +++ b/conf/apache-2.4/sites-available/opf.conf @@ -34,5 +34,5 @@ Require all granted -PerlPostReadRequestHandler My::ProxyRemoteAddr +PerlPostReadRequestHandler get_remote_proxy_address diff --git a/conf/apache-2.4/sites-available/opff.conf b/conf/apache-2.4/sites-available/opff.conf index 9dd6f844cdf26..2dad81fe586a3 100644 --- a/conf/apache-2.4/sites-available/opff.conf +++ b/conf/apache-2.4/sites-available/opff.conf @@ -33,5 +33,4 @@ Require all granted -PerlPostReadRequestHandler My::ProxyRemoteAddr - +PerlPostReadRequestHandler get_remote_proxy_address diff --git a/conf/logrotate/apache2 b/conf/logrotate/apache2 new file mode 100644 index 0000000000000..b1b99b486fc18 --- /dev/null +++ b/conf/logrotate/apache2 @@ -0,0 +1,25 @@ +# we want to rotate apache2 files as well as perl logs, +# we define all possible patterns, as we have missingok, so we don't have to worry +/var/log/apache2/*log /var/log/off/*log /var/log/opff/*log /var/log/obf/*log /var/log/opf/*log { + daily + missingok + rotate -1 + # remove after two years + maxage 730 + compress + delaycompress + notifempty + create 640 off off + # restart apache only once + sharedscripts + prerotate + if [ -d /etc/logrotate.d/httpd-prerotate ]; then + run-parts /etc/logrotate.d/httpd-prerotate + fi + endscript + postrotate + if pgrep -f ^/usr/sbin/apache2 > /dev/null; then + invoke-rc.d apache2 reload 2>&1 | logger -t apache2.logrotate + fi + endscript +} diff --git a/conf/nginx.conf b/conf/nginx.conf index 4694d3b880afb..6a705bb664327 100644 --- a/conf/nginx.conf +++ b/conf/nginx.conf @@ -39,7 +39,7 @@ server { index index.html index.htm index.nginx-debian.html; location /data/ { - include conf.d/off.cors-headers.include; + include /etc/nginx/snippets/off.cors-headers.include; # First attempt to serve request as file, then # as directory, then fall back to displaying a 404. try_files $uri $uri/ =404; @@ -49,10 +49,10 @@ server { index index.html index.htm index.nginx-debian.html; # handling expirations - include conf.d/expires-no-json-xml.include; + include /etc/nginx/snippets/expires-no-json-xml.conf; location ~ ^/images/products/ { - include conf.d/off.cors-headers.include; + include /etc/nginx/snippets/off.cors-headers.include; add_header Link "; rel='license'; title='CC-BY-SA 3.0'"; # optimize gzip compressed content (like OCR .json stored next to .jpg files) gzip_static always; @@ -61,8 +61,16 @@ server { # Static files are served directly by NGINX - location ~ ^/(.well-known|images|fonts|css|js|rss|files|resources|foundation|bower_components)/ { - include conf.d/off.cors-headers.include; + location ~ ^/files/(.*) { + include snippets/off.cors-headers.include; + # fist try in files_resources + try_files files_resources/$1 $uri $uri/ =404; + gzip_static always; + gunzip on; + } + + location ~ ^/(.well-known|images|fonts|css|js|rss|resources|foundation|bower_components)/ { + include /etc/nginx/snippets/off.cors-headers.include; # First attempt to serve request as file, then # as directory, then fall back to displaying a 404. try_files $uri $uri/ =404; @@ -73,18 +81,19 @@ server { # GoogleAssociationService made 2500 requests/min to assetlinks.json # and much less when caching headers are sent location = /.well-known/assetlinks.json { - include conf.d/off.cors-headers.include; + include /etc/nginx/snippets/off.cors-headers.include; expires 1d; try_files $uri $uri/ =404; } location ~ /(favicon\.ico)$ { - include conf.d/off.cors-headers.include; + include /etc/nginx/snippets/off.cors-headers.include; + expires 1d; try_files $uri $uri/ =404; } # redirects of some locations - include conf.d/off.locations-redirects.include; + include /etc/nginx/snippets/off.locations-redirects.include; # Dynamically generated files and CGI scripts are passed # to the Apache + mod_perl server running on the backend container @@ -92,7 +101,7 @@ server { # this is the internal Docker DNS, cache only for 30s resolver 127.0.0.11 valid=30s; location ~ /donate\/.*$ { - include conf.d/off.cors-headers.include; + include /etc/nginx/snippets/off.cors-headers.include; try_files $uri =404; } location / { diff --git a/conf/nginx/conf.d/log_format_realip.conf b/conf/nginx/conf.d/log_format_realip.conf new file mode 100644 index 0000000000000..2127ae532971e --- /dev/null +++ b/conf/nginx/conf.d/log_format_realip.conf @@ -0,0 +1,6 @@ +# a log format for behing a proxy +log_format proxied_requests + '$http_x_forwarded_for - $remote_user [$time_local] ' + '"$request" $status $body_bytes_sent ' + '"$http_referer" "$http_user_agent"'; + diff --git a/conf/nginx/sites-available/cestemballepresdechezvous b/conf/nginx/sites-available/cestemballepresdechezvous deleted file mode 100644 index d80b35def2404..0000000000000 --- a/conf/nginx/sites-available/cestemballepresdechezvous +++ /dev/null @@ -1,104 +0,0 @@ -## -# You should look at the following URL's in order to grasp a solid understanding -# of Nginx configuration files in order to fully unleash the power of Nginx. -# http://wiki.nginx.org/Pitfalls -# http://wiki.nginx.org/QuickStart -# http://wiki.nginx.org/Configuration -# -# Generally, you will want to move this file somewhere, and start with a clean -# file but keep this around for reference. Or just disable in sites-enabled. -# -# Please see /usr/share/doc/nginx-doc/examples/ for more detailed examples. -## - -# Default server configuration -# - -server { - listen 80; - listen [::]:80; - server_name cestfabriquepresdechezvous.info www.cestemballepresdechezvous.fr www.cestemballepresdechezvous.info www.cestfabriquepresdechezvous.info; - return 301 http://cestemballepresdechezvous.fr$request_uri; -} - - -server { - #listen 80 default_server; - listen 80; - #listen [::]:80 default_server; - listen [::]:80; - - server_name cestemballepresdechezvous.fr; - - # SSL configuration - # - # listen 443 ssl default_server; - # listen [::]:443 ssl default_server; - # - # Self signed certs generated by the ssl-cert package - # Don't use them in a production server! - # - # include snippets/snakeoil.conf; - - listen 443 ssl http2; - listen [::]:443 ssl http2; - include snippets/ssl.cestemballepresdechezvous.fr; - include snippets/ssl-params.conf; - - root /srv/off/html; - - access_log /srv/off/logs/nginx.cestemballepresdechezvous.access.log; - error_log /srv/off/logs/nginx.cestemballepresdechezvous.error.log; - - gzip on; - gzip_min_length 1000; - - - # Add index.php to the list if you are using PHP - index index.html index.htm index.nginx-debian.html; - - location ~* \.(eot|ttf|woff|woff2)$ { - add_header Access-Control-Allow-Origin *; - } - - location ~ ^/images/products/ { - add_header Link "; rel='license'; title='CC-BY-SA 3.0'"; - } - - location ~ ^/(favicon.ico) { - # First attempt to serve request as file, then - # as directory, then fall back to displaying a 404. - try_files $uri /images/misc/cestemballepresdechezvous.16x16.png; - } - - - location ~ ^/(.well-known|images|js|rss|data|files|resources|foundation)/ { - # First attempt to serve request as file, then - # as directory, then fall back to displaying a 404. - try_files $uri $uri/ =404; - } - - location = /robots.txt { - try_files $uri $uri/ =404; - } - - location / { - try_files $uri /cestemballepresdechezvous.html; - } - - location /cgi/ { - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_pass http://127.0.0.1:8001; - } - - # deny access to .htaccess files, if Apache's document root - # concurs with nginx's one - # - #location ~ /\.ht { - # deny all; - #} - - include /etc/nginx/expires-no-json-xml.conf; -} diff --git a/conf/nginx/sites-available/combiendesucres b/conf/nginx/sites-available/combiendesucres deleted file mode 100644 index 33e8dc44eaead..0000000000000 --- a/conf/nginx/sites-available/combiendesucres +++ /dev/null @@ -1,105 +0,0 @@ -## -# You should look at the following URL's in order to grasp a solid understanding -# of Nginx configuration files in order to fully unleash the power of Nginx. -# http://wiki.nginx.org/Pitfalls -# http://wiki.nginx.org/QuickStart -# http://wiki.nginx.org/Configuration -# -# Generally, you will want to move this file somewhere, and start with a clean -# file but keep this around for reference. Or just disable in sites-enabled. -# -# Please see /usr/share/doc/nginx-doc/examples/ for more detailed examples. -## - -# Default server configuration -# - -server { - listen 80; - listen [::]:80; - server_name www.combiendesucres.fr combiendesucre.fr www.combiendesucre.fr; - return 301 http://combiendesucres.fr$request_uri; -} - - -server { - #listen 80 default_server; - listen 80; - #listen [::]:80 default_server; - listen [::]:80; - - server_name combiendesucres.fr; - - # SSL configuration - # - # listen 443 ssl default_server; - # listen [::]:443 ssl default_server; - # - # Self signed certs generated by the ssl-cert package - # Don't use them in a production server! - # - # include snippets/snakeoil.conf; - - listen 443 ssl http2; - listen [::]:443 ssl http2; - include snippets/ssl.combiendesucres.fr; - include snippets/ssl-params.conf; - - root /srv/sucres/html; - - access_log /srv/sucres/logs/nginx.combiendesucres.access.log; - error_log /srv/sucres/logs/nginx.combiendesucres.error.log; - - gzip on; - gzip_min_length 1000; - - - # Add index.php to the list if you are using PHP - index index.html index.htm index.nginx-debian.html; - - location ~* \.(eot|ttf|woff|woff2)$ { - add_header Access-Control-Allow-Origin *; - } - - location ~ ^/(favicon.ico) { - # First attempt to serve request as file, then - # as directory, then fall back to displaying a 404. - try_files $uri /combiendesucres-favicon.ico; - } - - - location ~ ^/(.well-known|fonts|images|js|rss|data|files|resources|foundation)/ { - # First attempt to serve request as file, then - # as directory, then fall back to displaying a 404. - try_files $uri $uri/ =404; - } - - location = /robots.txt { - try_files $uri $uri/ =404; - } - - location ~ ^/$ { - try_files $uri /combiendesucres.html; - } - - # redirect to .html files - location / { - try_files $uri $uri.html =404; - } - - location /cgi/ { - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_pass http://127.0.0.1:8001; - } - - # deny access to .htaccess files, if Apache's document root - # concurs with nginx's one - # - #location ~ /\.ht { - # deny all; - #} - - include /etc/nginx/expires-no-json-xml.conf; -} diff --git a/conf/nginx/sites-available/howmuchsugar b/conf/nginx/sites-available/howmuchsugar index 9985ec7f5a6eb..d6815f494e6ef 100644 --- a/conf/nginx/sites-available/howmuchsugar +++ b/conf/nginx/sites-available/howmuchsugar @@ -1,58 +1,36 @@ -## -# You should look at the following URL's in order to grasp a solid understanding -# of Nginx configuration files in order to fully unleash the power of Nginx. -# http://wiki.nginx.org/Pitfalls -# http://wiki.nginx.org/QuickStart -# http://wiki.nginx.org/Configuration -# -# Generally, you will want to move this file somewhere, and start with a clean -# file but keep this around for reference. Or just disable in sites-enabled. -# -# Please see /usr/share/doc/nginx-doc/examples/ for more detailed examples. -## - -# Default server configuration -# +map $host $howmuchsugar_name { + hostnames; -server { - listen 80; - listen [::]:80; - server_name www.howmuchsugar.in howmuchsugar.info www.howmuchsugar.info; - return 301 http://howmuchsugar.in$request_uri; + default howmuchsugar; + combiendesucres.fr combiendesucres; } +map $howmuchsugar_name $howmuchsugar_lang { + + default en; + combiendesucres fr; +} +log_format proxied_requests2 + '$http_x_forwarded_for - $remote_user [$time_local] ' + '"$request" $status $body_bytes_sent ' + '"$http_referer" "$http_user_agent"' + '"$howmuchsugar_lang" "$howmuchsugar_name"'; server { - #listen 80 default_server; listen 80; - #listen [::]:80 default_server; listen [::]:80; - server_name howmuchsugar.in; + server_name howmuchsugar.in combiendesucres.fr; - # SSL configuration - # - # listen 443 ssl default_server; - # listen [::]:443 ssl default_server; - # - # Self signed certs generated by the ssl-cert package - # Don't use them in a production server! - # - # include snippets/snakeoil.conf; + include /etc/nginx/snippets/expires-no-json-xml.conf; - listen 443 ssl http2; - listen [::]:443 ssl http2; - include snippets/ssl.howmuchsugar.in; - include snippets/ssl-params.conf; - - root /srv/sugar/html; - - access_log /srv/sugar/logs/nginx.howmuchsugar.access.log; - error_log /srv/sugar/logs/nginx.howmuchsugar.error.log; + access_log /var/log/nginx/nginx.howmuchsugar.access.log proxied_requests2; + error_log /var/log/nginx/nginx.howmuchsugar.error.log; gzip on; gzip_min_length 1000; + root /srv/off/html/data/sugar/$howmuchsugar_lang; # Add index.php to the list if you are using PHP index index.html index.htm index.nginx-debian.html; @@ -64,10 +42,9 @@ server { location ~ ^/(favicon.ico) { # First attempt to serve request as file, then # as directory, then fall back to displaying a 404. - try_files $uri /howmuchsugar-favicon.ico; + try_files $howmuchsugar_name-favicon.ico =404; } - location ~ ^/(.well-known|images|js|rss|data|files|resources|foundation)/ { # First attempt to serve request as file, then # as directory, then fall back to displaying a 404. @@ -79,7 +56,7 @@ server { } location ~ ^/$ { - try_files $uri /howmuchsugar.html; + try_files $uri /$howmuchsugar_name.html; } # redirect to .html files @@ -87,19 +64,13 @@ server { try_files $uri $uri.html =404; } - location /cgi/ { + # we use sugar_check.pl and sugar_random.pl + location /cgi/sugar_ { proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_pass http://127.0.0.1:8001; + proxy_set_header X-Site-Name $howmuchsugar_name; + proxy_set_header X-Site-Lang $howmuchsugar_lang; + proxy_pass http://127.0.0.1:8004; } - - # deny access to .htaccess files, if Apache's document root - # concurs with nginx's one - # - #location ~ /\.ht { - # deny all; - #} - - include /etc/nginx/expires-no-json-xml.conf; } diff --git a/conf/nginx/sites-available/madenearme b/conf/nginx/sites-available/madenearme index feb28af2cd4c2..03fe6cdaa6f26 100644 --- a/conf/nginx/sites-available/madenearme +++ b/conf/nginx/sites-available/madenearme @@ -1,58 +1,26 @@ -## -# You should look at the following URL's in order to grasp a solid understanding -# of Nginx configuration files in order to fully unleash the power of Nginx. -# http://wiki.nginx.org/Pitfalls -# http://wiki.nginx.org/QuickStart -# http://wiki.nginx.org/Configuration -# -# Generally, you will want to move this file somewhere, and start with a clean -# file but keep this around for reference. Or just disable in sites-enabled. -# -# Please see /usr/share/doc/nginx-doc/examples/ for more detailed examples. -## - -# Default server configuration -# - -server { - listen 80; - listen [::]:80; - server_name madenearme.com www.madenearme.com madenearme.org www.madenear.org madenear.com www.madenear.com www.madenear.me; - return 301 http://madenear.me$request_uri; -} +map $host $madenearme_name { + hostnames; + default madenearme; + cestemballepresdechezvous.fr cestemballepresdechezvous; + madenear.me.uk madenearme-uk; +} server { - #listen 80 default_server; listen 80; - #listen [::]:80 default_server; listen [::]:80; - server_name madenear.me; + server_name madenear.me cestemballepresdechezvous.fr madenear.me.uk; - # SSL configuration - # - # listen 443 ssl default_server; - # listen [::]:443 ssl default_server; - # - # Self signed certs generated by the ssl-cert package - # Don't use them in a production server! - # - # include snippets/snakeoil.conf; - - listen 443 ssl http2; - listen [::]:443 ssl http2; - include snippets/ssl.madenear.me; - include snippets/ssl-params.conf; - - root /srv/off/html; - - access_log /srv/off/logs/nginx.madenearme.access.log; - error_log /srv/off/logs/nginx.madenearme.error.log; + access_log /var/log/nginx/nginx.madenearme.access.log proxied_requests; + error_log /var/log/nginx/nginx.madenearme.error.log; gzip on; gzip_min_length 1000; + include /etc/nginx/snippets/expires-no-json-xml.conf; + + root /srv/off/html; # Add index.php to the list if you are using PHP index index.html index.htm index.nginx-debian.html; @@ -68,7 +36,7 @@ server { location ~ ^/(favicon.ico) { # First attempt to serve request as file, then # as directory, then fall back to displaying a 404. - try_files $uri /images/misc/madenearme.16x16.png; + try_files $uri /images/misc/$madenearme_name.16x16.png; } @@ -83,22 +51,7 @@ server { } location / { - try_files $uri /madenearme.html; + try_files $uri /data/$madenearme_name.html; } - location /cgi/ { - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_pass http://127.0.0.1:8001; - } - - # deny access to .htaccess files, if Apache's document root - # concurs with nginx's one - # - #location ~ /\.ht { - # deny all; - #} - - include /etc/nginx/expires-no-json-xml.conf; } diff --git a/conf/nginx/sites-available/madenearme-uk b/conf/nginx/sites-available/madenearme-uk deleted file mode 100644 index 9ad3975f2c068..0000000000000 --- a/conf/nginx/sites-available/madenearme-uk +++ /dev/null @@ -1,104 +0,0 @@ -## -# You should look at the following URL's in order to grasp a solid understanding -# of Nginx configuration files in order to fully unleash the power of Nginx. -# http://wiki.nginx.org/Pitfalls -# http://wiki.nginx.org/QuickStart -# http://wiki.nginx.org/Configuration -# -# Generally, you will want to move this file somewhere, and start with a clean -# file but keep this around for reference. Or just disable in sites-enabled. -# -# Please see /usr/share/doc/nginx-doc/examples/ for more detailed examples. -## - -# Default server configuration -# - -server { - listen 80; - listen [::]:80; - server_name madenearme.uk www.madenearme.uk www.madenear.me.uk; - return 301 http://madenear.me.uk$request_uri; -} - - -server { - #listen 80 default_server; - listen 80; - #listen [::]:80 default_server; - listen [::]:80; - - server_name madenear.me.uk; - - # SSL configuration - # - # listen 443 ssl default_server; - # listen [::]:443 ssl default_server; - # - # Self signed certs generated by the ssl-cert package - # Don't use them in a production server! - # - # include snippets/snakeoil.conf; - - listen 443 ssl http2; - listen [::]:443 ssl http2; - include snippets/ssl.madenear.me.uk; - include snippets/ssl-params.conf; - - root /srv/off/html; - - access_log /srv/off/logs/nginx.madenearme-uk.access.log; - error_log /srv/off/logs/nginx.madenearme-uk.error.log; - - gzip on; - gzip_min_length 1000; - - - # Add index.php to the list if you are using PHP - index index.html index.htm index.nginx-debian.html; - - location ~* \.(eot|ttf|woff|woff2)$ { - add_header Access-Control-Allow-Origin *; - } - - location ~ ^/images/products/ { - add_header Link "; rel='license'; title='CC-BY-SA 3.0'"; - } - - location ~ ^/(favicon.ico) { - # First attempt to serve request as file, then - # as directory, then fall back to displaying a 404. - try_files $uri /images/misc/madenearme-uk.16x16.png; - } - - - location ~ ^/(.well-known|images|js|rss|data|files|resources|foundation)/ { - # First attempt to serve request as file, then - # as directory, then fall back to displaying a 404. - try_files $uri $uri/ =404; - } - - location = /robots.txt { - try_files $uri $uri/ =404; - } - - location / { - try_files $uri /madenearme-uk.html; - } - - location /cgi/ { - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_pass http://127.0.0.1:8001; - } - - # deny access to .htaccess files, if Apache's document root - # concurs with nginx's one - # - #location ~ /\.ht { - # deny all; - #} - - include /etc/nginx/expires-no-json-xml.conf; -} diff --git a/conf/nginx/sites-available/off b/conf/nginx/sites-available/off index ccbcf53135e7a..679c07507849a 100644 --- a/conf/nginx/sites-available/off +++ b/conf/nginx/sites-available/off @@ -1,119 +1,54 @@ +# Default server configuration - nginx_status # -# You should look at the following URL's in order to grasp a solid understanding -# of Nginx configuration files in order to fully unleash the power of Nginx. -# http://wiki.nginx.org/Pitfalls -# http://wiki.nginx.org/QuickStart -# http://wiki.nginx.org/Configuration -# -# Generally, you will want to move this file somewhere, and start with a clean -# file but keep this around for reference. Or just disable in sites-enabled. -# -# Please see /usr/share/doc/nginx-doc/examples/ for more detailed examples. -## - -# Default server configuration -# - -server { - listen 80; - listen [::]:80; - # Disabled as we don't want to redirect POST API queries - # as they would not be resent with their body. - server_name disabled-openfoodfacts.org *.disabled-openfoodfacts.org; - # Redirect all HTTP links to the matching HTTPS page - - return 301 https://$host$request_uri; -} - server { listen 80 default_server; listen [::]:80 default_server; server_name _; - # nginx_status configuration, need for Munin - location /nginx_status { - stub_status on; - access_log off; - allow all; - } - - # return 301 https://world.openfoodfacts.org; -} - - -server { - listen 443 ssl http2 default_server; - listen [::]:443 ssl http2 default_server; - server_name _; - - include snippets/ssl.openfoodfacts.org; - include snippets/ssl-params.conf; - - return 404; + # nginx_status configuration, need for Munin + location /nginx_status { + stub_status on; + access_log off; + allow all; + } } - server { - client_body_timeout 120s; - client_header_timeout 120s; - listen 80; listen [::]:80; # Product Opener needs a root domain + a wildcard for all subdomains server_name openfoodfacts.org *.openfoodfacts.org; - # SSL configuration - # - - listen 443 ssl http2; - listen [::]:443 ssl http2; - - include snippets/ssl.openfoodfacts.org; - include snippets/ssl-params.conf; - root /srv/off/html; - access_log /srv/off/logs/nginx.access2.log combined buffer=256K flush=1s; - error_log /srv/off/logs/nginx.error2.log; - - # some redirection for specific subdomains - include snippets/off.domain-redirects.include; - - # Redirect GET requests to https. POST requests will be transformed - # to GET by most browsers when redirected, and it breaks apps that - # use the API through http. + # enable large uploads + client_max_body_size 20M; + client_body_timeout 120s; + client_header_timeout 120s; - if ($scheme = http) { - set $test "A"; - } - if ($request_uri !~ "/api/") { - set $test "${test}B"; - } - if ($request_method = GET) { - set $test "${test}C"; - } - if ($test = ABC) { - return 301 https://$host$request_uri; - } + # logs location + access_log /var/log/nginx/off-access.log proxied_requests buffer=256K flush=1s; + error_log /var/log/nginx/off-error.log; + # some redirection for specific subdomains + include snippets/off.domain-redirects.include; gzip on; gzip_min_length 1000; + gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript text/csv; + + index index.html index.htm index.nginx-debian.html; location /data/ { - include snippets/off.cors-headers.include; - include snippets/ssl-headers.conf; + include snippets/off.cors-headers.include; # First attempt to serve request as file, then # as directory, then fall back to displaying a 404. try_files $uri $uri/ =404; } - # Add index.php to the list if you are using PHP - index index.html index.htm index.nginx-debian.html; - - include /etc/nginx/expires-no-json-xml.conf; # 2018-06-18 Moved to the end because of CORS issue with top_translators.csv + include /etc/nginx/snippets/expires-no-json-xml.conf; # 2018-06-18 Moved to the end because of CORS issue with top_translators.csv location ~ ^/images/products/ { include snippets/off.cors-headers.include; @@ -126,12 +61,12 @@ server { if ($http_referer ~* (jobothoniel.com) ) { return 403; } # blocked since 2021-07-13 # the app requests /1.json to get the product count... - # the commented code below is to serve a static copy + # the commented code below is to serve a static copy # if there is a spike of installs - location ~ ^/1.json$ { - root /srv/off/html/static; - try_files /1.json = 404; - } + location ~ ^/1.json$ { + root /srv/off/html/static; + try_files /1.json = 404; + } location ~ ^/(favicon.ico) { # First attempt to serve request as file, then @@ -141,28 +76,44 @@ server { # Static files are served directly by NGINX - location ~ ^/(.well-known|images|fonts|css|js|rss|files|resources|foundation|bower_components)/ { - include snippets/off.cors-headers.include; + location ~ ^/(favicon.ico) { # First attempt to serve request as file, then # as directory, then fall back to displaying a 404. + try_files $uri $uri/ =404; + } + + # Static files are served directly by NGINX + location ~ ^/(.well-known|files)/ { + include snippets/off.cors-headers.include; + # First attempt to serve request from resource, then as file, + # then as directory, then fall back to displaying a 404. + try_files resources/$uri $uri $uri/ =404; + gzip_static always; + gunzip on; + } + location ~ ^/(images|fonts|css|js|rss|foundation|bower_components)/ { + include snippets/off.cors-headers.include; + # First attempt to serve as file, + # then as directory, then fall back to displaying a 404. + try_files $uri $uri/ =404; gzip_static always; gunzip on; } - # Redirect to the change password form + # Redirect to the change password form location = /.well-known/change-password { return 307 https://$host/cgi/change_password.pl; } - # GoogleAssociationService made 2500 requests/min to assetlinks.json - # and much less when caching headers are sent - location = /.well-known/assetlinks.json { - include snippets/off.cors-headers.include; - expires 1d; - try_files $uri $uri/ =404; - } + # GoogleAssociationService made 2500 requests/min to assetlinks.json + # and much less when caching headers are sent + location = /.well-known/assetlinks.json { + include snippets/off.cors-headers.include; + expires 1d; + try_files $uri $uri/ =404; + } - include snippets/off.locations-redirects.include; + include snippets/off.locations-redirects.include; # Dynamically generated files and CGI scripts are passed # to the Apache + mod_perl server running on a different @@ -170,25 +121,20 @@ server { location / { proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + # recursive hosts as we are proxying behind a proxy + set_real_ip_from 10.0.0.0/8; + real_ip_recursive on; - proxy_pass http://127.0.0.1:8001/cgi/display.pl?; + proxy_pass http://127.0.0.1:8004/cgi/display.pl?; } location /cgi/ { proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_pass http://127.0.0.1:8001; - } - - # deny access to .htaccess files, if Apache's document root - # concurs with nginx's one - # - #location ~ /\.ht { - # deny all; - #} + # recursive hosts as we are proxying behind a proxy + set_real_ip_from 10.0.0.0/8; + real_ip_recursive on; + proxy_pass http://127.0.0.1:8004; + } } diff --git a/conf/nginx/sites-available/off-pro b/conf/nginx/sites-available/off-pro index 13e679fb00dc3..f1bc42a261a63 100644 --- a/conf/nginx/sites-available/off-pro +++ b/conf/nginx/sites-available/off-pro @@ -1,155 +1,63 @@ +# Default server configuration - nginx_status # -# You should look at the following URL's in order to grasp a solid understanding -# of Nginx configuration files in order to fully unleash the power of Nginx. -# http://wiki.nginx.org/Pitfalls -# http://wiki.nginx.org/QuickStart -# http://wiki.nginx.org/Configuration -# -# Generally, you will want to move this file somewhere, and start with a clean -# file but keep this around for reference. Or just disable in sites-enabled. -# -# Please see /usr/share/doc/nginx-doc/examples/ for more detailed examples. -## - -# Default server configuration -# - -server { - listen 80; - listen [::]:80; - # Disabled as we don't want to redirect POST API queries - # as they would not be resent with their body. - server_name disabled-pro.openfoodfacts.org *.disabled-pro.openfoodfacts.org; - # Redirect all HTTP links to the matching HTTPS page - return 301 https://$host$request_uri; -} - server { - #listen 80 default_server; - listen 80 ; - #listen [::]:80 default_server; - listen [::]:80 ; - server_name pro.openfoodfacts.org; - return 301 http://world.pro.openfoodfacts.org$request_uri; + listen 80 default_server; + listen [::]:80 default_server; + server_name _; + + # nginx_status configuration, need for Munin + location /nginx_status { + stub_status on; + access_log off; + allow all; + } } - server { - # Huge files can be uploaded to the Producers platform - client_body_timeout 1200s; - client_header_timeout 1200s; - - client_max_body_size 400M; - proxy_connect_timeout 1200; - proxy_send_timeout 1200; - proxy_read_timeout 1200; - send_timeout 1200; - - #listen 80 default_server; listen 80; - #listen [::]:80 default_server; listen [::]:80; # Product Opener needs a root domain + a wildcard for all subdomains server_name *.pro.openfoodfacts.org; - #auth_basic "login and password: off"; - #auth_basic_user_file /etc/nginx/.htpasswd; - - # SSL configuration - # - # listen 443 ssl default_server; - # listen [::]:443 ssl default_server; - # - # Self signed certs generated by the ssl-cert package - # Don't use them in a production server! - # - # include snippets/snakeoil.conf; - - # 13/09/2016: got error "nginx: [emerg] invalid parameter "http2" " - #listen 443 ssl http2 default_server; - listen 443 ssl http2; - #listen [::]:443 ssl http2 default_server; - listen [::]:443 ssl http2; - - include snippets/ssl.pro.openfoodfacts.org; - include snippets/ssl-params.conf; - root /srv/off-pro/html; - access_log /srv/off-pro/logs/nginx.off.access2.log; - error_log /srv/off-pro/logs/nginx.off.error2.log; - - # Redirect GET requests to https. POST requests will be transformed - # to GET by most browsers when redirected, and it breaks apps that - # use the API through http. + # Huge files can be uploaded to the Producers platform + client_max_body_size 400M; + client_body_timeout 1200s; + client_header_timeout 1200s; - if ($scheme = http) { - set $test "A"; - } - if ($request_uri !~ "/api/") { - set $test "${test}B"; - } - if ($request_method = GET) { - set $test "${test}C"; - } - if ($test = ABC) { -# return 301 https://$host$request_uri; - } + proxy_connect_timeout 1200; + proxy_send_timeout 1200; + proxy_read_timeout 1200; + send_timeout 1200; + # logs location + access_log /var/log/nginx/off-access.log proxied_requests; + error_log /var/log/nginx/off-error.log; gzip on; gzip_min_length 1000; + gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript text/csv; + + index index.html index.htm index.nginx-debian.html; location /data/ { - if ($request_method = 'OPTIONS') { - add_header Access-Control-Allow-Origin *; - add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS'; - # - # Custom headers and headers various browsers *should* be OK with but aren't - # - add_header Access-Control-Allow-Headers 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,If-None-Match'; - # - # Tell client that this pre-flight info is valid for 20 days - # - add_header Access-Control-Max-Age 1728000; - add_header Content-Type 'text/plain; charset=utf-8'; - add_header Content-Length 0; - return 204; - } - if ($request_method = 'POST') { - add_header Access-Control-Allow-Origin '*'; - add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS'; - add_header Access-Control-Allow-Header 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,If-None-Match'; - add_header Access-Control-Expose-Headers 'Content-Length,Content-Range'; - } - if ($request_method = 'GET') { - add_header Access-Control-Allow-Origin '*'; - add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS'; - add_header Access-Control-Allow-Headers 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,If-None-Match'; - add_header Access-Control-Expose-Headers 'Content-Length,Content-Range'; - } - include snippets/ssl-headers.conf; + include snippets/off.cors-headers.include; # First attempt to serve request as file, then # as directory, then fall back to displaying a 404. try_files $uri $uri/ =404; -} - - # Add index.php to the list if you are using PHP - index index.html index.htm index.nginx-debian.html; - - include /etc/nginx/expires-no-json-xml.conf; # 2018-06-18 Moved to the end because of CORS issue with top_translators.csv - - location ~* \.(eot|ttf|woff|woff2)$ { - add_header Access-Control-Expose-Headers 'Content-Length,Content-Range'; - add_header Access-Control-Allow-Origin '*'; - expires 1d; - try_files $uri $uri/ =404; } + include /etc/nginx/snippets/expires-no-json-xml.conf; # 2018-06-18 Moved to the end because of CORS issue with top_translators.csv + location ~ ^/images/products/ { - add_header Link "; rel='license; title='CC-BY-SA 3.0'"; + include snippets/off.cors-headers.include; + add_header Link "; rel='license'; title='CC-BY-SA 3.0'"; + # optimize gzip compressed content (like OCR .json stored next to .jpg files) + gzip_static always; + gunzip on; } location ~ ^/(favicon.ico) { @@ -159,13 +67,21 @@ server { } # Static files are served directly by NGINX - - location ~ ^/(.well-known|fonts|images|js|css|rss|data|files|resources)/ { - # First attempt to serve request as file, then - # as directory, then fall back to displaying a 404. - add_header Access-Control-Expose-Headers 'Content-Length,Content-Range'; - add_header Access-Control-Allow-Origin '*'; + location ~ ^/(.well-known|files)/ { + include snippets/off.cors-headers.include; + # First attempt to serve request from resource, then as file, + # then as directory, then fall back to displaying a 404. + try_files resources/$uri $uri $uri/ =404; + gzip_static always; + gunzip on; + } + location ~ ^/(images|fonts|css|js|rss|foundation|bower_components)/ { + include snippets/off.cors-headers.include; + # First attempt to serve as file, + # then as directory, then fall back to displaying a 404. try_files $uri $uri/ =404; + gzip_static always; + gunzip on; } # Dynamically generated files and CGI scripts are passed @@ -174,25 +90,21 @@ server { location / { proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + # recursive hosts as we are proxying behind a proxy + set_real_ip_from 10.0.0.0/8; + real_ip_recursive on; - proxy_pass http://127.0.0.1:8705/cgi/display.pl?; + proxy_pass http://127.0.0.1:8014/cgi/display.pl?; } location /cgi/ { proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_pass http://127.0.0.1:8705; - } + # recursive hosts as we are proxying behind a proxy + set_real_ip_from 10.0.0.0/8; + real_ip_recursive on; - # deny access to .htaccess files, if Apache's document root - # concurs with nginx's one - # - #location ~ /\.ht { - # deny all; - #} + proxy_pass http://127.0.0.1:8014; + } } diff --git a/conf/nginx/expires-no-json-xml.conf b/conf/nginx/snippets/expires-no-json-xml.conf similarity index 100% rename from conf/nginx/expires-no-json-xml.conf rename to conf/nginx/snippets/expires-no-json-xml.conf diff --git a/conf/nginx/snippets/ssl-params-opff.conf b/conf/nginx/snippets/ssl-params-opff.conf deleted file mode 100644 index 33baa39072781..0000000000000 --- a/conf/nginx/snippets/ssl-params-opff.conf +++ /dev/null @@ -1,22 +0,0 @@ -# from https://cipherli.st/ -# and https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html - -ssl_protocols TLSv1 TLSv1.1 TLSv1.2; -ssl_prefer_server_ciphers on; -ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH"; -ssl_ecdh_curve secp384r1; -#ssl_session_cache shared:SSL:10m; -ssl_session_tickets off; -ssl_stapling on; -ssl_stapling_verify on; -resolver 8.8.8.8 8.8.4.4 valid=300s; -resolver_timeout 5s; -# Disable preloading HSTS for now. You can use the commented out header line that includes -# the "preload" directive if you understand the implications. -#add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload"; -add_header Strict-Transport-Security "max-age=63072000; includeSubdomains"; -# need frame for OPFF svg embed -#add_header X-Frame-Options DENY; -add_header X-Content-Type-Options nosniff; - -ssl_dhparam /etc/ssl/certs/dhparam.pem; diff --git a/conf/nginx/snippets/ssl-params.conf b/conf/nginx/snippets/ssl-params.conf deleted file mode 100644 index 7dc287a34b78c..0000000000000 --- a/conf/nginx/snippets/ssl-params.conf +++ /dev/null @@ -1,17 +0,0 @@ -# from https://cipherli.st/ -# and https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html - -ssl_protocols TLSv1 TLSv1.1 TLSv1.2; -ssl_prefer_server_ciphers on; -ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH"; -ssl_ecdh_curve secp384r1; -#ssl_session_cache shared:SSL:10m; -ssl_session_tickets off; -ssl_stapling on; -ssl_stapling_verify on; -resolver 8.8.8.8 8.8.4.4 valid=300s; -resolver_timeout 5s; - -include snippets/ssl-headers.conf; - -ssl_dhparam /etc/ssl/certs/dhparam.pem; diff --git a/conf/nginx/snippets/ssl.cestemballepresdechezvous.fr b/conf/nginx/snippets/ssl.cestemballepresdechezvous.fr deleted file mode 100644 index 1a4f44d5104b3..0000000000000 --- a/conf/nginx/snippets/ssl.cestemballepresdechezvous.fr +++ /dev/null @@ -1,2 +0,0 @@ -ssl_certificate /etc/letsencrypt/live/cestemballepresdechezvous.fr/fullchain.pem; -ssl_certificate_key /etc/letsencrypt/live/cestemballepresdechezvous.fr/privkey.pem; diff --git a/conf/nginx/snippets/ssl.madenear.me b/conf/nginx/snippets/ssl.madenear.me deleted file mode 100644 index 8246cc507f95f..0000000000000 --- a/conf/nginx/snippets/ssl.madenear.me +++ /dev/null @@ -1,2 +0,0 @@ -ssl_certificate /etc/letsencrypt/live/madenear.me/fullchain.pem; -ssl_certificate_key /etc/letsencrypt/live/madenear.me/privkey.pem; diff --git a/conf/nginx/snippets/ssl.madenear.me.uk b/conf/nginx/snippets/ssl.madenear.me.uk deleted file mode 100644 index 3d17cf01d9d43..0000000000000 --- a/conf/nginx/snippets/ssl.madenear.me.uk +++ /dev/null @@ -1,2 +0,0 @@ -ssl_certificate /etc/letsencrypt/live/madenear.me.uk/fullchain.pem; -ssl_certificate_key /etc/letsencrypt/live/madenear.me.uk/privkey.pem; diff --git a/conf/nginx/snippets/ssl.openbeautyfacts.org b/conf/nginx/snippets/ssl.openbeautyfacts.org deleted file mode 100644 index 892dbbfbf5d98..0000000000000 --- a/conf/nginx/snippets/ssl.openbeautyfacts.org +++ /dev/null @@ -1,4 +0,0 @@ -ssl_certificate /etc/nginx/acme.sh/live/openbeautyfacts.org/fullchain.pem; -ssl_certificate_key /etc/nginx/acme.sh/live/openbeautyfacts.org/key.pem; -ssl_trusted_certificate /etc/nginx/acme.sh/live/openbeautyfacts.org/ca.pem; - diff --git a/conf/nginx/snippets/ssl.openbeautyfacts.org.2017 b/conf/nginx/snippets/ssl.openbeautyfacts.org.2017 deleted file mode 100644 index 23954d31c7b62..0000000000000 --- a/conf/nginx/snippets/ssl.openbeautyfacts.org.2017 +++ /dev/null @@ -1,3 +0,0 @@ -#ssl_certificate /home/obf/ssl/openbeautyfacts.org.crt; -ssl_certificate /home/obf/ssl/openbeautyfacts.org-intermediate_domain_ca.crt; -ssl_certificate_key /home/obf/ssl/openbeautyfacts.org.key; diff --git a/conf/nginx/snippets/ssl.openfoodfacts.org b/conf/nginx/snippets/ssl.openfoodfacts.org deleted file mode 100644 index 1d2ca48f514c0..0000000000000 --- a/conf/nginx/snippets/ssl.openfoodfacts.org +++ /dev/null @@ -1,8 +0,0 @@ -# commented out manual certificate -ssl_certificate /etc/nginx/acme.sh/live/openfoodfacts.org/fullchain.pem; -#ssl_certificate /home/acme-off/.acme.sh/openfoodfacts.org/fullchain.cer; -ssl_certificate_key /etc/nginx/acme.sh/live/openfoodfacts.org/key.pem; -#ssl_certificate_key /home/acme-off/.acme.sh/openfoodfacts.org/openfoodfacts.org.key; -ssl_trusted_certificate /etc/nginx/acme.sh/live/openfoodfacts.org/ca.pem; -#ssl_trusted_certificate /home/acme-off/.acme.sh/openfoodfacts.org/ca.cer; - diff --git a/conf/nginx/snippets/ssl.openfoodfacts.org.2016 b/conf/nginx/snippets/ssl.openfoodfacts.org.2016 deleted file mode 100644 index 5247da6b693a4..0000000000000 --- a/conf/nginx/snippets/ssl.openfoodfacts.org.2016 +++ /dev/null @@ -1,3 +0,0 @@ -#ssl_certificate /home/off/ssl/openfoodfacts.org.crt; -ssl_certificate /home/off/ssl/openfoodfacts.org-intermediate_domain_ca.crt; -ssl_certificate_key /home/off/ssl/openfoodfacts.org.key; diff --git a/conf/nginx/snippets/ssl.openpetfoodfacts.org b/conf/nginx/snippets/ssl.openpetfoodfacts.org deleted file mode 100644 index 8f9bd61d8ba17..0000000000000 --- a/conf/nginx/snippets/ssl.openpetfoodfacts.org +++ /dev/null @@ -1,4 +0,0 @@ -ssl_certificate /etc/nginx/acme.sh/live/openpetfoodfacts.org/fullchain.pem; -ssl_certificate_key /etc/nginx/acme.sh/live/openpetfoodfacts.org/key.pem; -ssl_trusted_certificate /etc/nginx/acme.sh/live/openpetfoodfacts.org/ca.pem; - diff --git a/conf/nginx/snippets/ssl.openproductsfacts.org b/conf/nginx/snippets/ssl.openproductsfacts.org deleted file mode 100644 index 1b912d0f54e47..0000000000000 --- a/conf/nginx/snippets/ssl.openproductsfacts.org +++ /dev/null @@ -1,4 +0,0 @@ -ssl_certificate /etc/nginx/acme.sh/live/openproductsfacts.org/fullchain.pem; -ssl_certificate_key /etc/nginx/acme.sh/live/openproductsfacts.org/key.pem; -ssl_trusted_certificate /etc/nginx/acme.sh/live/openproductsfacts.org/ca.pem; - diff --git a/conf/off-log.conf b/conf/off-log.conf new file mode 100644 index 0000000000000..7557465cd638d --- /dev/null +++ b/conf/off-log.conf @@ -0,0 +1,19 @@ +log4perl.rootLogger=ERROR, LOGFILE +log4perl.logger.mongodb=INFO, MONGODB_LOGFILE + +log4perl.PatternLayout.cspec.S = sub { my $context = Log::Log4perl::MDC->get_context; use Data::Dumper (); local $Data::Dumper::Indent = 0; local $Data::Dumper::Terse = 1; local $Data::Dumper::Sortkeys = 1; local $Data::Dumper::Quotekeys = 0; local $Data::Dumper::Deparse = 1; my $str = Data::Dumper::Dumper($context); $str =~ s/[\n\r]/ /g; return $str; } + +log4perl.appender.LOGFILE=Log::Log4perl::Appender::File +log4perl.appender.LOGFILE.filename=/srv/off/logs/log4perl.log +log4perl.appender.LOGFILE.mode=append + +log4perl.appender.LOGFILE.layout=PatternLayout +log4perl.appender.LOGFILE.layout.ConversionPattern=[%r] %F %L %c %S %m{chomp}%n + +log4perl.appender.MONGODB_LOGFILE=Log::Log4perl::Appender::File +log4perl.appender.MONGODB_LOGFILE.filename=/srv/off/logs/mongodb_log4perl.log +log4perl.appender.MONGODB_LOGFILE.mode=append + +log4perl.appender.MONGODB_LOGFILE.layout=PatternLayout +log4perl.appender.MONGODB_LOGFILE.layout.ConversionPattern=[%r] %F %L %c %S %m{chomp}%n + diff --git a/conf/off-minion_log.conf b/conf/off-minion_log.conf new file mode 100644 index 0000000000000..e0f03db4090e0 --- /dev/null +++ b/conf/off-minion_log.conf @@ -0,0 +1,10 @@ +log4perl.rootLogger=DEBUG, LOGFILE + +log4perl.PatternLayout.cspec.S = sub { my $context = Log::Log4perl::MDC->get_context; use Data::Dumper (); local $Data::Dumper::Indent = 0; local $Data::Dumper::Terse = 1; local $Data::Dumper::Sortkeys = 1; local $Data::Dumper::Quotekeys = 0; local $Data::Dumper::Deparse = 1; my $str = Data::Dumper::Dumper($context); $str =~ s/[\n\r]/ /g; return $str; } + +log4perl.appender.LOGFILE=Log::Log4perl::Appender::File +log4perl.appender.LOGFILE.filename=/srv/off/logs/minion_log4perl.log +log4perl.appender.LOGFILE.mode=append + +log4perl.appender.LOGFILE.layout=PatternLayout +log4perl.appender.LOGFILE.layout.ConversionPattern=[%r] %F %L %c %S %m{chomp}%n diff --git a/conf/off-pro-log.conf b/conf/off-pro-log.conf new file mode 100644 index 0000000000000..f0965f52250af --- /dev/null +++ b/conf/off-pro-log.conf @@ -0,0 +1,10 @@ +log4perl.rootLogger=DEBUG, LOGFILE + +log4perl.PatternLayout.cspec.S = sub { my $context = Log::Log4perl::MDC->get_context; use Data::Dumper (); local $Data::Dumper::Indent = 0; local $Data::Dumper::Terse = 1; local $Data::Dumper::Sortkeys = 1; local $Data::Dumper::Quotekeys = 0; local $Data::Dumper::Deparse = 1; my $str = Data::Dumper::Dumper($context); $str =~ s/[\n\r]/ /g; return $str; } + +log4perl.appender.LOGFILE=Log::Log4perl::Appender::File +log4perl.appender.LOGFILE.filename=/mnt/off-pro/logs/off-pro/log4perl.log +log4perl.appender.LOGFILE.mode=append + +log4perl.appender.LOGFILE.layout=PatternLayout +log4perl.appender.LOGFILE.layout.ConversionPattern=[%r] %F %L %c %S %m{chomp}%n diff --git a/conf/off-pro-minion_log.conf b/conf/off-pro-minion_log.conf new file mode 100644 index 0000000000000..e0a1319c9717f --- /dev/null +++ b/conf/off-pro-minion_log.conf @@ -0,0 +1,10 @@ +log4perl.rootLogger=DEBUG, LOGFILE + +log4perl.PatternLayout.cspec.S = sub { my $context = Log::Log4perl::MDC->get_context; use Data::Dumper (); local $Data::Dumper::Indent = 0; local $Data::Dumper::Terse = 1; local $Data::Dumper::Sortkeys = 1; local $Data::Dumper::Quotekeys = 0; local $Data::Dumper::Deparse = 1; my $str = Data::Dumper::Dumper($context); $str =~ s/[\n\r]/ /g; return $str; } + +log4perl.appender.LOGFILE=Log::Log4perl::Appender::File +log4perl.appender.LOGFILE.filename=/mnt/off-pro/logs/off-pro/minion_log4perl.log +log4perl.appender.LOGFILE.mode=append + +log4perl.appender.LOGFILE.layout=PatternLayout +log4perl.appender.LOGFILE.layout.ConversionPattern=[%r] %F %L %c %S %m{chomp}%n diff --git a/conf/systemd/apache2.service.d/override.conf b/conf/systemd/apache2.service.d/override.conf new file mode 100644 index 0000000000000..0eee2bd2dba97 --- /dev/null +++ b/conf/systemd/apache2.service.d/override.conf @@ -0,0 +1,5 @@ +[Unit] +OnFailure=email-failures@apache2-%l.service +# we need time to reboot apache because we load a lot of things… +JobTimeoutSec=600 +JobRunningTimeoutSec=600 diff --git a/conf/systemd/cloud_vision_ocr@.service b/conf/systemd/cloud_vision_ocr@.service new file mode 100644 index 0000000000000..8b6d884d5d06a --- /dev/null +++ b/conf/systemd/cloud_vision_ocr@.service @@ -0,0 +1,17 @@ +# service instance name "%i" is off or off-pro +[Unit] +Description=run cloud vision OCR on new images for %i +# __ will be replaced by @ in email-failures@.service +OnFailure=email-failures@cloud_vision_ocr__%i.service + +[Service] +Type=simple +User=off +WorkingDirectory=/srv/%i/ +Environment="PERL5LIB=/srv/%i/lib" +ExecStart=/srv/%i/scripts/run_cloud_vision_ocr.pl /srv/%i/new_images +KillMode=process + +[Install] +WantedBy=multi-user.target + diff --git a/conf/systemd/email-failures@.service b/conf/systemd/email-failures@.service new file mode 100644 index 0000000000000..08d02af282e60 --- /dev/null +++ b/conf/systemd/email-failures@.service @@ -0,0 +1,9 @@ +[Unit] +Description=%i failure email notification + +[Service] +Type=oneshot +# replace __ by @ in instance name to be able to call status on a specific instance +# then use mailx to email status +ExecStart=/bin/bash -c 'INSTANCE_NAME=%i; SERVICE_NAME=$${INSTANCE_NAME//__/@}; /bin/systemctl status $$SERVICE_NAME | /usr/bin/mailx -s "[$$SERVICE_NAME] failure notification" root' + diff --git a/conf/systemd/gen_feeds@.service b/conf/systemd/gen_feeds@.service new file mode 100644 index 0000000000000..f9422a112ed87 --- /dev/null +++ b/conf/systemd/gen_feeds@.service @@ -0,0 +1,13 @@ +[Unit] +Description=Generates regular %i feeds +# __ will be replaced by @ in email-failures@.service +OnFailure=email-failures@gen_feeds__%i.service + +[Service] +Type=oneshot +# service instance name "%i" is off / obf / opff / opf +Environment=PERL5LIB=/srv/%i/lib/:/usr/local/share/perl/5.32.1/:/usr/lib/perl5 +WorkingDirectory=/srv/%i +ExecStart=/srv/%i/scripts/gen_feeds_%i.sh + + diff --git a/conf/systemd/gen_feeds@.timer b/conf/systemd/gen_feeds@.timer new file mode 100644 index 0000000000000..9c18833731af6 --- /dev/null +++ b/conf/systemd/gen_feeds@.timer @@ -0,0 +1,11 @@ +[Unit] +Description=Generate %i feeds + +[Timer] +# every two hours +OnCalendar=0/2:35 +# service instance name "%i" is off / obf / opff / opf +Unit=gen_feeds@%i.service + +[Install] +WantedBy=multi-user.target diff --git a/conf/systemd/gen_feeds_daily@.service b/conf/systemd/gen_feeds_daily@.service new file mode 100644 index 0000000000000..d3dfb94abbaed --- /dev/null +++ b/conf/systemd/gen_feeds_daily@.service @@ -0,0 +1,13 @@ +[Unit] +Description=Generates %i daily feeds +# __ will be replaced by @ in email-failures@.service +OnFailure=email-failures@gen_feeds_daily__%i.service + +[Service] +Type=oneshot +# service instance name "%i" is off / obf / opff / opf +Environment=PERL5LIB=/srv/%i/lib/:/usr/local/share/perl/5.32.1/:/usr/lib/perl5 +WorkingDirectory=/srv/%i +ExecStart=/srv/%i/scripts/gen_feeds_daily_%i.sh + + diff --git a/conf/systemd/gen_feeds_daily@.timer b/conf/systemd/gen_feeds_daily@.timer new file mode 100644 index 0000000000000..fd3428d245fea --- /dev/null +++ b/conf/systemd/gen_feeds_daily@.timer @@ -0,0 +1,11 @@ +[Unit] +Description=Generate %i daily feeds + +[Timer] +# every day +OnCalendar=2:15 +# service instance name "%i" is off / obf / opff / opf +Unit=gen_feeds_daily@%i.service + +[Install] +WantedBy=multi-user.target diff --git a/conf/systemd/madenearme_gen.service b/conf/systemd/madenearme_gen.service new file mode 100644 index 0000000000000..e67ac95a6a7df --- /dev/null +++ b/conf/systemd/madenearme_gen.service @@ -0,0 +1,12 @@ +[Unit] +Description=Generates madenearme website using off data +OnFailure=email-failures@madenearme_gen__%i.service + +[Service] +Type=oneshot +# service instance name "%i" is off / obf / opff / opf +Environment=PERL5LIB=/srv/%i/lib/:/usr/local/share/perl/5.32.1/:/usr/lib/perl5 +WorkingDirectory=/srv/%i +ExecStart=/srv/%i/scripts/gen_feeds_daily_%i.sh + + diff --git a/conf/systemd/madenearme_gen.timer b/conf/systemd/madenearme_gen.timer new file mode 100644 index 0000000000000..5049ec3b55df6 --- /dev/null +++ b/conf/systemd/madenearme_gen.timer @@ -0,0 +1,11 @@ +[Unit] +Description=Generate madenearme sites for %i + +[Timer] +# once a week, on sunday +OnCalendar=Sun 2:15 +# service instance name "%i" is off / obf / opff / opf +Unit=madenearme_gen@%i.service + +[Install] +WantedBy=multi-user.target diff --git a/conf/systemd/minion@.service b/conf/systemd/minion@.service new file mode 100644 index 0000000000000..fbd45654b4a85 --- /dev/null +++ b/conf/systemd/minion@.service @@ -0,0 +1,18 @@ +# service instance name "%i" is off or off-pro +[Unit] +Description=%i minion workers +After=postgresql.service +# __ will be replaced by @ in email-failures@.service +OnFailure=email-failures@minion__%i.service + +[Service] +Type=simple +User=off +WorkingDirectory=/srv/%i +Environment="PERL5LIB=/srv/%i/lib" +ExecStart=/srv/%i/scripts/minion_producers.pl minion worker -m production +KillMode=process + +[Install] +WantedBy=multi-user.target + diff --git a/conf/systemd/nginx.service.d/override.conf b/conf/systemd/nginx.service.d/override.conf new file mode 100644 index 0000000000000..70e2acb32d5f2 --- /dev/null +++ b/conf/systemd/nginx.service.d/override.conf @@ -0,0 +1,2 @@ +[Unit] +OnFailure=email-failures@nginx-%l.service \ No newline at end of file diff --git a/conf/systemd/producers_import.service b/conf/systemd/producers_import.service new file mode 100644 index 0000000000000..e33afcb102076 --- /dev/null +++ b/conf/systemd/producers_import.service @@ -0,0 +1,13 @@ +[Unit] +Description=Generates %i daily feeds +# __ will be replaced by @ in email-failures@.service +OnFailure=email-failures@producers_import__%i.service + +[Service] +Type=oneshot +# service instance name "%i" is off / obf / opff / opf +Environment=PERL5LIB=/srv/%i/lib/:/usr/local/share/perl/5.32.1/:/usr/lib/perl5 +WorkingDirectory=/srv/%i +ExecStart=/srv/%i/scripts/imports/producers_imports.sh + + diff --git a/conf/systemd/producers_import.timer b/conf/systemd/producers_import.timer new file mode 100644 index 0000000000000..31ae34efa75c6 --- /dev/null +++ b/conf/systemd/producers_import.timer @@ -0,0 +1,11 @@ +[Unit] +Description=Import producers data for %i + +[Timer] +# every day +OnCalendar=9:15 +# service instance name "%i" is off / obf / opff / opf +Unit=producers_import@%i.service + +[Install] +WantedBy=multi-user.target diff --git a/conf/well-known/off-apple-app-site-association b/conf/well-known/off-apple-app-site-association new file mode 100644 index 0000000000000..b6f91381a2d18 --- /dev/null +++ b/conf/well-known/off-apple-app-site-association @@ -0,0 +1,10 @@ +{ + "applinks": { + "details": [ + { + "appID": "ZC9CYWD334.org.openfoodfacts.scanner", + "paths": ["*"] + } + ] + } +} diff --git a/conf/well-known/off-apple-developer-merchantid-domain-association b/conf/well-known/off-apple-developer-merchantid-domain-association new file mode 100644 index 0000000000000..2ff95c962810a --- /dev/null +++ b/conf/well-known/off-apple-developer-merchantid-domain-association @@ -0,0 +1 @@ +7B227073704964223A2239373943394538343346343131343044463144313834343232393232313734313034353044314339464446394437384337313531303944334643463542433731222C2276657273696F6E223A312C22637265617465644F6E223A313536363233343735303036312C227369676E6174757265223A22333038303036303932613836343838366637306430313037303261303830333038303032303130313331306633303064303630393630383634383031363530333034303230313035303033303830303630393261383634383836663730643031303730313030303061303830333038323033653333303832303338386130303330323031303230323038346333303431343935313964353433363330306130363038326138363438636533643034303330323330376133313265333032633036303335353034303330633235343137303730366336353230343137303730366336393633363137343639366636653230343936653734363536373732363137343639366636653230343334313230326432303437333333313236333032343036303335353034306230633164343137303730366336353230343336353732373436393636363936333631373436393666366532303431373537343638366637323639373437393331313333303131303630333535303430613063306134313730373036633635323034393665363332653331306233303039303630333535303430363133303235353533333031653137306433313339333033353331333833303331333333323335333735613137306433323334333033353331333633303331333333323335333735613330356633313235333032333036303335353034303330633163363536333633326437333664373032643632373236663662363537323264373336393637366535663535343333343264353035323466343433313134333031323036303335353034306230633062363934663533323035333739373337343635366437333331313333303131303630333535303430613063306134313730373036633635323034393665363332653331306233303039303630333535303430363133303235353533333035393330313330363037326138363438636533643032303130363038326138363438636533643033303130373033343230303034633231353737656465626436633762323231386636386464373039306131323138646337623062643666326332383364383436303935643934616634613534313162383334323065643831316633343037653833333331663163353463336637656233323230643662616435643465666634393238393839336537633066313361333832303231313330383230323064333030633036303335353164313330313031666630343032333030303330316630363033353531643233303431383330313638303134323366323439633434663933653465663237653663346636323836633366613262626664326534623330343530363038326230363031303530353037303130313034333933303337333033353036303832623036303130353035303733303031383632393638373437343730336132663266366636333733373032653631373037303663363532653633366636643266366636333733373033303334326436313730373036633635363136393633363133333330333233303832303131643036303335353164323030343832303131343330383230313130333038323031306330363039326138363438383666373633363430353031333038316665333038316333303630383262303630313035303530373032303233303831623630633831623335323635366336393631366536333635323036663665323037343638363937333230363336353732373436393636363936333631373436353230363237393230363136653739323037303631373237343739323036313733373337353664363537333230363136333633363537303734363136653633363532303666363632303734363836353230373436383635366532303631373037303663363936333631363236633635323037333734363136653634363137323634323037343635373236643733323036313665363432303633366636653634363937343639366636653733323036663636323037353733363532633230363336353732373436393636363936333631373436353230373036663663363936333739323036313665363432303633363537323734363936363639363336313734363936663665323037303732363136333734363936333635323037333734363137343635366436353665373437333265333033363036303832623036303130353035303730323031313632613638373437343730336132663266373737373737326536313730373036633635326536333666366432663633363537323734363936363639363336313734363536313735373436383666373236393734373932663330333430363033353531643166303432643330326233303239613032376130323538363233363837343734373033613266326636333732366332653631373037303663363532653633366636643266363137303730366336353631363936333631333332653633373236633330316430363033353531643065303431363034313439343537646236666435373438313836383938393736326637653537383530376537396235383234333030653036303335353164306630313031666630343034303330323037383033303066303630393261383634383836663736333634303631643034303230353030333030613036303832613836343863653364303430333032303334393030333034363032323130306265303935373166653731653165373335623535653561666163623463373266656234343566333031383532323263373235313030326236316562643666353530323231303064313862333530613564643664643665623137343630333562313165623263653837636661336536616636636264383338303839306463383263646461613633333038323032656533303832303237356130303330323031303230323038343936643266626633613938646139373330306130363038326138363438636533643034303330323330363733313162333031393036303335353034303330633132343137303730366336353230353236663666373432303433343132303264323034373333333132363330323430363033353530343062306331643431373037303663363532303433363537323734363936363639363336313734363936663665323034313735373436383666373236393734373933313133333031313036303335353034306130633061343137303730366336353230343936653633326533313062333030393036303335353034303631333032353535333330316531373064333133343330333533303336333233333334333633333330356131373064333233393330333533303336333233333334333633333330356133303761333132653330326330363033353530343033306332353431373037303663363532303431373037303663363936333631373436393666366532303439366537343635363737323631373436393666366532303433343132303264323034373333333132363330323430363033353530343062306331643431373037303663363532303433363537323734363936363639363336313734363936663665323034313735373436383666373236393734373933313133333031313036303335353034306130633061343137303730366336353230343936653633326533313062333030393036303335353034303631333032353535333330353933303133303630373261383634386365336430323031303630383261383634386365336430333031303730333432303030346630313731313834313964373634383564353161356532353831303737366538383061326566646537626165346465303864666334623933653133333536643536363562333561653232643039373736306432323465376262613038666437363137636538386362373662623636373062656338653832393834666635343435613338316637333038316634333034363036303832623036303130353035303730313031303433613330333833303336303630383262303630313035303530373330303138363261363837343734373033613266326636663633373337303265363137303730366336353265363336663664326636663633373337303330333432643631373037303663363537323666366637343633363136373333333031643036303335353164306530343136303431343233663234396334346639336534656632376536633466363238366333666132626266643265346233303066303630333535316431333031303166663034303533303033303130316666333031663036303335353164323330343138333031363830313462626230646561313538333338383961613438613939646562656264656261666461636232346162333033373036303335353164316630343330333032653330326361303261613032383836323636383734373437303361326632663633373236633265363137303730366336353265363336663664326636313730373036633635373236663666373436333631363733333265363337323663333030653036303335353164306630313031666630343034303330323031303633303130303630613261383634383836663736333634303630323065303430323035303033303061303630383261383634386365336430343033303230333637303033303634303233303361636637323833353131363939623138366662333563333536636136326266663431376564643930663735346461323865626566313963383135653432623738396638393866373962353939663938643534313064386639646539633266653032333033323264643534343231623061333035373736633564663333383362393036376664313737633263323136643936346663363732363938323132366635346638376137643162393963623962303938393231363130363939306630393932316430303030333138323031386233303832303138373032303130313330383138363330376133313265333032633036303335353034303330633235343137303730366336353230343137303730366336393633363137343639366636653230343936653734363536373732363137343639366636653230343334313230326432303437333333313236333032343036303335353034306230633164343137303730366336353230343336353732373436393636363936333631373436393666366532303431373537343638366637323639373437393331313333303131303630333535303430613063306134313730373036633635323034393665363332653331306233303039303630333535303430363133303235353533303230383463333034313439353139643534333633303064303630393630383634383031363530333034303230313035303061303831393533303138303630393261383634383836663730643031303930333331306230363039326138363438383666373064303130373031333031633036303932613836343838366637306430313039303533313066313730643331333933303338333133393331333733313332333333303561333032613036303932613836343838366637306430313039333433313164333031623330306430363039363038363438303136353033303430323031303530306131306130363038326138363438636533643034303330323330326630363039326138363438383666373064303130393034333132323034323062303731303365313430613462386231376262613230316130336163643036396234653431366232613263383066383661383338313435633239373566633131333030613036303832613836343863653364303430333032303434363330343430323230343639306264636637626461663833636466343934396534633035313039656463663334373665303564373261313264376335666538633033303033343464663032323032363764353863393365626233353031333836363062353730373938613064643731313734316262353864626436613138363633353038353431656565393035303030303030303030303030227D \ No newline at end of file diff --git a/cpanfile b/cpanfile index c6c5d251d6648..728688347447a 100644 --- a/cpanfile +++ b/cpanfile @@ -89,6 +89,9 @@ requires 'Action::Retry'; # deps: libmath-fibonacci-perl requires 'AnyEvent'; requires 'AnyEvent::Inotify::Simple'; +# more Apache stuff +requires 'Apache::Bootstrap'; # needed by Apache2::Connection::XForwardedFor +requires 'Apache2::Connection::XForwardedFor'; # GS1 Encoder requires 'GS1::SyntaxEngine::FFI'; diff --git a/cron/import_carrefour.sh b/cron/import_carrefour.sh deleted file mode 100755 index 057cfde50b57f..0000000000000 --- a/cron/import_carrefour.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/sh - -cp -a /home/sftp/carrefour/data/*xml /srv/off/imports/carrefour/data/ - -cd /srv/off/imports/carrefour - -./mv_non_off_files.sh - -# Warning some Carrefour XML files are broken with 2 .* -# fix them by removing the second one: -cd data -find . -name "*.xml" -type f -exec sed -i 's/<\/TabNutXMLPF>.*/<\/TabNutXMLPF>/g' {} \; - -unzip -o '/home/sftp/carrefour/data/*zip' -d /srv/off/imports/carrefour/images/ - -cd /srv/off-pro/scripts - -export PERL5LIB=. - -./convert_carrefour_data_off1.sh - -./import_carrefour_pro_off1.sh - -./export_csv_file.pl --fields code,nutrition_grades_tags --query editors_tags=carrefour --separator ';' > /srv/off/html/data/exports/carrefour_nutriscore.csv - -./export_csv_file.pl --fields code,nutrition_grades_tags --separator ';' > /srv/off/html/data/exports/nutriscore.csv diff --git a/debug/.empty b/debug/.empty deleted file mode 100644 index e69de29bb2d1d..0000000000000 diff --git a/docker-compose.yml b/docker-compose.yml index ef17f87daadc9..35358a4128147 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -36,6 +36,8 @@ x-backend-conf: &backend-conf - ${WEB_LANG_PATH}:/mnt/podata/lang # Static data (e.g dumps) - html_data:/opt/product-opener/html/data + # other servers dirs (this is temporary to be able to develop for now) + - other_servers:/srv # Binds from frontend container (read-only) - icons_dist:/opt/product-opener/html/images/icons/dist:ro @@ -50,7 +52,8 @@ x-backend-conf: &backend-conf - orgs:/mnt/podata/orgs # .sto # build-cache - build_cache:/mnt/podata/build-cache - + # export_files folders must be accessible between pro and public instances + - export_files:/mnt/podata/export_files # all the rest - podata:/mnt/podata @@ -119,11 +122,11 @@ services: # Nginx, we use templates dir to be able to use environment vars - ./conf/nginx.conf:/etc/nginx/templates/default.conf.template # cors headers definition as an include - - ./conf/nginx/snippets/off.cors-headers.include:/etc/nginx/conf.d/off.cors-headers.include + - ./conf/nginx/snippets/off.cors-headers.include:/etc/nginx/snippets/off.cors-headers.include # some expires rules - - ./conf/nginx/expires-no-json-xml.conf:/etc/nginx/conf.d/expires-no-json-xml.include + - ./conf/nginx/snippets/expires-no-json-xml.conf:/etc/nginx/snippets/expires-no-json-xml.conf # some redirects - - ./conf/nginx/snippets/off.locations-redirects.include:/etc/nginx/conf.d/off.locations-redirects.include + - ./conf/nginx/snippets/off.locations-redirects.include:/etc/nginx/snippets/off.locations-redirects.include ports: - ${PRODUCT_OPENER_EXPOSE}${PRODUCT_OPENER_PORT}:80 @@ -133,3 +136,6 @@ volumes: js_dist: css_dist: node_modules: + # build_cache does not needs not be external, for wiping it will avoid keeping too much cached data + build_cache: + other_servers: diff --git a/docker/dev.yml b/docker/dev.yml index 804d2105d34aa..4aacaf88d1c6d 100644 --- a/docker/dev.yml +++ b/docker/dev.yml @@ -102,18 +102,19 @@ services: volumes: product_images: html_data: + other_servers: products: # those one are volumes shared between off and pro, so we assign hard-coded names # see docs/dev/explain-pro-dev-setup.md - # PO_COMMON_PREFIX is there to separate env, eg. for tests + # PO_COMMON_PREFIX is there to separate envs, eg. for tests users: name: ${PO_COMMON_PREFIX:-}po_users orgs: name: ${PO_COMMON_PREFIX:-}po_orgs - podata: # we also need to share it because users_emails and orgs... are not separated yet - name: ${PO_COMMON_PREFIX:-}po_podata + export_files: + name: ${PO_COMMON_PREFIX:-}po_export_files + podata: dbdata: - build_cache: networks: # this is a specific network to enable pro platform to join the postgres db diff --git a/docker/docker-entrypoint.sh b/docker/docker-entrypoint.sh index 8ea229e4e9cef..f68b43a76f150 100755 --- a/docker/docker-entrypoint.sh +++ b/docker/docker-entrypoint.sh @@ -10,13 +10,52 @@ ln -sfT /opt/product-opener/lib/ProductOpener/SiteLang_${PRODUCT_OPENER_FLAVOR_S ln -sfT /opt/product-opener/lib/ProductOpener/Config_${PRODUCT_OPENER_FLAVOR_SHORT}.pm /opt/product-opener/lib/ProductOpener/Config.pm ln -sfT /opt/product-opener/lib/ProductOpener/Config2_docker.pm /opt/product-opener/lib/ProductOpener/Config2.pm +# 2023-08-16 migration for build-cache… should be in a volume +if [[ -L /mnt/podata/build-cache ]] +then + unlink /mnt/podata/build-cache + mkdir -p /mnt/podata/build-cache/taxonomies +fi + # Create symlinks of data files that are indeed conf data in /mnt/podata (because we currently mix data and conf data) # we need to do this here, because /mnt/podata is a volume -for path in data-default external-data emb_codes ingredients madenearme packager-codes po taxonomies templates build-cache; +for path in data-default external-data emb_codes ingredients madenearme packager-codes po taxonomies templates; do test -d /mnt/podata/${path} || ln -sf /opt/product-opener/${path} /mnt/podata/${path} done +# link some static files +for path in data-fields.{md,txt} +do + test -L /opt/products-opener/html_data/$path || ln -sf /opt/products-opener/html/$path /mnt/podata/html_data/$path +done + +# create some directories that might be needed +for path in new_images deleted_products_images reverted_products deleted_private_products translate deleted_products deleted.images import_files tmp build-cache/taxonomies debug +do + path="/mnt/podata/$path" + [[ -d $path ]] || mkdir $path +done +for path in dump exports files +do + src_path=/opt/product-opener/html/data/$path + target_path=/opt/product-opener/html/$path + [[ -d $target_path ]] && [[ ! -e $src_path ]] && mv $target_path $src_path + [[ -d $src_path ]] || mkdir -p $src_path + [[ -e $target_path ]] && [[ ! -h $target_path ]] && [[ -d $src_path ]] && rm -rf $target_path + [[ -h $target_path ]] || ln -s $src_path $target_path +done +[[ -d /opt/product-opener/html/data/files/debug ]] || mkdir /opt/product-opener/html/data/files/debug +# exchanges between projects (NOTE: just faking for now) +for service in obf off opf opff +do + for path in "/srv/$service/products" "/srv/$service/html/images/products" + do + [[ -d $path ]] || mkdir -p $path + done +done + + # this is not very elegant, but incron scripts won't have env variables so put them in a file rm -f /tmp/env-export.sh && export > /tmp/env-export.sh chown www-data:www-data /tmp/env-export.sh && chmod 0400 /tmp/env-export.sh diff --git a/docker/prod.yml b/docker/prod.yml index 6241624edf159..f6be0883cb547 100644 --- a/docker/prod.yml +++ b/docker/prod.yml @@ -43,9 +43,8 @@ volumes: podata: external: true name: ${COMPOSE_PROJECT_NAME}_podata - # not external, for wiping it will avoid keeping too much cached data - build_cache: - name: ${COMPOSE_PROJECT_NAME}_build_cache + export_files: + name: ${COMPOSE_PROJECT_NAME}_export_files networks: webnet: diff --git a/html/files/doc/perl/simple.min.css b/docs/assets/simple.min.css similarity index 100% rename from html/files/doc/perl/simple.min.css rename to docs/assets/simple.min.css diff --git a/docs/dev/explain-taxonomy-build-cache.md b/docs/dev/explain-taxonomy-build-cache.md index 1f71b2271dd0a..282edbcacb0d8 100644 --- a/docs/dev/explain-taxonomy-build-cache.md +++ b/docs/dev/explain-taxonomy-build-cache.md @@ -8,7 +8,19 @@ A hash is calculated for all of the source files used to build a particular taxo If no cached build is found then the taxonomy is rebuilt and cached locally. -If the GITHUB_TOKEN environemnt variable is set then the cached build is also uploaded to the https://github.com/openfoodfacts/openfoodfacts-build-cache repository. Note that no token is required to download previous cached builds from the repo. +If the GITHUB_TOKEN environment variable is set then the cached build is also uploaded to the https://github.com/openfoodfacts/openfoodfacts-build-cache repository. + +The token is a personal access token, created here: https://github.com/settings/tokens. +Only the public_repo scope is needed. + +Note that no token is required to download previous cached builds from the repo. + +# Storage + +Cached copies of taxonomy build results are stored in `build-cache/taxonomies`. + +If no local cache is available then https://github.com/openfoodfacts/openfoodfacts-build-cache is checked for a copy. + # Obtaining a token diff --git a/gulpfile.ts b/gulpfile.ts index 255aefe3f993c..84291db7d0c2f 100644 --- a/gulpfile.ts +++ b/gulpfile.ts @@ -37,7 +37,7 @@ export function icons() { export function attributesIcons() { return src("*.svg", { cwd: "./html/images/attributes/src" }). pipe(svgmin()). - pipe(dest("./html/images/attributes")); + pipe(dest("./html/images/attributes/dist")); } export function css() { diff --git a/html/data/data-fields.md b/html/data-fields.md similarity index 100% rename from html/data/data-fields.md rename to html/data-fields.md diff --git a/html/data/data-fields.txt b/html/data-fields.txt similarity index 100% rename from html/data/data-fields.txt rename to html/data-fields.txt diff --git a/html/files/doc/perl/a.txt b/html/files/doc/perl/a.txt deleted file mode 100644 index 8b137891791fe..0000000000000 --- a/html/files/doc/perl/a.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/html/files/presentations/index.txt b/html/files/presentations/index.txt deleted file mode 100644 index 3b94f915737ab..0000000000000 --- a/html/files/presentations/index.txt +++ /dev/null @@ -1 +0,0 @@ -Placeholder diff --git a/html/files/robots.txt b/html/files/robots.txt deleted file mode 100644 index a41159f85a640..0000000000000 --- a/html/files/robots.txt +++ /dev/null @@ -1,15 +0,0 @@ -User-agent: * -Allow: /cgi/product_image.pl -Allow: /cgi/opensearch.pl -Disallow: /cgi -Disallow: /code -User-agent: Slurp -Disallow: / -User-agent: dotbot -Disallow: / -User-agent: AhrefsBot -Disallow: / -User-agent: MJ12bot -Disallow: / -User-agent: SemrushBot -Disallow: / diff --git a/html/images/products/.empty b/html/images/products/.empty deleted file mode 100644 index e69de29bb2d1d..0000000000000 diff --git a/html/resources/README.md b/html/resources/README.md new file mode 100644 index 0000000000000..a4251105b9b4c --- /dev/null +++ b/html/resources/README.md @@ -0,0 +1,8 @@ +# IMPORTANT NOTE + +Files in this folders are made accessible through `//path/to/file` +thanks to a specific rule in nginx configuration. + +This is for historical reason. + +If you can, refer to them through `/resources/path/to/file` in the future. \ No newline at end of file diff --git a/html/files/app/ingredients-analysis.json b/html/resources/files/app/ingredients-analysis.json similarity index 100% rename from html/files/app/ingredients-analysis.json rename to html/resources/files/app/ingredients-analysis.json diff --git a/html/files/app/tagline/tagline-off-ios.json b/html/resources/files/app/tagline/tagline-off-ios.json similarity index 100% rename from html/files/app/tagline/tagline-off-ios.json rename to html/resources/files/app/tagline/tagline-off-ios.json diff --git a/html/files/knowledge_panel_test.json b/html/resources/files/knowledge_panel_test.json similarity index 100% rename from html/files/knowledge_panel_test.json rename to html/resources/files/knowledge_panel_test.json diff --git a/html/files/tagline-obf.json b/html/resources/files/tagline-obf.json similarity index 100% rename from html/files/tagline-obf.json rename to html/resources/files/tagline-obf.json diff --git a/html/files/tagline-off-android-v2.json b/html/resources/files/tagline-off-android-v2.json similarity index 100% rename from html/files/tagline-off-android-v2.json rename to html/resources/files/tagline-off-android-v2.json diff --git a/html/files/tagline-off-ios-v2.json b/html/resources/files/tagline-off-ios-v2.json similarity index 100% rename from html/files/tagline-off-ios-v2.json rename to html/resources/files/tagline-off-ios-v2.json diff --git a/html/files/tagline-off.json b/html/resources/files/tagline-off.json similarity index 100% rename from html/files/tagline-off.json rename to html/resources/files/tagline-off.json diff --git a/html/files/tagline-opf.json b/html/resources/files/tagline-opf.json similarity index 100% rename from html/files/tagline-opf.json rename to html/resources/files/tagline-opf.json diff --git a/html/files/tagline-opff.json b/html/resources/files/tagline-opff.json similarity index 100% rename from html/files/tagline-opff.json rename to html/resources/files/tagline-opff.json diff --git a/html/files/tagline.txt b/html/resources/files/tagline.txt similarity index 100% rename from html/files/tagline.txt rename to html/resources/files/tagline.txt diff --git a/lib/ProductOpener/APIProductRead.pm b/lib/ProductOpener/APIProductRead.pm index 04721b4a82843..3c4dfe2c47cc1 100644 --- a/lib/ProductOpener/APIProductRead.pm +++ b/lib/ProductOpener/APIProductRead.pm @@ -44,6 +44,7 @@ BEGIN { use vars @EXPORT_OK; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Display qw/:all/; use ProductOpener::Users qw/:all/; use ProductOpener::Lang qw/:all/; @@ -165,7 +166,7 @@ sub read_product_api ($request_ref) { # Return blame information if (single_param("blame")) { my $path = product_path_from_id($product_id); - my $changes_ref = retrieve("$data_root/products/$path/changes.sto"); + my $changes_ref = retrieve("$BASE_DIRS{PRODUCTS}/$path/changes.sto"); if (not defined $changes_ref) { $changes_ref = []; } diff --git a/lib/ProductOpener/APITest.pm b/lib/ProductOpener/APITest.pm index d75c69f290263..a9d8a9f5cf84f 100644 --- a/lib/ProductOpener/APITest.pm +++ b/lib/ProductOpener/APITest.pm @@ -60,6 +60,7 @@ BEGIN { use vars @EXPORT_OK; +use ProductOpener::Paths qw/:all/; use ProductOpener::TestDefaults qw/:all/; use ProductOpener::Test qw/:all/; use ProductOpener::Mail qw/$LOG_EMAIL_START $LOG_EMAIL_END/; @@ -704,7 +705,6 @@ ref to an array of lines of the email sub normalize_mail_for_comparison ($mail) { # remove boundaries - $DB::single = 1; my $text = mail_to_text($mail); my @boundaries = $text =~ m/boundary=([^ ,\n\t]+)/g; foreach my $boundary (@boundaries) { diff --git a/lib/ProductOpener/Attributes.pm b/lib/ProductOpener/Attributes.pm index f4cf83f723f9b..410183cec37ce 100644 --- a/lib/ProductOpener/Attributes.pm +++ b/lib/ProductOpener/Attributes.pm @@ -271,45 +271,45 @@ sub initialize_attribute ($attribute_id, $target_lc) { # Initialize icon for the attribute if ($attribute_id eq "nutriscore") { - $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/nutriscore-a.svg"; + $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/dist/nutriscore-a.svg"; $attribute_ref->{panel_id} = "nutriscore"; } elsif ($attribute_id eq "ecoscore") { - $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/ecoscore-a.svg"; + $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/dist/ecoscore-a.svg"; $attribute_ref->{panel_id} = "ecoscore"; } elsif ($attribute_id eq "forest_footprint") { - $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/forest-footprint-a.svg"; + $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/dist/forest-footprint-a.svg"; } elsif ($attribute_id eq "nova") { - $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/nova-group-1.svg"; + $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/dist/nova-group-1.svg"; $attribute_ref->{panel_id} = "nova"; } elsif ($attribute_id eq "additives") { - $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/0-additives.svg"; + $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/dist/0-additives.svg"; $attribute_ref->{panel_id} = "additives"; } elsif ($attribute_id =~ /^allergens_no_(.*)$/) { my $allergen = $1; $allergen =~ s/_/-/g; - $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/no-$allergen.svg"; + $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/dist/no-$allergen.svg"; } elsif ($attribute_id =~ /^(low)_(salt|sugars|fat|saturated_fat)$/) { my $nid = $2; $nid =~ s/_/-/g; - $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/nutrient-level-$nid-low.svg"; + $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/dist/nutrient-level-$nid-low.svg"; } elsif (($attribute_id eq "vegan") or ($attribute_id eq "vegetarian") or ($attribute_id eq "palm_oil_free")) { my $analysis_tag = $attribute_id; $analysis_tag =~ s/_/-/g; - $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/$analysis_tag.svg"; + $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/dist/$analysis_tag.svg"; } elsif ($attribute_id =~ /^(labels)_(.*)$/) { my $tagtype = $1; my $tag = $2; $tag =~ s/_/-/g; - $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/${tag}.svg"; + $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/dist/${tag}.svg"; } # Initialize name and setting name if a language is requested @@ -537,13 +537,13 @@ sub compute_attribute_nutriscore ($product_ref, $target_lc) { $attribute_ref->{description_short} = lang_in_other_lc($target_lc, "attribute_nutriscore_" . $grade . "_description_short"); } - $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/nutriscore-$grade.svg"; + $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/dist/nutriscore-$grade.svg"; } # Nutri-Score not-applicable: alcoholic beverages, baby food etc. elsif (has_tag($product_ref, "nutrition_grades", "not-applicable")) { $attribute_ref->{status} = "known"; - $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/nutriscore-not-applicable.svg"; + $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/dist/nutriscore-not-applicable.svg"; $attribute_ref->{match} = 0; if ($target_lc ne "data") { $attribute_ref->{title} = lang_in_other_lc($target_lc, "attribute_nutriscore_not_applicable_title"); @@ -565,7 +565,7 @@ sub compute_attribute_nutriscore ($product_ref, $target_lc) { # Nutri-Score not computed: missing data else { $attribute_ref->{status} = "unknown"; - $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/nutriscore-unknown.svg"; + $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/dist/nutriscore-unknown.svg"; $attribute_ref->{match} = 0; if ($target_lc ne "data") { $attribute_ref->{title} = lang_in_other_lc($target_lc, "attribute_nutriscore_unknown_title"); @@ -667,12 +667,12 @@ sub compute_attribute_ecoscore ($product_ref, $target_lc, $target_cc) { $attribute_ref->{description_short} = lang_in_other_lc($target_lc, "attribute_ecoscore_" . $grade . "_description_short"); } - $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/ecoscore-$grade.svg"; + $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/dist/ecoscore-$grade.svg"; } # Eco-Score is not-applicable elsif ((defined $product_ref->{ecoscore_grade}) and ($product_ref->{ecoscore_grade} eq "not-applicable")) { $attribute_ref->{status} = "unknown"; - $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/ecoscore-not-applicable.svg"; + $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/dist/ecoscore-not-applicable.svg"; $attribute_ref->{match} = 0; if ($target_lc ne "data") { $attribute_ref->{title} = lang_in_other_lc($target_lc, "attribute_ecoscore_not_applicable_title"); @@ -693,7 +693,7 @@ sub compute_attribute_ecoscore ($product_ref, $target_lc, $target_cc) { # Eco-Score is unknown else { $attribute_ref->{status} = "unknown"; - $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/ecoscore-unknown.svg"; + $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/dist/ecoscore-unknown.svg"; $attribute_ref->{match} = 0; if ($target_lc ne "data") { $attribute_ref->{title} = lang_in_other_lc($target_lc, "attribute_ecoscore_unknown_title"); @@ -773,14 +773,14 @@ sub compute_attribute_forest_footprint ($product_ref, $target_lc) { $attribute_ref->{description_short} = lang_in_other_lc($target_lc, "attribute_forest_footprint_" . $grade . "_description_short"); } - $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/forest-footprint-$grade.svg"; + $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/dist/forest-footprint-$grade.svg"; } else { # If we don't have a forest footprint, we assume it is zero and mark it as known # We do keep a greyed out icon until the forest footprint encompasses most sources of deforestation # (e.g. not only chicken and eggs, but also other raised animals products and palm oil) $attribute_ref->{status} = "known"; - $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/forest-footprint-not-computed.svg"; + $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/dist/forest-footprint-not-computed.svg"; $attribute_ref->{match} = 0; if ($target_lc ne "data") { $attribute_ref->{title} = lang_in_other_lc($target_lc, "attribute_forest_footprint_not_computed_title"); @@ -861,12 +861,12 @@ sub compute_attribute_nova ($product_ref, $target_lc) { $attribute_ref->{description_short} = lang_in_other_lc($target_lc, "attribute_nova_" . $nova_group . "_description_short"); } - $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/nova-group-$nova_group.svg"; + $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/dist/nova-group-$nova_group.svg"; } else { $attribute_ref->{status} = "unknown"; - $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/nova-group-unknown.svg"; + $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/dist/nova-group-unknown.svg"; $attribute_ref->{match} = 0; if ($target_lc ne "data") { $attribute_ref->{title} = lang_in_other_lc($target_lc, "attribute_nova_unknown_title"); @@ -955,13 +955,13 @@ sub compute_attribute_additives ($product_ref, $target_lc) { $n = 10; } - $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/$n-additives.svg"; + $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/dist/$n-additives.svg"; } else { $attribute_ref->{status} = "unknown"; $attribute_ref->{match} = 0; - $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/additives-unknown.svg"; + $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/dist/additives-unknown.svg"; if ($target_lc ne "data") { $attribute_ref->{title} = lang_in_other_lc($target_lc, "attribute_additives_unknown_title"); $attribute_ref->{description} = lang_in_other_lc($target_lc, "attribute_additives_unknown_description"); @@ -1034,18 +1034,18 @@ sub compute_attribute_has_tag ($product_ref, $target_lc, $tagtype, $tagid) { $attribute_ref->{status} = "unknown"; $value = "unknown"; - $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/${tag}-unknown.svg"; + $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/dist/${tag}-unknown.svg"; } elsif (has_tag($product_ref, $tagtype, $tagid)) { $attribute_ref->{match} = 100; $value = "yes"; - $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/${tag}.svg"; + $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/dist/${tag}.svg"; } else { $attribute_ref->{match} = 0; $value = "no"; - $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/not-${tag}.svg"; + $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/dist/not-${tag}.svg"; } if ($target_lc ne "data") { @@ -1124,7 +1124,7 @@ sub compute_attribute_nutrient_level ($product_ref, $target_lc, $level, $nid) { if ((not defined $product_ref->{nutrient_levels}) or (not defined $product_ref->{nutrient_levels}{$nid})) { $attribute_ref->{status} = "unknown"; - $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/nutrient-level-$nid-unknown.svg"; + $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/dist/nutrient-level-$nid-unknown.svg"; if ($target_lc ne "data") { $attribute_ref->{title} = sprintf( lang_in_other_lc($target_lc, "nutrient_in_quantity"), @@ -1161,19 +1161,19 @@ sub compute_attribute_nutrient_level ($product_ref, $target_lc, $level, $nid) { if ($value < $low) { $match = 80 + 20 * ($low - $value) / $low; - $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/nutrient-level-$nid-low.svg"; + $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/dist/nutrient-level-$nid-low.svg"; } elsif ($value <= $high) { $match = 20 + 60 * ($high - $value) / ($high - $low); - $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/nutrient-level-$nid-medium.svg"; + $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/dist/nutrient-level-$nid-medium.svg"; } elsif ($value < $high * 2) { $match = 20 * ($high * 2 - $value) / $high; - $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/nutrient-level-$nid-high.svg"; + $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/dist/nutrient-level-$nid-high.svg"; } else { $match = 0; - $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/nutrient-level-$nid-high.svg"; + $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/dist/nutrient-level-$nid-high.svg"; } $attribute_ref->{match} = $match; @@ -1319,7 +1319,7 @@ sub compute_attribute_allergen ($product_ref, $target_lc, $attribute_id) { lang_in_other_lc($target_lc, "presence_unknown_s"), display_taxonomy_tag($target_lc, "allergens", $allergen_id) ); - $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/$allergen-content-unknown.svg"; + $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/dist/$allergen-content-unknown.svg"; if (not($product_ref->{ingredients_n})) { # If we don't have ingredients, @@ -1337,17 +1337,17 @@ sub compute_attribute_allergen ($product_ref, $target_lc, $attribute_id) { lang_in_other_lc($target_lc, "does_not_contain_s"), display_taxonomy_tag($target_lc, "allergens", $allergen_id) ); - $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/no-$allergen.svg"; + $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/dist/no-$allergen.svg"; } elsif ($attribute_ref->{match} == 20) { $attribute_ref->{title} = sprintf( lang_in_other_lc($target_lc, "may_contain_s"), display_taxonomy_tag($target_lc, "allergens", $allergen_id) ); - $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/may-contain-$allergen.svg"; + $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/dist/may-contain-$allergen.svg"; } elsif ($attribute_ref->{match} == 0) { - $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/contains-$allergen.svg"; + $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/dist/contains-$allergen.svg"; $attribute_ref->{title} = sprintf( lang_in_other_lc($target_lc, "contains_s"), display_taxonomy_tag($target_lc, "allergens", $allergen_id) @@ -1474,7 +1474,7 @@ sub compute_attribute_ingredients_analysis ($product_ref, $target_lc, $analysis) } $attribute_ref->{status} = $status; - $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/$analysis_tag.svg"; + $attribute_ref->{icon_url} = "$static_subdomain/images/attributes/dist/$analysis_tag.svg"; # the ingredients_analysis taxonomy contains en:palm-oil and not en:contains-palm-oil $analysis_tag =~ s/contains-(.*)$/$1/; diff --git a/lib/ProductOpener/Config2_docker.pm b/lib/ProductOpener/Config2_docker.pm index a711ea7a11245..93e51c88fcfaa 100755 --- a/lib/ProductOpener/Config2_docker.pm +++ b/lib/ProductOpener/Config2_docker.pm @@ -35,6 +35,7 @@ BEGIN { $producers_platform $data_root $conf_root + $sftp_root $www_root $geolite2_path $log_emails @@ -78,6 +79,7 @@ $server_domain = $is_localhost && $po_port != '80' ? "$po_domain:$po_port" : $po $data_root = "/mnt/podata"; $www_root = "/opt/product-opener/html"; $conf_root = "/opt/product-opener/conf"; +$sftp_root = "/mnt/podata/sftp"; $geolite2_path = $ENV{GEOLITE2_PATH}; my $mongodb_url = $ENV{MONGODB_HOST} || "mongodb"; diff --git a/lib/ProductOpener/Config2_sample.pm b/lib/ProductOpener/Config2_sample.pm index fe08108ff9da0..5f02fe75b61e5 100644 --- a/lib/ProductOpener/Config2_sample.pm +++ b/lib/ProductOpener/Config2_sample.pm @@ -30,7 +30,9 @@ BEGIN { $server_domain @ssl_subdomains $data_root + $conf_root $www_root + $sftp_root $geolite2_path $mongodb $mongodb_host @@ -60,7 +62,9 @@ $server_domain = "openfoodfacts.org"; # server paths $www_root = "/home/off/html"; +$conf_root = "/home/off"; $data_root = "/home/off"; +$sftp_root = "/home/sftp"; $geolite2_path = '/usr/local/share/GeoLite2-Country/GeoLite2-Country.mmdb'; diff --git a/lib/ProductOpener/Config_off.pm b/lib/ProductOpener/Config_off.pm index b5faea0d7aa35..8d2bdc2339744 100644 --- a/lib/ProductOpener/Config_off.pm +++ b/lib/ProductOpener/Config_off.pm @@ -35,6 +35,7 @@ BEGIN { $conf_root $data_root $www_root + $sftp_root $geolite2_path $reference_timezone $contact_email @@ -344,6 +345,7 @@ $memd_servers = $ProductOpener::Config2::memd_servers; $www_root = $ProductOpener::Config2::www_root; $data_root = $ProductOpener::Config2::data_root; $conf_root = $ProductOpener::Config2::conf_root; +$sftp_root = $ProductOpener::Config2::sftp_root; # might be undef $geolite2_path = $ProductOpener::Config2::geolite2_path; diff --git a/lib/ProductOpener/Display.pm b/lib/ProductOpener/Display.pm index da6ef84397c40..86eb02a6b3b85 100644 --- a/lib/ProductOpener/Display.pm +++ b/lib/ProductOpener/Display.pm @@ -59,6 +59,7 @@ BEGIN { &display_robots_txt_and_exit &display_page &display_text + &display_stats &display_points &display_mission &display_tag @@ -150,6 +151,7 @@ use vars @EXPORT_OK; use ProductOpener::HTTP qw(:all); use ProductOpener::Store qw(:all); use ProductOpener::Config qw(:all); +use ProductOpener::Paths qw/:all/; use ProductOpener::Tags qw(:all); use ProductOpener::TagsEntries qw(:all); use ProductOpener::Users qw(:all); @@ -1218,8 +1220,6 @@ sub display_text ($request_ref) { my $textid = $request_ref->{text}; - $request_ref->{page_type} = "text"; - if ($textid =~ /open-food-facts-mobile-app|application-mobile-open-food-facts/) { # we want the mobile app landing page to be included in a
# so we display it under the `banner` page format, which is the page format @@ -1235,7 +1235,23 @@ sub display_text ($request_ref) { $text_lang = 'en'; } - my $file = "$data_root/lang/$text_lang/texts/" . $texts{$textid}{$text_lang}; + my $file = "$BASE_DIRS{LANG}/$text_lang/texts/" . $texts{$textid}{$text_lang}; + + display_text_content($request_ref, $textid, $text_lang, $file); + return; +} + +sub display_stats ($request_ref) { + my $textid = $request_ref->{text}; + my $stats_dir = "$BASE_DIRS{PUBLIC_DATA}/products_stats/$lang"; + my $file = "$stats_dir/products_stats_$cc.html"; + display_text_content($request_ref, $textid, $lang, $file); + return; +} + +sub display_text_content ($request_ref, $textid, $text_lang, $file) { + + $request_ref->{page_type} = "text"; open(my $IN, "<:encoding(UTF-8)", $file); my $html = join('', (<$IN>)); @@ -1281,7 +1297,12 @@ sub display_text ($request_ref) { my $replace_file = sub ($fileid) { ($fileid =~ /\.\./) and return ''; $fileid =~ s/^texts\///; - my $file = "$data_root/lang/$lc/texts/$fileid"; + my $text_dir = "$BASE_DIRS{LANG}/$lc/texts/"; + if ($fileid =~ /products_stats_/) { + # special location as this is generated + $text_dir = "$BASE_DIRS{PUBLIC_DATA}/products_stats/$lc/"; + } + my $file = "$text_dir/$fileid"; my $html = ''; if (-e $file) { open(my $IN, "<:encoding(UTF-8)", "$file"); @@ -1439,7 +1460,7 @@ sub display_mission ($request_ref) { my $missionid = $request_ref->{missionid}; - open(my $IN, "<:encoding(UTF-8)", "$data_root/lang/$lang/missions/$missionid.html"); + open(my $IN, "<:encoding(UTF-8)", "$BASE_DIRS{PUBLIC_DATA}/missions/$lang/$missionid.html"); my $html = join('', (<$IN>)); $request_ref->{content_ref} = \$html; @@ -1767,14 +1788,14 @@ sub display_list_of_tags ($request_ref, $query_ref) { $request_ref->{title} = sprintf(lang("list_of_x"), $Lang{$tagtype . "_p"}{$lang}); - if ( -e "$data_root/lang/$lc/texts/" + if ( -e "$BASE_DIRS{LANG}/$lc/texts/" . get_string_id_for_lang("no_language", $Lang{$tagtype . "_p"}{$lang}) . ".list.html") { open( my $IN, q{<}, - "$data_root/lang/$lc/texts/" + "$BASE_DIRS{LANG}/$lc/texts/" . get_string_id_for_lang("no_language", $Lang{$tagtype . "_p"}{$lang}) . ".list.html" ); @@ -2044,7 +2065,7 @@ sub display_list_of_tags ($request_ref, $query_ref) { $grade = lang("unknown"); } $display - = "\"$Lang{nutrition_grade_fr_alt}{$lc}\n"; @@ -2928,7 +2949,7 @@ sub display_points ($request_ref) { my $description = ''; if ($tagtype eq 'users') { - my $user_ref = retrieve("$data_root/users/$tagid.sto"); + my $user_ref = retrieve("$BASE_DIRS{USERS}/$tagid.sto"); if (defined $user_ref) { if ((defined $user_ref->{name}) and ($user_ref->{name} ne '')) { $title = $user_ref->{name} . " ($tagid)"; @@ -3969,7 +3990,7 @@ HTML # User - $user_or_org_ref = retrieve("$data_root/users/$tagid.sto"); + $user_or_org_ref = retrieve("$BASE_DIRS{USERS}/$tagid.sto"); if (not defined $user_or_org_ref) { display_error_and_exit(lang("error_unknown_user"), 404); @@ -7341,7 +7362,7 @@ HTML my $path = product_path($product_ref); - if (-e "$www_root/images/products/$path/$filename.full.json") { + if (-e "$BASE_DIRS{PRODUCTS_IMAGES}/$path/$filename.full.json") { $html .= <OCR result HTML @@ -10333,7 +10354,7 @@ HTML # Return blame information if (single_param("blame")) { my $path = product_path_from_id($product_id); - my $changes_ref = retrieve("$data_root/products/$path/changes.sto"); + my $changes_ref = retrieve("$BASE_DIRS{PRODUCTS}/$path/changes.sto"); if (not defined $changes_ref) { $changes_ref = []; } @@ -10363,7 +10384,7 @@ sub display_rev_info ($product_ref, $rev) { my $code = $product_ref->{code}; my $path = product_path($product_ref); - my $changes_ref = retrieve("$data_root/products/$path/changes.sto"); + my $changes_ref = retrieve("$BASE_DIRS{PRODUCTS}/$path/changes.sto"); if (not defined $changes_ref) { return ''; } @@ -10411,7 +10432,7 @@ sub display_product_history ($code, $product_ref) { } my $path = product_path($product_ref); - my $changes_ref = retrieve("$data_root/products/$path/changes.sto"); + my $changes_ref = retrieve("$BASE_DIRS{PRODUCTS}/$path/changes.sto"); if (not defined $changes_ref) { $changes_ref = []; } diff --git a/lib/ProductOpener/Export.pm b/lib/ProductOpener/Export.pm index 554760633edbc..397cf980dee92 100644 --- a/lib/ProductOpener/Export.pm +++ b/lib/ProductOpener/Export.pm @@ -92,6 +92,7 @@ BEGIN { use vars @EXPORT_OK; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Lang qw/:all/; use ProductOpener::Tags qw/:all/; @@ -206,8 +207,24 @@ sub export_csv ($args_ref) { # We will have one cursor for each collection # We store cursors because we will iterate them twice + # (or only once if the fields to export are specified) my %cursors = (); + foreach my $collection (@collections) { + + my $obsolete = ($collection eq "products_obsolete") ? 1 : 0; + + my $count = get_products_collection({obsolete => $obsolete})->count_documents($query_ref); + + $log->debug("export_csv - documents to export", {count => $count, collection => $collection}) + if $log->is_debug(); + + $cursors{$collection} = get_products_collection({obsolete => $obsolete})->find($query_ref); + $cursors{$collection}->immortal(1); + } + + # First pass to determine which fields should be exported + if (defined $fields_ref) { # The fields to export are specified by the fields parameter @sorted_populated_fields = @{$fields_ref}; @@ -216,7 +233,6 @@ sub export_csv ($args_ref) { # 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 = (); @@ -224,16 +240,6 @@ sub export_csv ($args_ref) { # Loop on collections foreach my $collection (@collections) { - my $obsolete = ($collection eq "products_obsolete") ? 1 : 0; - - my $count = get_products_collection({obsolete => $obsolete})->count_documents($query_ref); - - $log->debug("export_csv - documents to export", {count => $count, collection => $collection}) - if $log->is_debug(); - - $cursors{$collection} = get_products_collection({obsolete => $obsolete})->find($query_ref); - $cursors{$collection}->immortal(1); - while (my $product_ref = $cursors{$collection}->next) { # Possible fields to export are listed in $options{import_export_fields_groups} @@ -533,7 +539,7 @@ sub export_csv ($args_ref) { if (not defined $scans_ref) { # Load the scan data - $scans_ref = retrieve_json("$data_root/products/$product_path/scans.json"); + $scans_ref = retrieve_json("$BASE_DIRS{PRODUCTS}/$product_path/scans.json"); } if (not defined $scans_ref) { $scans_ref = {}; @@ -588,13 +594,13 @@ sub export_csv ($args_ref) { if ((defined $product_ref->{images}) and (defined $product_ref->{images}{$imagefield})) { $value - = "$www_root/images/products/" + = "$BASE_DIRS{PRODUCTS_IMAGES}/" . $product_path . "/" . $product_ref->{images}{$imagefield}{imgid} . ".jpg"; } elsif (defined $other_images{$product_ref->{code} . "." . $imagefield}) { $value - = "$www_root/images/products/" + = "$BASE_DIRS{PRODUCTS_IMAGES}/" . $product_path . "/" . $other_images{$product_ref->{code} . "." . $imagefield}{imgid} . ".jpg"; } diff --git a/lib/ProductOpener/Food.pm b/lib/ProductOpener/Food.pm index deb37c6a7cb28..3b21b0347febf 100644 --- a/lib/ProductOpener/Food.pm +++ b/lib/ProductOpener/Food.pm @@ -97,6 +97,7 @@ use vars @EXPORT_OK; use ProductOpener::Store qw/:all/; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Lang qw/:all/; use ProductOpener::Tags qw/:all/; use ProductOpener::Images qw/:all/; @@ -156,12 +157,13 @@ foreach my $categories_list_id ( # the stats are displayed on category pages and used in product pages, # as well as in data quality checks and improvement opportunity detection -if (opendir(my $dh, "$data_root/data/categories_stats")) { +if (opendir(my $dh, "$BASE_DIRS{PRIVATE_DATA}/categories_stats")) { foreach my $file (readdir($dh)) { if ($file =~ /categories_nutriments_per_country.(\w+).sto$/) { my $country_cc = $1; $categories_nutriments_per_country{$country_cc} - = retrieve("$data_root/data/categories_stats/categories_nutriments_per_country.$country_cc.sto"); + = retrieve( + "$BASE_DIRS{PRIVATE_DATA}/categories_stats/categories_nutriments_per_country.$country_cc.sto"); } } closedir $dh; diff --git a/lib/ProductOpener/Images.pm b/lib/ProductOpener/Images.pm index eb3b0e6ad83b3..19e3a15c3a567 100644 --- a/lib/ProductOpener/Images.pm +++ b/lib/ProductOpener/Images.pm @@ -125,6 +125,7 @@ use vars @EXPORT_OK; use ProductOpener::Store qw/:all/; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Products qw/:all/; use CGI qw/:cgi :form escapeHTML/; @@ -479,18 +480,18 @@ sub process_search_image_form ($filename_ref) { my $extension = lc($1); my $filename = get_string_id_for_lang("no_language", remote_addr() . '_' . $`); - (-e "$data_root/tmp") or mkdir("$data_root/tmp", 0755); - open(my $out, ">", "$data_root/tmp/$filename.$extension"); + ensure_dir_created_or_die($BASE_DIRS{CACHE_TMP}); + open(my $out, ">", "$BASE_DIRS{CACHE_TMP}/$filename.$extension"); while (my $chunk = <$file>) { print $out $chunk; } close($out); - $code = scan_code("$data_root/tmp/$filename.$extension"); + $code = scan_code("$BASE_DIRS{CACHE_TMP}/$filename.$extension"); if (defined $code) { $code = normalize_code($code); } - ${$filename_ref} = "$data_root/tmp/$filename.$extension"; + ${$filename_ref} = "$BASE_DIRS{CACHE_TMP}/$filename.$extension"; } } return $code; @@ -784,18 +785,13 @@ sub process_image_upload ($product_id, $imagefield, $user_id, $time, $comment, $ # create them # Create the directories for the product - foreach my $current_dir ($product_www_root . "/images/products") { - (-e "$current_dir") or mkdir($current_dir, 0755); - foreach my $component (split("/", $path)) { - $current_dir .= "/$component"; - (-e "$current_dir") or mkdir($current_dir, 0755); - } - } + my $target_image_dir = "$product_www_root/images/products/$path"; + ensure_dir_created_or_die($target_image_dir); - my $lock_path = "$product_www_root/images/products/$path/$imgid.lock"; - while ((-e $lock_path) or (-e "$product_www_root/images/products/$path/$imgid.jpg")) { + my $lock_path = "$target_image_dir/$imgid.lock"; + while ((-e $lock_path) or (-e "$target_image_dir/$imgid.jpg")) { $imgid++; - $lock_path = "$product_www_root/images/products/$path/$imgid.lock"; + $lock_path = "$target_image_dir/$imgid.lock"; } mkdir($lock_path, 0755) @@ -804,7 +800,7 @@ sub process_image_upload ($product_id, $imagefield, $user_id, $time, $comment, $ local $log->context->{imgid} = $imgid; $log->debug("new imgid: ", {imgid => $imgid, extension => $extension}) if $log->is_debug(); - my $img_orig = "$product_www_root/images/products/$path/$imgid.$extension.orig"; + my $img_orig = "$target_image_dir/$imgid.$extension.orig"; $log->debug("writing the original image", {img_orig => $img_orig}) if $log->is_debug(); open(my $out, ">", $img_orig) or $log->warn("could not open image path for saving", {path => $img_orig, error => $!}); @@ -820,7 +816,7 @@ sub process_image_upload ($product_id, $imagefield, $user_id, $time, $comment, $ if (($imagemagick_error) and ($imagemagick_error =~ /(\d+)/) and ($1 >= 400)) { # ImageMagick returns a string starting with a number greater than 400 for errors $log->error("cannot read image", - {path => "$product_www_root/images/products/$path/$imgid.$extension", error => $imagemagick_error}); + {path => "$target_image_dir/$imgid.$extension", error => $imagemagick_error}); $debug .= " - could not read image: $imagemagick_error"; ${$debug_string_ref} = $debug; return -5; @@ -839,7 +835,7 @@ sub process_image_upload ($product_id, $imagefield, $user_id, $time, $comment, $ $source = $bg; } - my $img_jpg = "$product_www_root/images/products/$path/$imgid.jpg"; + my $img_jpg = "$target_image_dir/$imgid.jpg"; $source->Set('quality', 95); $imagemagick_error = $source->Write("jpeg:$img_jpg"); @@ -870,12 +866,12 @@ sub process_image_upload ($product_id, $imagefield, $user_id, $time, $comment, $ # but we stored original PNG files before they were converted to JPG in [imgid].png # We compare both the sizes of the original files and the converted files - my @existing_images = ("$product_www_root/images/products/$path/$i.jpg"); - if (-e "$product_www_root/images/products/$path/$i.$extension.orig") { - push @existing_images, "$product_www_root/images/products/$path/$i.$extension.orig"; + my @existing_images = ("$target_image_dir/$i.jpg"); + if (-e "$target_image_dir/$i.$extension.orig") { + push @existing_images, "$target_image_dir/$i.$extension.orig"; } - if (($extension ne "jpg") and (-e "$product_www_root/images/products/$path/$i.$extension")) { - push @existing_images, "$product_www_root/images/products/$path/$i.$extension"; + if (($extension ne "jpg") and (-e "$target_image_dir/$i.$extension")) { + push @existing_images, "$target_image_dir/$i.$extension"; } foreach my $existing_image (@existing_images) { @@ -909,13 +905,12 @@ sub process_image_upload ($product_id, $imagefield, $user_id, $time, $comment, $ and (defined $product_ref->{images}) and (exists $product_ref->{images}{$i})) { - $log->debug( - "unlinking image", - {imgid => $imgid, file => "$product_www_root/images/products/$path/$imgid.$extension"} - ) if $log->is_debug(); + $log->debug("unlinking image", + {imgid => $imgid, file => "$target_image_dir/$imgid.$extension"}) + if $log->is_debug(); unlink $img_orig; unlink $img_jpg; - rmdir("$product_www_root/images/products/$path/$imgid.lock"); + rmdir("$target_image_dir/$imgid.lock"); ${$imgid_ref} = $i; $debug .= " - we already have an image with this file size: $size - imgid: $i"; ${$debug_string_ref} = $debug; @@ -936,8 +931,8 @@ sub process_image_upload ($product_id, $imagefield, $user_id, $time, $comment, $ or (not defined $options{users_who_can_upload_small_images}{$user_id})) ) { - unlink "$product_www_root/images/products/$path/$imgid.$extension"; - rmdir("$product_www_root/images/products/$path/$imgid.lock"); + unlink "$target_image_dir/$imgid.$extension"; + rmdir("$target_image_dir/$imgid.lock"); $debug .= " - image too small - width: " . $source->Get('width') . " - height: " . $source->Get('height'); ${$debug_string_ref} = $debug; return -4; @@ -972,20 +967,20 @@ sub process_image_upload ($product_id, $imagefield, $user_id, $time, $comment, $ ); _set_magickal_options($img, $w); - $imagemagick_error = $img->Write("jpeg:$product_www_root/images/products/$path/$imgid.$max.jpg"); + $imagemagick_error = $img->Write("jpeg:$target_image_dir/$imgid.$max.jpg"); if (($imagemagick_error) and ($imagemagick_error =~ /(\d+)/) and ($1 >= 400)) { # ImageMagick returns a string starting with a number greater than 400 for errors $log->warn( "could not write jpeg", { - path => "jpeg:$product_www_root/images/products/$path/$imgid.$max.jpg", + path => "jpeg:$target_image_dir/$imgid.$max.jpg", error => $imagemagick_error } ) if $log->is_warn(); last; } else { - $log->info("jpeg written", {path => "jpeg:$product_www_root/images/products/$path/$imgid.$max.jpg"}) + $log->info("jpeg written", {path => "jpeg:$target_image_dir/$imgid.$max.jpg"}) if $log->is_info(); } @@ -1041,7 +1036,7 @@ sub process_image_upload ($product_id, $imagefield, $user_id, $time, $comment, $ (-e "$product_data_root/new_images") or mkdir("$product_data_root/new_images", 0755); my $code = $product_id; $code =~ s/.*\///; - symlink("$product_www_root/images/products/$path/$imgid.jpg", + symlink("$target_image_dir/$imgid.jpg", "$product_data_root/new_images/" . time() . "." . $code . "." . $imagefield . "." . $imgid . ".jpg"); # Save the image file size so that we can skip the image before processing it if it is uploaded again @@ -1054,7 +1049,7 @@ sub process_image_upload ($product_id, $imagefield, $user_id, $time, $comment, $ $imgid = -5; } - rmdir("$product_www_root/images/products/$path/$imgid.lock"); + rmdir("$target_image_dir/$imgid.lock"); # make sure to close the file so that it does not stay in /tmp forever my $tmpfilename = tmpFileName($file); @@ -1116,7 +1111,7 @@ sub process_image_move ($user_id, $code, $imgids, $move_to, $ownerid) { if ($move_to =~ /^((off|obf|opf|opff):)?\d+$/) { $ok = process_image_upload( $move_to_id, - "$www_root/images/products/$path/$imgid.jpg", + "$BASE_DIRS{PRODUCTS_IMAGES}/$path/$imgid.jpg", $product_ref->{images}{$imgid}{uploader}, $product_ref->{images}{$imgid}{uploaded_t}, "image moved from product $code on $server_domain by $user_id -- uploader: $product_ref->{images}{$imgid}{uploader} - time: $product_ref->{images}{$imgid}{uploaded_t}", @@ -1127,7 +1122,7 @@ sub process_image_move ($user_id, $code, $imgids, $move_to, $ownerid) { $log->error( "could not move image to other product", { - source_path => "$www_root/images/products/$path/$imgid.jpg", + source_path => "$BASE_DIRS{PRODUCTS_IMAGES}/$path/$imgid.jpg", move_to => $move_to, old_code => $code, ownerid => $ownerid, @@ -1140,7 +1135,7 @@ sub process_image_move ($user_id, $code, $imgids, $move_to, $ownerid) { $log->info( "moved image to other product", { - source_path => "$www_root/images/products/$path/$imgid.jpg", + source_path => "$BASE_DIRS{PRODUCTS_IMAGES}/$path/$imgid.jpg", move_to => $move_to, old_code => $code, ownerid => $ownerid, @@ -1154,7 +1149,7 @@ sub process_image_move ($user_id, $code, $imgids, $move_to, $ownerid) { $log->info( "moved image to trash", { - source_path => "$www_root/images/products/$path/$imgid.jpg", + source_path => "$BASE_DIRS{PRODUCTS_IMAGES}/$path/$imgid.jpg", old_code => $code, ownerid => $ownerid, user_id => $user_id, @@ -1166,28 +1161,29 @@ sub process_image_move ($user_id, $code, $imgids, $move_to, $ownerid) { # Don't delete images to be moved if they weren't moved correctly if ($ok) { # Delete images (move them to the deleted.images dir - - -e "$data_root/deleted.images" or mkdir("$data_root/deleted.images", 0755); + ensure_dir_created_or_die($BASE_DIRS{DELETED_IMAGES}); File::Copy->import(qw( move )); $log->info( "moving source image to deleted images directory", { - source_path => "$www_root/images/products/$path/$imgid.jpg", - destination_path => "$data_root/deleted.images/product.$code.$imgid.jpg" + source_path => "$BASE_DIRS{PRODUCTS_IMAGES}/$path/$imgid.jpg", + destination_path => "$BASE_DIRS{DELETED_IMAGES}/product.$code.$imgid.jpg" } ); - move("$www_root/images/products/$path/$imgid.jpg", - "$data_root/deleted.images/product.$code.$imgid.jpg"); move( - "$www_root/images/products/$path/$imgid.$thumb_size.jpg", - "$data_root/deleted.images/product.$code.$imgid.$thumb_size.jpg" + "$BASE_DIRS{PRODUCTS_IMAGES}/$path/$imgid.jpg", + "$BASE_DIRS{DELETED_IMAGES}/product.$code.$imgid.jpg" + ); + move( + "$BASE_DIRS{PRODUCTS_IMAGES}/$path/$imgid.$thumb_size.jpg", + "$BASE_DIRS{DELETED_IMAGES}/product.$code.$imgid.$thumb_size.jpg" ); move( - "$www_root/images/products/$path/$imgid.$crop_size.jpg", - "$data_root/deleted.images/product.$code.$imgid.$crop_size.jpg" + "$BASE_DIRS{PRODUCTS_IMAGES}/$path/$imgid.$crop_size.jpg", + "$BASE_DIRS{DELETED_IMAGES}/product.$code.$imgid.$crop_size.jpg" ); delete $product_ref->{images}{$imgid}; @@ -2017,7 +2013,7 @@ sub extract_text_from_image ($product_ref, $id, $field, $ocr_engine, $results_re return; } - my $image = "$www_root/images/products/$path/$filename.full.jpg"; + my $image = "$BASE_DIRS{PRODUCTS_IMAGES}/$path/$filename.full.jpg"; my $image_url = "$images_subdomain/images/products/$path/$filename.full.jpg"; my $text; @@ -2055,8 +2051,8 @@ sub extract_text_from_image ($product_ref, $id, $field, $ocr_engine, $results_re } elsif ($ocr_engine eq 'google_cloud_vision') { - my $json_file = "$www_root/images/products/$path/$filename.json.gz"; - open(my $gv_logs, ">>:encoding(UTF-8)", "$data_root/logs/cloud_vision.log"); + my $json_file = "$BASE_DIRS{PRODUCTS_IMAGES}/$path/$filename.json.gz"; + open(my $gv_logs, ">>:encoding(UTF-8)", "$BASE_DIRS{LOGS}/cloud_vision.log"); my $cloudvision_ref = send_image_to_cloud_vision($image, $json_file, \@CLOUD_VISION_FEATURES_TEXT, $gv_logs); close $gv_logs; diff --git a/lib/ProductOpener/Import.pm b/lib/ProductOpener/Import.pm index 34fe6f0c44851..67a2d2a24c23e 100644 --- a/lib/ProductOpener/Import.pm +++ b/lib/ProductOpener/Import.pm @@ -79,6 +79,7 @@ BEGIN { use vars @EXPORT_OK; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; @@ -166,7 +167,7 @@ sub import_images_from_dir ($image_dir, $stats) { $log->debug("opening images_dir", {images_dir => $image_dir}) if $log->is_debug(); - if (opendir(DH, "$image_dir")) { + if (opendir(DH, $image_dir)) { foreach my $file (sort {$a cmp $b} readdir(DH)) { # apply image rules to the file name to assign front/ingredients/nutrition @@ -1368,7 +1369,7 @@ sub import_csv_file ($args_ref) { if $log->is_debug(); # Load GS1 GLNs so that we can map products to the owner orgs - my $glns_ref = retrieve("$data_root/orgs/orgs_glns.sto"); + my $glns_ref = retrieve("$BASE_DIRS{ORGS}/orgs_glns.sto"); not defined $glns_ref and $glns_ref = {}; my %global_values = (); @@ -1677,7 +1678,7 @@ sub import_csv_file ($args_ref) { = $imported_product_ref->{"sources_fields:org-gs1:partyName"}; } set_org_gs1_gln($org_ref, $imported_product_ref->{"sources_fields:org-gs1:gln"}); - $glns_ref = retrieve("$data_root/orgs/orgs_glns.sto"); + $glns_ref = retrieve("$BASE_DIRS{ORGS}/orgs_glns.sto"); } store_org($org_ref); @@ -2339,7 +2340,7 @@ sub import_csv_file ($args_ref) { if (not -d $images_download_dir) { $log->debug("Creating images_download_dir", {images_download_dir => $images_download_dir}) if $log->is_debug(); - mkdir($images_download_dir, 0755) + ensure_dir_created($images_download_dir) or $log->warn("Could not create images_download_dir", {images_download_dir => $images_download_dir, error => $!}) if $log->is_warn(); @@ -2888,7 +2889,7 @@ sub update_export_status_for_csv_file ($args_ref) { # Update the product without creating a new revision my $path = product_path($product_ref); - store("$data_root/products/$path/product.sto", $product_ref); + store("$BASE_DIRS{PRODUCTS}/$path/product.sto", $product_ref); $product_ref->{code} = $product_ref->{code} . ''; # Use the obsolete collection if the product is obsolete my $products_collection = get_products_collection({obsolete => $product_ref->{obsolete}}); diff --git a/lib/ProductOpener/ImportConvert.pm b/lib/ProductOpener/ImportConvert.pm index 36857a02bc3f0..98f7b831a51f0 100644 --- a/lib/ProductOpener/ImportConvert.pm +++ b/lib/ProductOpener/ImportConvert.pm @@ -103,6 +103,7 @@ BEGIN { use vars @EXPORT_OK; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Tags qw/:all/; use ProductOpener::Products qw/:all/; @@ -1233,7 +1234,7 @@ sub load_xml_file ($file, $xml_rules_ref, $xml_fields_mapping_ref, $code) { if ($log->is_trace()) { binmode STDOUT, ":encoding(UTF-8)"; - open(my $OUT_JSON, ">", "$www_root/data/import_debug_xml.json"); + open(my $OUT_JSON, ">", "$BASE_DIRS{PUBLIC_DATA}/import_debug_xml.json"); print $OUT_JSON encode_json($xml_ref); close($OUT_JSON); } diff --git a/lib/ProductOpener/Index.pm b/lib/ProductOpener/Index.pm index 51f2f8d2d3a08..c6a7bb2309c7c 100644 --- a/lib/ProductOpener/Index.pm +++ b/lib/ProductOpener/Index.pm @@ -43,6 +43,7 @@ use vars @EXPORT_OK; use ProductOpener::Store qw/:all/; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use CGI qw/:standard escape unescape/; use Time::Local; @@ -73,12 +74,12 @@ use HTML::Entities qw(decode_entities); %texts = (); -$lang_dir = "$data_root/lang"; +$lang_dir = $BASE_DIRS{LANG}; if (not -e $lang_dir) { - $lang_dir = "$data_root/lang-default"; + $lang_dir = "$BASE_DIRS{LANG}-default"; $log->warn( - "The $data_root/lang directory does not exist. It should be copied from the openfoodfacts-web repository. Using default texts from $lang_dir" + "The $BASE_DIRS{LANG} directory does not exist. It should be copied from the openfoodfacts-web repository. Using default texts from $lang_dir" ) if $log->is_warn(); } @@ -114,7 +115,7 @@ if (opendir DH2, $lang_dir) { } else { $log->error("Texts could not be loaded.") if $log->is_error(); - die("Texts could not be loaded from $data_root/lang or $data_root/lang-default"); + die("Texts could not be loaded from $BASE_DIRS{LANG} or $BASE_DIRS{LANG}-default"); } # Initialize internal variables diff --git a/lib/ProductOpener/KnowledgePanels.pm b/lib/ProductOpener/KnowledgePanels.pm index 0bbe533a607b4..a17354ab553b1 100644 --- a/lib/ProductOpener/KnowledgePanels.pm +++ b/lib/ProductOpener/KnowledgePanels.pm @@ -55,6 +55,7 @@ BEGIN { use vars @EXPORT_OK; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Tags qw/:all/; use ProductOpener::Products qw/:all/; @@ -355,11 +356,10 @@ sub create_panel_from_json_template ($panel_id, $panel_template, $panel_data_ref my $json_decode_error = $@; # Save the JSON file so that it can be more easily debugged, and that we can monitor issues - my $target_file = "/files/debug/knowledge_panels/$panel_id." . $product_ref->{code} . ".json"; - (-e "$www_root/files") or mkdir("$www_root/files", 0755); - (-e "$www_root/files/debug") or mkdir("$www_root/files/debug", 0755); - (-e "$www_root/files/debug/knowledge_panels") or mkdir("$www_root/files/debug/knowledge_panels", 0755); - open(my $out, ">:encoding(UTF-8)", $www_root . $target_file) or die "cannot open $www_root/$target_file"; + my $target_dir = "$BASE_DIRS{PUBLIC_FILES}/debug/knowledge_panels/"; + my $target_file = "$target_dir/$panel_id." . $product_ref->{code} . ".json"; + ensure_dir_created_or_die($target_dir); + open(my $out, ">:encoding(UTF-8)", $target_file) or die "cannot open $target_file"; print $out $panel_json; close($out); diff --git a/lib/ProductOpener/Lang.pm b/lib/ProductOpener/Lang.pm index 84dedcf7782d2..c52bf444f5704 100644 --- a/lib/ProductOpener/Lang.pm +++ b/lib/ProductOpener/Lang.pm @@ -70,6 +70,7 @@ use vars @EXPORT_OK; use ProductOpener::I18N; use ProductOpener::Store qw/:all/; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use DateTime; use DateTime::Locale; @@ -256,7 +257,7 @@ $log->info("initialize", {data_root => $data_root}) if $log->is_info(); # Load stored %Lang from Lang.sto and Lang_tags.sto -my $path = "$data_root/data/Lang.${server_domain}.sto"; +my $path = "$BASE_DIRS{PRIVATE_DATA}/Lang.${server_domain}.sto"; if (-e $path) { $log->info("Loading \%Lang", {path => $path}) if $log->is_info(); @@ -545,16 +546,14 @@ sub build_lang ($Languages_ref) { sub build_json { $log->info("Building I18N JSON") if $log->is_info(); - my $i18n_root = "$www_root/data/i18n"; + my $i18n_root = "$BASE_DIRS{PUBLIC_DATA}/i18n"; if (!-e $i18n_root) { mkdir($i18n_root, 0755) or die("Could not create target directory $i18n_root : $!\n"); } foreach my $l (@Langs) { my $target_dir = "$i18n_root/$l"; - if (!-e $target_dir) { - mkdir($target_dir, 0755) or die("Could not create target directory $target_dir : $!\n"); - } + ensure_dir_created_or_die($target_dir); my $short_l = undef; if ($l =~ /_/) { diff --git a/lib/ProductOpener/Mail.pm b/lib/ProductOpener/Mail.pm index 98e26b13a2a77..ea79415d76564 100644 --- a/lib/ProductOpener/Mail.pm +++ b/lib/ProductOpener/Mail.pm @@ -64,6 +64,7 @@ use vars @EXPORT_OK; use ProductOpener::Store qw/:all/; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Lang qw/:all/; use Email::Stuffer; use Log::Any qw($log); @@ -197,7 +198,7 @@ sub send_html_email ($user_ref, $subject, $html_content) { =head2 get_html_email_content ($filename, $lang ) -Fetch the HTML email content in $DATA_ROOT/lang/emails. If a translation is available +Fetch the HTML email content in $BASE_DIRS{LANG}/emails. If a translation is available for the requested language, we provide the translated version otherwise English is the default. @@ -219,10 +220,10 @@ The HTML string or undef if the file does not exists or is not readable. sub get_html_email_content ($filename, $lang) { # if an email does not exist in the local language, use the English version - my $file = "$data_root/lang/$lang/emails/$filename"; + my $file = "$BASE_DIRS{LANG}/$lang/emails/$filename"; if (!-e $file) { - $file = "$data_root/lang/en/emails/$filename"; + $file = "$BASE_DIRS{LANG}/en/emails/$filename"; } open(my $IN, "<:encoding(UTF-8)", $file) or $log->error("Can't open $file for reading"); diff --git a/lib/ProductOpener/MainCountries.pm b/lib/ProductOpener/MainCountries.pm index 77d060ca9a0fd..27a60425a28e1 100644 --- a/lib/ProductOpener/MainCountries.pm +++ b/lib/ProductOpener/MainCountries.pm @@ -67,6 +67,7 @@ BEGIN { use vars @EXPORT_OK; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Tags qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Products qw/:all/; @@ -84,7 +85,7 @@ my $all_products_scans_ref; sub load_scans_data() { - $all_products_scans_ref = retrieve_json("$data_root/products/all_products_scans.json"); + $all_products_scans_ref = retrieve_json("$BASE_DIRS{PRODUCTS}/all_products_scans.json"); return; } @@ -118,7 +119,7 @@ sub compute_main_countries ($product_ref) { # Load the scan data my $path = product_path($product_ref); - my $scans_ref = retrieve_json("$data_root/products/$path/scans.json"); + my $scans_ref = retrieve_json("$BASE_DIRS{PRODUCTS}/$path/scans.json"); if ((defined $all_products_scans_ref) and (defined $scans_ref)) { diff --git a/lib/ProductOpener/Missions.pm b/lib/ProductOpener/Missions.pm index 00150c6cfec38..29a115783b797 100644 --- a/lib/ProductOpener/Missions.pm +++ b/lib/ProductOpener/Missions.pm @@ -37,6 +37,7 @@ use vars @EXPORT_OK; use ProductOpener::Store qw/:all/; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Users qw/:all/; use ProductOpener::Products qw/:all/; use ProductOpener::Display qw/:all/; @@ -53,6 +54,8 @@ sub gen_missions_html() { foreach my $l (keys %Missions_by_lang) { $lang = $l; + my $mission_lang_dir = "$BASE_DIRS{PUBLIC_DATA}/missions/$lang"; + ensure_dir_created_or_die($mission_lang_dir); my $html = '
    '; @@ -125,15 +128,19 @@ sub gen_missions_html() { . "\">$Lang{all_missions}{$lang}

    "; $missionid =~ s/(.*)\.//; - (-e "$data_root/lang/$lang/missions") or mkdir("$data_root/lang/$lang/missions", 0755); - open(my $OUT, ">:encoding(UTF-8)", "$data_root/lang/$lang/missions/$missionid.html"); + open(my $OUT, ">:encoding(UTF-8)", "$mission_lang_dir/$missionid.html"); print $OUT $html2; close $OUT; } $html .= "
"; - open(my $OUT, ">:encoding(UTF-8)", "$data_root/lang/$lang/texts/missions_list.html"); + # FIXME: to reactivate missions list functionality, + # we would need to add a symlink to missions_list in openfoodfacts-web, + # or change display_text or display.pl to fetch file in the right directory + # for now it's disabled + die("FIX: see comment to reactivate missions list functionality"); + open(my $OUT, ">:encoding(UTF-8)", "$mission_lang_dir/missions_list.html"); print $OUT $html; close $OUT; } @@ -143,7 +150,7 @@ sub gen_missions_html() { sub compute_missions() { - opendir DH, "$data_root/users" or die "Couldn't open the current directory: $!"; + opendir DH, $BASE_DIRS{USERS} or die "Couldn't open the current directory: $!"; my @userids = sort(readdir(DH)); closedir(DH); @@ -159,11 +166,11 @@ sub compute_missions() { $log->debug("userid without extension", {userid => $userid}) if $log->is_debug(); - my $user_ref = retrieve("$data_root/users/$userid.sto"); + my $user_ref = retrieve("$BASE_DIRS{USERS}/$userid.sto"); compute_missions_for_user($user_ref); - store("$data_root/users/$userid.sto", $user_ref); + store("$BASE_DIRS{USERS}/$userid.sto", $user_ref); foreach my $missionid (keys %{$user_ref->{missions}}) { (defined $missions_ref->{$missionid}) or $missions_ref->{$missionid} = {}; diff --git a/lib/ProductOpener/Orgs.pm b/lib/ProductOpener/Orgs.pm index 65a23b07f9c69..211087452184a 100644 --- a/lib/ProductOpener/Orgs.pm +++ b/lib/ProductOpener/Orgs.pm @@ -66,6 +66,7 @@ use vars @EXPORT_OK; use ProductOpener::Store qw/:all/; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Mail qw/:all/; use ProductOpener::Lang qw/:all/; use ProductOpener::Display qw/:all/; @@ -78,16 +79,12 @@ use Log::Any qw($log); =head1 DATA -Organization profile data is kept in files in the $data_root/orgs directory. +Organization profile data is kept in files in the $BASE_DIRS{ORGS} directory. If it does not exist yet, the directory is created when the module is initialized. =cut -if (!-e "$data_root/orgs") { - mkdir("$data_root/orgs", 0755) - or $log->warn("Could not create orgs dir", {dir => "$data_root/orgs", error => $!}) - if $log->is_warn(); -} +ensure_dir_created($BASE_DIRS{ORGS}); =head1 FUNCTIONS @@ -112,8 +109,7 @@ sub retrieve_org ($org_id_or_name) { $log->debug("retrieve_org", {org_id_or_name => $org_id_or_name, org_id => $org_id}) if $log->is_debug(); if (defined $org_id and $org_id ne "") { - - my $org_ref = retrieve("$data_root/orgs/$org_id.sto"); + my $org_ref = retrieve("$BASE_DIRS{ORGS}/$org_id.sto"); return $org_ref; } @@ -132,7 +128,7 @@ This function returns an array of all existing org ids sub list_org_ids () { # all .sto but orgs_glns - my @org_files = glob("$data_root/orgs/*.sto"); + my @org_files = glob("$BASE_DIRS{ORGS}/*.sto"); # id is the filename without .sto my @org_ids = map {$_ =~ /\/([^\/]+).sto/;} @org_files; # remove "orgs_glns" @@ -163,14 +159,14 @@ sub store_org ($org_ref) { defined $org_ref->{org_id} or die("Missing org_id"); # retrieve eventual previous values - my $previous_org_ref = retrieve("$data_root/orgs/" . $org_ref->{org_id} . ".sto"); + my $previous_org_ref = retrieve("$BASE_DIRS{ORGS}/" . $org_ref->{org_id} . ".sto"); if ((defined $previous_org_ref) && !$previous_org_ref->{validated} && $org_ref->{validated}) { # we switched on validated # TODO: create org and its users in Odoo CRM } - store("$data_root/orgs/" . $org_ref->{org_id} . ".sto", $org_ref); + store("$BASE_DIRS{ORGS}/" . $org_ref->{org_id} . ".sto", $org_ref); return; } @@ -285,7 +281,7 @@ This function returns a hash ref for the org. sub set_org_gs1_gln ($org_ref, $list_of_gs1_gln) { # Remove existing GLNs - my $glns_ref = retrieve("$data_root/orgs/orgs_glns.sto"); + my $glns_ref = retrieve("$BASE_DIRS{ORGS}/orgs_glns.sto"); not defined $glns_ref and $glns_ref = {}; if (defined $org_ref->{list_of_gs1_gln}) { foreach my $gln (split(/,| /, $org_ref->{list_of_gs1_gln})) { @@ -305,7 +301,7 @@ sub set_org_gs1_gln ($org_ref, $list_of_gs1_gln) { } } } - store("$data_root/orgs/orgs_glns.sto", $glns_ref); + store("$BASE_DIRS{ORGS}/orgs_glns.sto", $glns_ref); return; } diff --git a/lib/ProductOpener/Packaging.pm b/lib/ProductOpener/Packaging.pm index bbb6fc6f1f29d..86458ebb40f35 100644 --- a/lib/ProductOpener/Packaging.pm +++ b/lib/ProductOpener/Packaging.pm @@ -61,6 +61,7 @@ BEGIN { use vars @EXPORT_OK; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Images qw/:all/; use ProductOpener::Tags qw/:all/; use ProductOpener::Store qw/:all/; @@ -77,12 +78,12 @@ my $categories_packagings_materials_stats_ref; sub load_categories_packagings_materials_stats() { if (not defined $categories_packagings_materials_stats_ref) { - my $file = "$data_root/data/categories_stats/categories_packagings_materials_stats.all.popular.json"; + my $file = "$BASE_DIRS{PRIVATE_DATA}/categories_stats/categories_packagings_materials_stats.all.popular.json"; # In dev environments, we provide a sample stats file in the data-default directory # so that we can run tests with meaningful and unchanging data if (!-e $file) { my $default_file - = "$data_root/data-default/categories_stats/categories_packagings_materials_stats.all.popular.json"; + = "$BASE_DIRS{PRIVATE_DATA}-default/categories_stats/categories_packagings_materials_stats.all.popular.json"; $log->debug("local packaging stats file does not exist, will use default", {file => $file, default_file => $default_file}) if $log->is_debug(); diff --git a/lib/ProductOpener/PackagingStats.pm b/lib/ProductOpener/PackagingStats.pm index 81cca240a6084..17a5684fe99bb 100755 --- a/lib/ProductOpener/PackagingStats.pm +++ b/lib/ProductOpener/PackagingStats.pm @@ -88,6 +88,7 @@ use vars @EXPORT_OK; use ProductOpener::PerlStandards; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Tags qw/:all/; use ProductOpener::Products qw/:all/; @@ -333,35 +334,29 @@ Store the stats in JSON format for internal use in Product Opener and store a co sub store_stats ($name, $packagings_stats_ref, $packagings_materials_stats_ref) { # Create directories for the output if they do not exist yet + ensure_dir_created_or_die("$BASE_DIRS{PRIVATE_DATA}/categories_stats"); + ensure_dir_created_or_die("$BASE_DIRS{PUBLIC_DATA}/categories_stats"); - (-e "$data_root/data") - or mkdir("$data_root/data", oct(755)) - or die("Could not create target directory $data_root/data : $!\n"); - (-e "$data_root/data/categories_stats") - or mkdir("$data_root/data/categories_stats", oct(755)) - or die("Could not create target directory $data_root/data/categories_stats : $!\n"); - (-e "$www_root/data/categories_stats") - or mkdir("$www_root/data/categories_stats", oct(755)) - or die("Could not create target directory $www_root/data/categories_stats : $!\n"); - - # Packaging stats for packaging components - store_json("$data_root/data/categories_stats/categories_packagings_stats.$name.json", $packagings_stats_ref); - store_json("$www_root/data/categories_stats/categories_packagings_stats.$name.json", $packagings_stats_ref); - - # Packaging stats for products - store_json("$data_root/data/categories_stats/categories_packagings_materials_stats.$name.json", + # Packaging stats for packaging components + store_json("$BASE_DIRS{PRIVATE_DATA}/categories_stats/categories_packagings_stats.$name.json", + $packagings_stats_ref); + store_json("$BASE_DIRS{PUBLIC_DATA}/categories_stats/categories_packagings_stats.$name.json", + $packagings_stats_ref); + + # Packaging stats for products + store_json("$BASE_DIRS{PRIVATE_DATA}/categories_stats/categories_packagings_materials_stats.$name.json", $packagings_materials_stats_ref); - store_json("$www_root/data/categories_stats/categories_packagings_materials_stats.$name.json", + store_json("$BASE_DIRS{PUBLIC_DATA}/categories_stats/categories_packagings_materials_stats.$name.json", $packagings_materials_stats_ref); # special export for French yogurts for the "What's around my yogurt?" operation in January 2023 # https://fr.openfoodfacts.org/categorie/desserts-lactes-fermentes/misc/en:packagings-with-weights store_json( - "$www_root/data/categories_stats/categories_packagings_stats.fr.fermented-dairy-desserts.$name.json", + "$BASE_DIRS{PUBLIC_DATA}/categories_stats/categories_packagings_stats.fr.fermented-dairy-desserts.$name.json", $packagings_stats_ref->{countries}{"en:france"}{categories}{"en:fermented-dairy-desserts"} ); store_json( - "$www_root/data/categories_stats/categories_packagings_materials_stats.fr.fermented-dairy-desserts.$name.json", + "$BASE_DIRS{PUBLIC_DATA}/categories_stats/categories_packagings_materials_stats.fr.fermented-dairy-desserts.$name.json", $packagings_materials_stats_ref->{countries}{"en:france"}{categories}{"en:fermented-dairy-desserts"} ); @@ -383,7 +378,7 @@ Open a file, initialize a Text::CSV object, and output the CSV header for packag sub init_products_packaging_components_csv ($name) { my $filehandle; - my $filename = "$www_root/data/packagings.$name.csv"; + my $filename = "$BASE_DIRS{PUBLIC_DATA}/packagings.$name.csv"; open($filehandle, ">:encoding(UTF-8)", $filename) or die("Could not write " . $filename . " : $!\n"); my $csv = Text::CSV->new( @@ -607,8 +602,8 @@ sub compute_stats_for_all_materials ($packagings_materials_stats_ref, $delete_va Generate packaging stats for products matching a specific query. -Stats are saved in .json format in $data_root/data/categories_stats/ -and in JSON format in $www_root/data/categories_stats/ +Stats are saved in .json format in $BASE_DIRS{PRIVATE_DATA}/categories_stats/ +and in JSON format in $BASE_DIRS{PUBLIC_DATA}/categories_stats/ =head3 Arguments diff --git a/lib/ProductOpener/Paths.pm b/lib/ProductOpener/Paths.pm new file mode 100644 index 0000000000000..9b6ed05c4f330 --- /dev/null +++ b/lib/ProductOpener/Paths.pm @@ -0,0 +1,346 @@ +# This file is part of Product Opener. +# +# Product Opener +# Copyright (C) 2011-2023 Association Open Food Facts +# Contact: contact@openfoodfacts.org +# Address: 21 rue des Iles, 94100 Saint-Maur des Fossés, France +# +# Product Opener is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +=head1 NAME + +ProductOpener::Paths - functions to get, check and initialize important directories + +=head1 SYNOPSIS + +… + +=cut + +package ProductOpener::Paths; + +use ProductOpener::PerlStandards; +use Exporter qw< import >; + +use Log::Any qw($log); + +BEGIN { + use vars qw(@ISA @EXPORT_OK %EXPORT_TAGS); + @EXPORT_OK = qw( + %BASE_DIRS + + &base_paths + &base_paths_loading_script + &check_missing_dirs + &ensure_dir_created + &ensure_dir_created_or_die + ); # symbols to export on request + %EXPORT_TAGS = (all => [@EXPORT_OK]); +} + +use vars @EXPORT_OK; + +use ProductOpener::Config qw/:all/; + +=head1 VARIABLES + +=cut + +=head2 %BASE_DIRS +A hashmap containing references to base directories +=cut + +%BASE_DIRS = (); + +=head3 $BASE_DIRS{LOGS} +Directory for logging +=cut + +$BASE_DIRS{LOGS} = "$data_root/logs"; + +=head2 $BASE_DIRS{ORGS} +Directory containing sto of organizations +=cut + +$BASE_DIRS{ORGS} = "$data_root/orgs"; + +=head2 $BASE_DIRS{USERS} +Directory containing sto of users +=cut + +$BASE_DIRS{USERS} = "$data_root/users"; + +=head2 $BASE_DIRS{PRODUCTS} +Directory containing sto of products +=cut + +$BASE_DIRS{PRODUCTS} = "$data_root/products"; + +=head2 $BASE_DIRS{PRIVATE_DATA} +Directory for private data +=cut + +$BASE_DIRS{PRIVATE_DATA} = "$data_root/data"; + +=head2 $BASE_DIRS{LANG} +Directory with language files (.po). Normally linked to openfoodfacts-web +=cut + +$BASE_DIRS{LANG} = "$data_root/lang"; + +=head2 $BASE_DIRS{IMPORT_FILES} +files to import in producer platform +=cut + +$BASE_DIRS{IMPORT_FILES} = "$data_root/import_files"; + +=head2 $BASE_DIRS{EXPORT_FILES} +files to export from producer platform to public platform +=cut + +$BASE_DIRS{EXPORT_FILES} = "$data_root/export_files"; + +=head2 $BASE_DIRS{PRODUCTS_IMAGES} +product images is a big directory, normally a volume of its own +=cut + +$BASE_DIRS{PRODUCTS_IMAGES} = "$www_root/images/products"; + +=head2 $BASE_DIRS{CACHE_TMP} +temporary files we manage locally +=cut + +$BASE_DIRS{CACHE_TMP} = "$data_root/tmp"; + +=head2 $BASE_DIRS{CACHE_NEW_IMAGES} +A directory to link newly updated images in order to apply processing (like OCR) +=cut + +$BASE_DIRS{CACHE_NEW_IMAGES} = "$data_root/new_images"; + +=head2 $BASE_DIRS{CACHE_DEBUG} +Temporary files for debugging purposes +=cut + +$BASE_DIRS{CACHE_DEBUG} = "$data_root/debug"; + +=head2 $BASE_DIRS{CACHE_BUILD} +Files needed for various build phases - eg taxonomy and cached +=cut + +$BASE_DIRS{CACHE_BUILD} = "$data_root/build-cache"; + +=head2 $BASE_DIRS{DELETED_PRODUCTS} +Products deleted from the public platform +=cut + +$BASE_DIRS{DELETED_PRODUCTS} = "$data_root/deleted_products"; + +=head2 $BASE_DIRS{DELETED_PRODUCTS_IMAGES} +Products deleted from the public platform +=cut + +$BASE_DIRS{DELETED_PRODUCTS_IMAGES} = "$data_root/deleted_products_images"; + +=head2 $BASE_DIRS{DELETED_PRIVATE_PRODUCTS} +Products deleted from the producers platform +=cut + +$BASE_DIRS{DELETED_PRIVATE_PRODUCTS} = "$data_root/deleted_private_products"; + +=head2 $BASE_DIRS{DELETED_IMAGES} +A directory to store deleted images (not accessible from web) +=cut + +$BASE_DIRS{DELETED_IMAGES} = "$data_root/deleted.images"; + +=head2 $BASE_DIRS{REVERTED_PRODUCTS} +A directory where we store revisions we reverted for some products +=cut + +$BASE_DIRS{REVERTED_PRODUCTS} = "$data_root/reverted_products"; + +=head2 $BASE_DIRS{FILES_DEBUG} +A directory used to debug knowledge panels +=cut + +$BASE_DIRS{FILES_DEBUG} = "$www_root/files/debug"; + +=head2 $BASE_DIRS{PUBLIC_DATA} +The main public data directory where database dumps are published along with other assets +=cut + +$BASE_DIRS{PUBLIC_DATA} = "$www_root/data"; + +# FIXME: can we move those in PUBLIC_DATA_DIR ? + +=head2 $BASE_DIRS{PUBLIC_DUMP} +=cut + +$BASE_DIRS{PUBLIC_DUMP} = "$www_root/dump"; + +=head2 $BASE_DIRS{PUBLIC_FILES} +=cut + +$BASE_DIRS{PUBLIC_FILES} = "$www_root/files"; + +=head2 $BASE_DIRS{PUBLIC_EXPORTS} +=cut + +$BASE_DIRS{PUBLIC_EXPORTS} = "$www_root/exports"; + +=head2 $BASE_DIRS{USERS_TRANSLATIONS} +Users contributed translations directory +=cut + +$BASE_DIRS{USERS_TRANSLATIONS} = "$data_root/translate"; + +=head2 $BASE_DIRS{SFTP_HOME} +sftp home directory, only for producers platform +=cut + +$BASE_DIRS{SFTP_HOME} = $sftp_root; + +my @PRO_ONLY_PATHS = qw(SFTP_HOME); + +=head1 FUNCTIONS + +=head2 products_dir($server_name) +products directory for a foreign server +=head3 Arguments +=head4 $server_name - off/obf/opf/opff… +=head3 Return +String of path to base directory containing products sto +=cut + +sub products_dir ($server_name) { + my $server_data_root = $options{other_servers}{$server_name}{data_root}; + return "$server_data_root/products"; +} + +=head2 products_images_dir($server_name) +products images directory for a foreign server +=head3 Arguments +=head4 $server_name - off/obf/opf/opff… +=head3 Return +String of path to base directory containing products images +=cut + +sub products_images_dir ($server_name) { + my $server_www_root = $options{other_servers}{$server_name}{www_root}; + return "$server_www_root/images/products"; +} + +=head2 base_paths() +Return the list of base paths as a hashmap +=cut + +sub base_paths() { + my %paths = (%BASE_DIRS); + if (!$server_options{producers_platform}) { + # on non pro instances, + # also add foreign projects dirs for products migrations + my $servers_options = $options{other_servers}; + foreach my $server_name (keys %{$servers_options}) { + if ($server_name eq $options{current_server}) { + next; + } + $paths{uc($server_name) . "_PRODUCTS_DIR"} = products_dir($server_name); + $paths{uc($server_name) . "_PRODUCTS_IMAGES_DIR"} = products_images_dir($server_name); + } + # remove some paths + foreach my $path (@PRO_ONLY_PATHS) { + delete $paths{$path}; + } + } + return \%paths; +} + +=head2 check_missing_dirs() +Check main directories, needed for the project to run, exists +=head3 Return +A ref to a list of missing paths +=cut + +sub check_missing_dirs() { + my @to_check = (values %{base_paths()}); + $log->debug("check_missing_dirs - to check: " . (join ":", @to_check)) if $log->is_debug; + + my @missing = grep {!(-e $_)} @to_check; + + return \@missing; +} + +=head2 ensure_dir_created($path, $mode=oct(755)) +Ensure a multiple path is created but die if a fundamental path is missing +=cut + +sub ensure_dir_created ($path, $mode = oct(755)) { + # search base directory + my $prefix; + my $suffix; + my @base_dirs = (values %{base_paths()}); + foreach my $prefix_candidate (@base_dirs) { + if ($path =~ /^$prefix_candidate/) { + $prefix = $prefix_candidate; + $suffix = $'; + last; + } + } + if (!defined $prefix) { + $log->error("Could not create $path, no corresponding base directory found in " . join(":", @base_dirs)); + return; + } + # ensure the rest of the path + foreach my $component (split(/\//, $suffix)) { + $prefix .= "/$component"; + (-e $prefix) or mkdir($prefix); + } + return (-e $path); +} + +=head2 ensure_dir_created_or_die($path, $mode=0755) +Ensure a multiple path is created but die if a fundamental path is missing +=cut + +sub ensure_dir_created_or_die ($path, $mode = 0755) { + my $result = ensure_dir_created($path, $mode); + if (!$result) { + die("Could not create target directory $path : $!\n"); + } + return $result; +} + +=head2 base_paths_loading_script() +Return a sh script to define environment variables + +You can then use it in a script by running: + +C<< . <(perl -e 'use ProductOpener::Paths qw/:all/; print base_paths_loading_script()') >> + +=cut + +sub base_paths_loading_script() { + my %paths = %{base_paths()}; + my @outputs = (); + foreach my $path_name (keys %paths) { + my $value = $paths{$path_name}; + if (defined $value) { + push @outputs, "export OFF_${path_name}_DIR=$value"; + } + } + return (join "\n", @outputs) . "\n"; +} + +1; diff --git a/lib/ProductOpener/Producers.pm b/lib/ProductOpener/Producers.pm index 857cb12f39b1d..bf0f8a415fb90 100644 --- a/lib/ProductOpener/Producers.pm +++ b/lib/ProductOpener/Producers.pm @@ -73,6 +73,7 @@ BEGIN { use vars @EXPORT_OK; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Tags qw/:all/; use ProductOpener::Products qw/:all/; @@ -852,13 +853,9 @@ sub init_fields_columns_names_for_lang ($l) { } $fields_columns_names_for_lang{$l}{"kj"} = {field => "energy-kj_100g_value_unit", value_unit => "value_in_kj"}; - if (!-e "$data_root/debug") { - mkdir("$data_root/debug", 0755) - or $log->warn("Could not create debug dir", {dir => "$data_root/debug", error => $!}) - if $log->is_warn(); - } + ensure_dir_created($BASE_DIRS{CACHE_DEBUG}); - store("$data_root/debug/fields_columns_names_$l.sto", $fields_columns_names_for_lang{$l}); + store("$BASE_DIRS{CACHE_DEBUG}/fields_columns_names_$l.sto", $fields_columns_names_for_lang{$l}); return $fields_columns_names_for_lang{$l}; } @@ -1443,7 +1440,7 @@ sub init_columns_fields_match ($input_headers_ref, $rows_ref) { my $all_columns_fields_ref = {}; if (defined $Owner_id) { - $all_columns_fields_ref = retrieve("$data_root/import_files/${Owner_id}/all_columns_fields.sto"); + $all_columns_fields_ref = retrieve("$BASE_DIRS{IMPORT_FILES}/${Owner_id}/all_columns_fields.sto"); } # Match known column names to OFF fields @@ -1800,12 +1797,12 @@ sub export_and_import_to_public_database ($args_ref) { my $started_t = time(); my $export_id = $started_t; - my $exports_ref = retrieve("$data_root/export_files/${Owner_id}/exports.sto"); + my $exports_ref = retrieve("$BASE_DIRS{EXPORT_FILES}/${Owner_id}/exports.sto"); if (not defined $exports_ref) { $exports_ref = {}; } - my $exported_file = "$data_root/export_files/${Owner_id}/export.$export_id.exported.csv"; + my $exported_file = "$BASE_DIRS{EXPORT_FILES}/${Owner_id}/export.$export_id.exported.csv"; $exports_ref->{$export_id} = { started_t => $started_t, @@ -1891,10 +1888,9 @@ sub export_and_import_to_public_database ($args_ref) { $exports_ref->{$export_id}{remote_import_job_id} = $remote_import_job_id; $exports_ref->{$export_id}{local_export_status_job_id} = $local_export_status_job_id; - (-e "$data_root/export_files") or mkdir("$data_root/export_files", 0755); - (-e "$data_root/export_files/${Owner_id}") or mkdir("$data_root/export_files/${Owner_id}", 0755); + ensure_dir_created_or_die("$BASE_DIRS{EXPORT_FILES}/${Owner_id}"); - store("$data_root/export_files/${Owner_id}/exports.sto", $exports_ref); + store("$BASE_DIRS{EXPORT_FILES}/${Owner_id}/exports.sto", $exports_ref); return { export_id => $export_id, @@ -1937,7 +1933,7 @@ sub import_csv_file_task ($job, $args_ref) { my $job_id = $job->{id}; - open(my $log, ">>", "$data_root/logs/minion.log"); + open(my $log, ">>", "$BASE_DIRS{LOGS}/minion.log"); print $log "import_csv_file_task - job: $job_id started - args: " . encode_json($args_ref) . "\n"; close($log); @@ -1958,7 +1954,7 @@ sub export_csv_file_task ($job, $args_ref) { my $job_id = $job->{id}; - open(my $minion_log, ">>", "$data_root/logs/minion.log"); + open(my $minion_log, ">>", "$BASE_DIRS{LOGS}/minion.log"); print $minion_log "export_csv_file_task - job: $job_id started - args: " . encode_json($args_ref) . "\n"; close($minion_log); @@ -1978,7 +1974,7 @@ sub export_csv_file_task ($job, $args_ref) { print STDERR "export_csv_file_task - job: $job_id - done\n"; - open(my $log, ">>", "$data_root/logs/minion.log"); + open(my $log, ">>", "$BASE_DIRS{LOGS}/minion.log"); print $log "export_csv_file_task - job: $job_id done\n"; close($log); @@ -1993,7 +1989,7 @@ sub import_products_categories_from_public_database_task ($job, $args_ref) { my $job_id = $job->{id}; - open(my $minion_log, ">>", "$data_root/logs/minion.log"); + open(my $minion_log, ">>", "$BASE_DIRS{LOGS}/minion.log"); print $minion_log "import_products_categories_from_public_database_file_task - job: $job_id started - args: " . encode_json($args_ref) . "\n"; close($minion_log); @@ -2005,7 +2001,7 @@ sub import_products_categories_from_public_database_task ($job, $args_ref) { print STDERR "import_products_categories_from_public_database_file_task - job: $job_id - done\n"; - open(my $log, ">>", "$data_root/logs/minion.log"); + open(my $log, ">>", "$BASE_DIRS{LOGS}/minion.log"); print $log "import_products_categories_from_public_database_file_task - job: $job_id done\n"; close($log); @@ -2020,7 +2016,7 @@ sub update_export_status_for_csv_file_task ($job, $args_ref) { my $job_id = $job->{id}; - open(my $minion_log, ">>", "$data_root/logs/minion.log"); + open(my $minion_log, ">>", "$BASE_DIRS{LOGS}/minion.log"); print $minion_log "update_export_status_for_csv_file_task - job: $job_id started - args: " . encode_json($args_ref) . "\n"; close($minion_log); @@ -2032,7 +2028,7 @@ sub update_export_status_for_csv_file_task ($job, $args_ref) { print STDERR "update_export_status_for_csv_file_task - job: $job_id - done\n"; - open(my $log, ">>", "$data_root/logs/minion.log"); + open(my $log, ">>", "$BASE_DIRS{LOGS}/minion.log"); print $log "update_export_status_file_task - job: $job_id done\n"; close($log); diff --git a/lib/ProductOpener/Products.pm b/lib/ProductOpener/Products.pm index 9604b978fef54..129aed5723fd0 100644 --- a/lib/ProductOpener/Products.pm +++ b/lib/ProductOpener/Products.pm @@ -129,6 +129,7 @@ use vars @EXPORT_OK; use ProductOpener::Store qw/:all/; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Users qw/:all/; use ProductOpener::Orgs qw/:all/; use ProductOpener::Lang qw/:all/; @@ -241,20 +242,20 @@ sub assign_new_code() { my $code = 2000000000001; # Codes beginning with 2 are for internal use - my $internal_code_ref = retrieve("$data_root/products/internal_code.sto"); + my $internal_code_ref = retrieve("$BASE_DIRS{PRODUCTS}/internal_code.sto"); if ((defined $internal_code_ref) and (${$internal_code_ref} > $code)) { $code = ${$internal_code_ref}; } my $product_id = product_id_for_owner($Owner_id, $code); - while (-e ("$data_root/products/" . product_path_from_id($product_id))) { + while (-e ("$BASE_DIRS{PRODUCTS}/" . product_path_from_id($product_id))) { $code++; $product_id = product_id_for_owner($Owner_id, $code); } - store("$data_root/products/internal_code.sto", \$code); + store("$BASE_DIRS{PRODUCTS}/internal_code.sto", \$code); $log->debug("assigning a new code", {code => $code, lc => $lc}) if $log->is_debug(); @@ -638,7 +639,7 @@ sub product_id_from_path ($product_path) { $id = dirname($id); } # eventually remove root path - my $root = quotemeta("$data_root/products/"); + my $root = quotemeta("$BASE_DIRS{PRODUCTS}/"); $id =~ s/^$root//; # transform to id by simply removing "/" $id =~ s/\///g; @@ -1221,13 +1222,8 @@ sub store_product ($user_id, $product_ref, $comment) { $log->debug("creating product directories", {path => $path, prefix_path => $prefix_path}) if $log->is_debug(); # Create the directories for the product - foreach my $current_dir ($new_data_root . "/products", $new_www_root . "/images/products") { - (-e "$current_dir") or mkdir($current_dir, 0755) or die("could not create $current_dir: $!\n"); - foreach my $component (split("/", $prefix_path)) { - $current_dir .= "/$component"; - (-e "$current_dir") or mkdir($current_dir, 0755) or die("could not create $current_dir: $!\n"); - } - } + ensure_dir_created_or_die("$new_data_root/products/$prefix_path"); + ensure_dir_created_or_die("$new_www_root/images/products/$prefix_path"); if ( (!-e "$new_data_root/products/$path") and (!-e "$new_www_root/images/products/$path")) @@ -1247,21 +1243,26 @@ sub store_product ($user_id, $product_ref, $comment) { File::Copy::Recursive->import(qw( dirmove )); $log->debug("moving product data", - {source => "$data_root/products/$old_path", destination => "$data_root/products/$path"}) + {source => "$BASE_DIRS{PRODUCTS}/$old_path", destination => "$BASE_DIRS{PRODUCTS}/$path"}) if $log->is_debug(); - dirmove("$data_root/products/$old_path", "$new_data_root/products/$path") - or $log->error("could not move product data", - {source => "$data_root/products/$old_path", destination => "$data_root/products/$path", error => $!}); + dirmove("$BASE_DIRS{PRODUCTS}/$old_path", "$new_data_root/products/$path") + or $log->error( + "could not move product data", + {source => "$BASE_DIRS{PRODUCTS}/$old_path", destination => "$BASE_DIRS{PRODUCTS}/$path", error => $!} + ); $log->debug( "moving product images", - {source => "$www_root/images/products/$old_path", destination => "$new_www_root/images/products/$path"} + { + source => "$BASE_DIRS{PRODUCTS_IMAGES}/$old_path", + destination => "$new_www_root/images/products/$path" + } ) if $log->is_debug(); - dirmove("$www_root/images/products/$old_path", "$new_www_root/images/products/$path") + dirmove("$BASE_DIRS{PRODUCTS_IMAGES}/$old_path", "$new_www_root/images/products/$path") or $log->error( "could not move product images", { - source => "$www_root/images/products/$old_path", + source => "$BASE_DIRS{PRODUCTS_IMAGES}/$old_path", destination => "$new_www_root/images/products/$path", error => $! } @@ -1282,11 +1283,15 @@ sub store_product ($user_id, $product_ref, $comment) { else { (-e "$new_data_root/products/$path") and $log->error("cannot move product data, because the destination already exists", - {source => "$data_root/products/$old_path", destination => "$data_root/products/$path"}); - (-e "$new_www_root/products/$path") and $log->error( + {source => "$BASE_DIRS{PRODUCTS}/$old_path", destination => "$BASE_DIRS{PRODUCTS}/$path"}); + (-e "$new_www_root/products/$path") + and $log->error( "cannot move product images data, because the destination already exists", - {source => "$www_root/images/products/$old_path", destination => "$new_www_root/images/products/$path"} - ); + { + source => "$BASE_DIRS{PRODUCTS_IMAGES}/$old_path", + destination => "$new_www_root/images/products/$path" + } + ); } $comment .= " - barcode changed from $old_code to $code by $user_id"; @@ -1294,13 +1299,8 @@ sub store_product ($user_id, $product_ref, $comment) { if ($rev < 1) { # Create the directories for the product - foreach my $current_dir ($new_data_root . "/products", $new_www_root . "/images/products") { - (-e "$current_dir") or mkdir($current_dir, 0755); - foreach my $component (split("/", $path)) { - $current_dir .= "/$component"; - (-e "$current_dir") or mkdir($current_dir, 0755); - } - } + ensure_dir_created_or_die("$new_data_root/products/$path"); + ensure_dir_created_or_die("$new_www_root/images/products/$path"); } # Check lock and previous version @@ -1935,7 +1935,7 @@ sub replace_user_id_in_product ($product_id, $user_id, $new_user_id, $products_c # List of changes - my $changes_ref = retrieve("$data_root/products/$path/changes.sto"); + my $changes_ref = retrieve("$BASE_DIRS{PRODUCTS}/$path/changes.sto"); if (not defined $changes_ref) { $log->warn("replace_user_id_in_products - no changes file found for " . $product_id); return; @@ -1958,7 +1958,7 @@ sub replace_user_id_in_product ($product_id, $user_id, $new_user_id, $products_c if (not defined $rev) { $rev = $revs; # was not set before June 2012 } - my $product_ref = retrieve("$data_root/products/$path/$rev.sto"); + my $product_ref = retrieve("$BASE_DIRS{PRODUCTS}/$path/$rev.sto"); if (defined $product_ref) { @@ -2003,7 +2003,7 @@ sub replace_user_id_in_product ($product_id, $user_id, $new_user_id, $products_c # Save product if ($changes) { - store("$data_root/products/$path/$rev.sto", $product_ref); + store("$BASE_DIRS{PRODUCTS}/$path/$rev.sto", $product_ref); } } @@ -2015,7 +2015,7 @@ sub replace_user_id_in_product ($product_id, $user_id, $new_user_id, $products_c $most_recent_product_ref, {upsert => 1}); } - store("$data_root/products/$path/changes.sto", $changes_ref); + store("$BASE_DIRS{PRODUCTS}/$path/changes.sto", $changes_ref); return; } @@ -2560,7 +2560,7 @@ sub add_back_field_values_removed_by_user ($current_product_ref, $changes_ref, $ if (not defined $rev) { $rev = $revs; # was not set before June 2012 } - my $product_ref = retrieve("$data_root/products/$path/$rev.sto"); + my $product_ref = retrieve("$BASE_DIRS{PRODUCTS}/$path/$rev.sto"); # if not found, we may be be updating the product, with the latest rev not set yet if ((not defined $product_ref) or ($rev == $current_product_ref->{rev})) { @@ -2852,7 +2852,7 @@ sub compute_codes ($product_ref) { if (product_exists('0' . $code)) { push @codes, "conflict-with-ean-13"; } - elsif (-e ("$data_root/products/" . product_path_from_id("0" . $code))) { + elsif (-e ("$BASE_DIRS{PRODUCTS}/" . product_path_from_id("0" . $code))) { push @codes, "conflict-with-deleted-ean-13"; } } diff --git a/lib/ProductOpener/Routing.pm b/lib/ProductOpener/Routing.pm index fd7880bbc302a..cf761dd2e140f 100644 --- a/lib/ProductOpener/Routing.pm +++ b/lib/ProductOpener/Routing.pm @@ -42,6 +42,7 @@ BEGIN { use vars @EXPORT_OK; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Display qw/:all/; use ProductOpener::Users qw/:all/; use ProductOpener::Lang qw/:all/; @@ -430,7 +431,7 @@ sub analyze_request ($request_ref) { } # Graph of the products? - # $data_root/lang/$lang/texts/products_stats_$cc.html + # $BASE_DIRS{LANG}/$lang/texts/products_stats_$cc.html #elsif (($components[0] eq $tag_type_plural{products}{$lc}) and (not defined $components[1])) { # $request_ref->{text} = "products_stats_$cc"; # $request_ref->{canon_rel_url} = "/" . $components[0]; diff --git a/lib/ProductOpener/Store.pm b/lib/ProductOpener/Store.pm index 8b731f7e404de..0a1a5ea3d609c 100644 --- a/lib/ProductOpener/Store.pm +++ b/lib/ProductOpener/Store.pm @@ -42,6 +42,7 @@ BEGIN { use vars @EXPORT_OK; # no 'my' keyword for these use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use Storable qw(lock_store lock_nstore lock_retrieve); use Encode; @@ -297,7 +298,7 @@ sub sto_iter ($initial_path, $pattern = qr/\.sto$/i) { # explore a new dir until we get some file while ((scalar @files == 0) && (scalar @dirs > 0)) { my $current_dir = shift @dirs; - opendir(DIR, "$current_dir") or die "Cannot open $current_dir\n"; + opendir(DIR, $current_dir) or die "Cannot open $current_dir\n"; # Sort files so that we always explore them in the same order (useful for tests) my @candidates = sort readdir(DIR); closedir(DIR); diff --git a/lib/ProductOpener/Tags.pm b/lib/ProductOpener/Tags.pm index 1ffa0c244e142..fdeeebc1eb9d8 100644 --- a/lib/ProductOpener/Tags.pm +++ b/lib/ProductOpener/Tags.pm @@ -176,6 +176,7 @@ use vars @EXPORT_OK; use ProductOpener::Store qw/:all/; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::TagsEntries qw/:all/; use ProductOpener::Lang qw/:all/; use ProductOpener::Text qw/:all/; @@ -1018,7 +1019,7 @@ sub get_lc_tagid ($synonyms_ref, $lc, $tagtype, $tag, $warning) { } sub get_file_from_cache ($source, $target) { - my $cache_root = "$data_root/build-cache/taxonomies"; + my $cache_root = "$BASE_DIRS{CACHE_BUILD}/taxonomies"; my $local_cache_source = "$cache_root/$source"; # first, try to get it localy @@ -1044,7 +1045,7 @@ sub get_from_cache ($tagtype, @files) { # If the full set of cached files can't be found then returns the hash to be used # when saving the new cached files. my $tag_data_root = "$data_root/taxonomies/$tagtype"; - my $tag_www_root = "$www_root/data/taxonomies/$tagtype"; + my $tag_www_root = "$BASE_DIRS{PUBLIC_DATA}/taxonomies/$tagtype"; my $sha1 = Digest::SHA1->new; @@ -1085,7 +1086,7 @@ sub get_from_cache ($tagtype, @files) { } sub put_file_to_cache ($source, $target) { - my $local_target_path = "$data_root/build-cache/taxonomies/$target"; + my $local_target_path = "$BASE_DIRS{CACHE_BUILD}/taxonomies/$target"; copy($source, $local_target_path); # Upload to github @@ -1120,7 +1121,7 @@ sub put_file_to_cache ($source, $target) { sub put_to_cache ($tagtype, $cache_prefix) { my $tag_data_root = "$data_root/taxonomies/$tagtype"; - my $tag_www_root = "$www_root/data/taxonomies/$tagtype"; + my $tag_www_root = "$BASE_DIRS{PUBLIC_DATA}/taxonomies/$tagtype"; put_file_to_cache("$tag_www_root.json", "$cache_prefix.json"); put_file_to_cache("$tag_www_root.full.json", "$cache_prefix.full.json"); @@ -2132,29 +2133,31 @@ sub build_tags_taxonomy ($tagtype, $publish) { } } - (-e "$www_root/data/taxonomies") or mkdir("$www_root/data/taxonomies", 0755); + (-e "$BASE_DIRS{PUBLIC_DATA}/taxonomies") or mkdir("$BASE_DIRS{PUBLIC_DATA}/taxonomies", 0755); { binmode STDOUT, ":encoding(UTF-8)"; - if (open(my $OUT_JSON, ">", "$www_root/data/taxonomies/$tagtype.json")) { + if (open(my $OUT_JSON, ">", "$BASE_DIRS{PUBLIC_DATA}/taxonomies/$tagtype.json")) { print $OUT_JSON encode_json(\%taxonomy_json); close($OUT_JSON); } else { - print "Cannot open $www_root/data/taxonomies/$tagtype.json, skipping writing taxonomy to file.\n"; + print + "Cannot open $BASE_DIRS{PUBLIC_DATA}/taxonomies/$tagtype.json, skipping writing taxonomy to file.\n"; } - if (open(my $OUT_JSON_FULL, ">", "$www_root/data/taxonomies/$tagtype.full.json")) { + if (open(my $OUT_JSON_FULL, ">", "$BASE_DIRS{PUBLIC_DATA}/taxonomies/$tagtype.full.json")) { print $OUT_JSON_FULL encode_json(\%taxonomy_full_json); close($OUT_JSON_FULL); } else { - print "Cannot open $www_root/data/taxonomies/$tagtype.full.json, skipping writing taxonomy to file.\n"; + print + "Cannot open $BASE_DIRS{PUBLIC_DATA}/taxonomies/$tagtype.full.json, skipping writing taxonomy to file.\n"; } # to serve pre-compressed files from Apache # nginx : needs nginx_static module - # system("cp $www_root/data/taxonomies/$tagtype.json $www_root/data/taxonomies/$tagtype.json.json"); - # system("gzip $www_root/data/taxonomies/$tagtype.json"); + # system("cp $BASE_DIRS{PUBLIC_DATA}/taxonomies/$tagtype.json $BASE_DIRS{PUBLIC_DATA}/taxonomies/$tagtype.json.json"); + # system("gzip $BASE_DIRS{PUBLIC_DATA}/taxonomies/$tagtype.json"); } $log->error("taxonomy errors", {errors => $errors}) if $log->is_error(); @@ -4320,7 +4323,7 @@ GEXF ; open(my $OUT, ">:encoding(UTF-8)", - "$www_root/data/$lc." . get_string_id_for_lang("no_language", lang($tagtype . "_p"), 1) . ".gexf") + "$BASE_DIRS{PUBLIC_DATA}/$lc." . get_string_id_for_lang("no_language", lang($tagtype . "_p"), 1) . ".gexf") or die("write error: $!\n"); print $OUT $gexf; close $OUT; @@ -4328,14 +4331,14 @@ GEXF eval { $graph->run( format => 'svg', - output_file => "$www_root/data/$lc." + output_file => "$BASE_DIRS{PUBLIC_DATA}/$lc." . get_string_id_for_lang("no_language", lang($tagtype . "_p"), 1) . ".svg" ); }; eval { $graph->run( format => 'png', - output_file => "$www_root/data/$lc." + output_file => "$BASE_DIRS{PUBLIC_DATA}/$lc." . get_string_id_for_lang("no_language", lang($tagtype . "_p"), 1) . ".png" ); }; @@ -4700,9 +4703,9 @@ sub compute_field_tags ($product_ref, $tag_lc, $field) { sub add_user_translation ($tag_lc, $tagtype, $user, $from, $to) { - (-e "$data_root/translate") or mkdir("$data_root/translate", 0755); + ensure_dir_created_or_die($BASE_DIRS{USERS_TRANSLATIONS}); - open(my $LOG, ">>:encoding(UTF-8)", "$data_root/translate/$tagtype.$tag_lc.txt"); + open(my $LOG, ">>:encoding(UTF-8)", "$BASE_DIRS{USERS_TRANSLATIONS}/$tagtype.$tag_lc.txt"); print $LOG join("\t", (time(), $user, $from, $to)) . "\n"; close $LOG; @@ -4715,13 +4718,13 @@ sub load_users_translations_for_lc ($users_translations_ref, $tagtype, $tag_lc) $users_translations_ref->{$tag_lc} = {}; } - my $file = "$data_root/translate/$tagtype.$tag_lc.txt"; + my $file = "$BASE_DIRS{USERS_TRANSLATIONS}/$tagtype.$tag_lc.txt"; $log->debug("load_users_translations_for_lc", {file => $file}) if $log->is_debug(); if (-e $file) { $log->debug("load_users_translations_for_lc, file exists", {file => $file}) if $log->is_debug(); - open(my $LOG, "<:encoding(UTF-8)", "$data_root/translate/$tagtype.$tag_lc.txt"); + open(my $LOG, "<:encoding(UTF-8)", "$BASE_DIRS{USERS_TRANSLATIONS}/$tagtype.$tag_lc.txt"); while (<$LOG>) { chomp(); my ($time, $userid, $from, $to) = split(/\t/, $_); @@ -4742,7 +4745,7 @@ sub load_users_translations_for_lc ($users_translations_ref, $tagtype, $tag_lc) sub load_users_translations ($users_translations_ref, $tagtype) { - if (opendir(my $DH, "$data_root/translate")) { + if (opendir(my $DH, $BASE_DIRS{USERS_TRANSLATIONS})) { foreach my $file (readdir($DH)) { if ($file =~ /^$tagtype.(\w\w).txt$/) { load_users_translations_for_lc($users_translations_ref, $tagtype, $1); diff --git a/lib/ProductOpener/TaxonomySuggestions.pm b/lib/ProductOpener/TaxonomySuggestions.pm index 5f98e7d6677f9..babd3d298837a 100644 --- a/lib/ProductOpener/TaxonomySuggestions.pm +++ b/lib/ProductOpener/TaxonomySuggestions.pm @@ -44,6 +44,7 @@ BEGIN { use vars @EXPORT_OK; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Display qw/:all/; use ProductOpener::Lang qw/:all/; @@ -59,11 +60,12 @@ my $categories_packagings_stats_for_suggestions_ref; sub load_categories_packagings_stats_for_suggestions() { if (not defined $categories_packagings_stats_for_suggestions_ref) { - my $file = "$data_root/data/categories_stats/categories_packagings_stats.all.popular.json"; + my $file = "$BASE_DIRS{PRIVATE_DATA}/categories_stats/categories_packagings_stats.all.popular.json"; # In dev environments, we provide a sample stats file in the data-default directory # so that we can run tests with meaningful and unchanging data if (!-e $file) { - my $default_file = "$data_root/data-default/categories_stats/categories_packagings_stats.all.popular.json"; + my $default_file + = "$BASE_DIRS{PRIVATE_DATA}-default/categories_stats/categories_packagings_stats.all.popular.json"; $log->debug("local packaging stats file does not exist, will use default", {file => $file, default_file => $default_file}) if $log->is_debug(); diff --git a/lib/ProductOpener/Test.pm b/lib/ProductOpener/Test.pm index f7937443f247a..b255fde03bdc9 100644 --- a/lib/ProductOpener/Test.pm +++ b/lib/ProductOpener/Test.pm @@ -64,6 +64,7 @@ use vars @EXPORT_OK; use IO::Capture::Stdout::Extended; use IO::Capture::Stderr::Extended; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Data qw/execute_query get_products_collection/; use ProductOpener::Store "store"; @@ -214,11 +215,11 @@ sub remove_all_products () { } ); # clean files - remove_tree("$data_root/products", {keep_root => 1, error => \my $err}); + remove_tree($BASE_DIRS{PRODUCTS}, {keep_root => 1, error => \my $err}); if (@$err) { confess("not able to remove some products directories: " . join(":", @$err)); } - remove_tree("$www_root/images/products", {keep_root => 1, error => \$err}); + remove_tree($BASE_DIRS{PRODUCTS_IMAGES}, {keep_root => 1, error => \$err}); if (@$err) { confess("not able to remove some products directories: " . join(":", @$err)); } @@ -237,7 +238,7 @@ sub remove_all_users () { check_not_production(); # clean files # clean files - remove_tree("$data_root/users", {keep_root => 1, error => \my $err}); + remove_tree($BASE_DIRS{USERS}, {keep_root => 1, error => \my $err}); if (@$err) { confess("not able to remove some users directories: " . join(":", @$err)); } @@ -255,7 +256,7 @@ sub remove_all_orgs () { # Important: check we are not on a prod database check_not_production(); # clean files - remove_tree("$data_root/orgs", {keep_root => 1, error => \my $err}); + remove_tree($BASE_DIRS{ORGS}, {keep_root => 1, error => \my $err}); if (@$err) { confess("not able to remove some orgs directories: " . join(":", @$err)); } @@ -306,7 +307,7 @@ sub ensure_expected_results_dir ($expected_results_dir, $update_expected_results if ($update_expected_results) { # Reset the expected results dir if (-e $expected_results_dir) { - remove_tree("$expected_results_dir", {error => \my $err}); + remove_tree($expected_results_dir, {error => \my $err}); if (@$err) { confess("not able to remove some result directories: " . join(":", @$err)); } @@ -464,9 +465,11 @@ This is so that we can easily see diffs with git diffs: Tests will pass when this flag is passed, and the new expected results can be diffed / committed in GitHub. +=head4 $test_name - name of test for failure display + =cut -sub compare_csv_file_to_expected_results ($csv_file, $expected_results_dir, $update_expected_results) { +sub compare_csv_file_to_expected_results ($csv_file, $expected_results_dir, $update_expected_results, $test_name = "") { # Read the CSV file @@ -485,18 +488,19 @@ sub compare_csv_file_to_expected_results ($csv_file, $expected_results_dir, $upd push @data, $product_ref; } close($io); - compare_array_to_expected_results(\@data, $expected_results_dir . "/rows", $update_expected_results); + compare_array_to_expected_results(\@data, $expected_results_dir . "/rows", $update_expected_results, + $test_name); # If we update the expected results, copy the CSV file so that we can easily see line by line diffs if ($update_expected_results) { my $csv_filename = $csv_file; $csv_filename =~ s/.*\///; copy($csv_file, $expected_results_dir . '/' . $csv_filename) - or die "Copy of $csv_file to $expected_results_dir failed: $!"; + or die "$test_name - Copy of $csv_file to $expected_results_dir failed: $!"; } } else { - fail("Could not open " . $csv_file . ": $!"); + fail("$test_name - Could not open " . $csv_file . ": $!"); } return 1; @@ -524,9 +528,11 @@ This is so that we can easily see diffs with git diffs: Tests will always pass when this flag is passed, and the new expected results can be diffed / committed in GitHub. +=head4 $test_name - name of the test for outputs + =cut -sub compare_array_to_expected_results ($array_ref, $expected_results_dir, $update_expected_results) { +sub compare_array_to_expected_results ($array_ref, $expected_results_dir, $update_expected_results, $test_name = "") { ensure_expected_results_dir($expected_results_dir, $update_expected_results); @@ -553,7 +559,7 @@ sub compare_array_to_expected_results ($array_ref, $expected_results_dir, $updat local $/; #Enable 'slurp' mode my $expected_product_ref = $json->decode(<$expected_result>); - is_deeply($product_ref, $expected_product_ref) or diag explain $product_ref; + is_deeply($product_ref, $expected_product_ref, "$test_name - $code") or diag explain $product_ref; } else { diag explain $product_ref; @@ -577,10 +583,10 @@ sub compare_array_to_expected_results ($array_ref, $expected_results_dir, $updat } } if (@missed) { - fail("Products " . join(", ", @missed) . " not found in array"); + fail("$test_name - Products " . join(", ", @missed) . " not found in array"); } else { - pass("All products found in array"); + pass("$test_name - All products found in array"); } return 1; diff --git a/lib/ProductOpener/URL.pm b/lib/ProductOpener/URL.pm index 61f37c482c7d8..a0e8e8cffbef2 100644 --- a/lib/ProductOpener/URL.pm +++ b/lib/ProductOpener/URL.pm @@ -28,7 +28,7 @@ C is used to generate a URL of the product according to the use ProductOpener::URL qw/:all/; - my $image = "$www_root/images/products/$path/$filename.full.jpg"; + my $image = "$BASE_DIRS{PRODUCTS_IMAGES}/$path/$filename.full.jpg"; my $image_url = format_subdomain('static') . "/images/products/$path/$filename.full.jpg"; # subdomain format: @@ -61,6 +61,7 @@ use vars @EXPORT_OK; use experimental 'smartmatch'; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; =head1 FUNCTIONS diff --git a/lib/ProductOpener/Users.pm b/lib/ProductOpener/Users.pm index de21925aa3207..c2a7c52a66056 100644 --- a/lib/ProductOpener/Users.pm +++ b/lib/ProductOpener/Users.pm @@ -80,6 +80,7 @@ use vars @EXPORT_OK; use ProductOpener::Store qw/:all/; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Mail qw/:all/; use ProductOpener::Lang qw/:all/; use ProductOpener::Display qw/:all/; @@ -224,7 +225,7 @@ sub delete_user_task ($job, $args_ref) { my $job_id = $job->{id}; my $log_message = "delete_user_task - job: $job_id started - args: " . encode_json($args_ref) . "\n"; - open(my $minion_log, ">>", "$data_root/logs/minion.log"); + open(my $minion_log, ">>", "$BASE_DIRS{LOGS}/minion.log"); print $minion_log $log_message; close($minion_log); @@ -237,17 +238,17 @@ sub delete_user_task ($job, $args_ref) { $log->info("delete_user", {userid => $userid, new_userid => $new_userid}) if $log->is_info(); # Remove the user file - unlink("$data_root/users/$userid.sto"); + unlink("$BASE_DIRS{USERS}/$userid.sto"); # Remove the e-mail - my $emails_ref = retrieve("$data_root/users/users_emails.sto"); + my $emails_ref = retrieve("$BASE_DIRS{USERS}/users_emails.sto"); my $email = $args_ref->{email}; if ((defined $email) and ($email =~ /\@/)) { if (defined $emails_ref->{$email}) { delete $emails_ref->{$email}; - store("$data_root/users/users_emails.sto", $emails_ref); + store("$BASE_DIRS{USERS}/users_emails.sto", $emails_ref); } } @@ -376,7 +377,7 @@ sub check_user_form ($type, $user_ref, $errors_ref) { } if ($is_spam) { # log the ip - open(my $log, ">>", "$data_root/logs/user_spam.log"); + open(my $log, ">>", "$BASE_DIRS{LOGS}/user_spam.log"); print $log remote_addr() . "\t" . time() . "\t" . $user_ref->{userid} . "\t" . $user_ref->{name} . "\n"; close($log); # bail out, return 200 status code @@ -390,7 +391,7 @@ sub check_user_form ($type, $user_ref, $errors_ref) { if ((defined $email) and ($email ne '') and ($user_ref->{email} ne $email)) { # check that the email is not already used - my $emails_ref = retrieve("$data_root/users/users_emails.sto"); + my $emails_ref = retrieve("$BASE_DIRS{USERS}/users_emails.sto"); if ((defined $emails_ref->{$email}) and ($emails_ref->{$email}[0] ne $user_ref->{userid})) { $log->debug("check_user_form - email already in use", {type => $type, email => $email, existing_userid => $emails_ref->{$email}}) @@ -498,7 +499,7 @@ sub check_user_form ($type, $user_ref, $errors_ref) { if (length($user_ref->{userid}) < 2) { push @{$errors_ref}, $Lang{error_no_username}{$lang}; } - elsif (-e "$data_root/users/$userid.sto") { + elsif (-e "$BASE_DIRS{USERS}/$userid.sto") { push @{$errors_ref}, $Lang{error_username_not_available}{$lang}; } elsif ($user_ref->{userid} !~ /^[a-z0-9]+[a-z0-9\-]*[a-z0-9]+$/) { @@ -663,10 +664,10 @@ sub process_user_form ($type, $user_ref, $request_ref) { process_user_requested_org($user_ref); # save user - store("$data_root/users/$userid.sto", $user_ref); + store("$BASE_DIRS{USERS}/$userid.sto", $user_ref); # Update email - my $emails_ref = retrieve("$data_root/users/users_emails.sto"); + my $emails_ref = retrieve("$BASE_DIRS{USERS}/users_emails.sto"); my $email = $user_ref->{email}; if ((defined $email) and ($email =~ /\@/)) { @@ -676,7 +677,7 @@ sub process_user_form ($type, $user_ref, $request_ref) { delete $emails_ref->{$user_ref->{old_email}}; delete $user_ref->{old_email}; } - store("$data_root/users/users_emails.sto", $emails_ref); + store("$BASE_DIRS{USERS}/users_emails.sto", $emails_ref); if ($type eq 'add') { @@ -742,7 +743,7 @@ sub check_edit_owner ($user_ref, $errors_ref) { # If the owner id looks like a GLN, see if we have a corresponding org if ($user_ref->{pro_moderator_owner} =~ /^\d+$/) { - my $glns_ref = retrieve("$data_root/orgs/orgs_glns.sto"); + my $glns_ref = retrieve("$BASE_DIRS{ORGS}/orgs_glns.sto"); not defined $glns_ref and $glns_ref = {}; if (defined $glns_ref->{$user_ref->{pro_moderator_owner}}) { $user_ref->{pro_moderator_owner} = $glns_ref->{$user_ref->{pro_moderator_owner}}; @@ -760,7 +761,7 @@ sub check_edit_owner ($user_ref, $errors_ref) { my $userid = $'; # Add check that organization exists when we add org profiles - if (!-e "$data_root/users/$userid.sto") { + if (!-e "$BASE_DIRS{USERS}/$userid.sto") { push @{$errors_ref}, sprintf($Lang{error_user_does_not_exist}{$lang}, $userid); } else { @@ -937,7 +938,7 @@ sub open_user_session ($user_ref, $request_ref) { }; # Store user data - my $user_file = "$data_root/users/" . get_string_id_for_lang("no_language", $user_id) . ".sto"; + my $user_file = "$BASE_DIRS{USERS}/" . get_string_id_for_lang("no_language", $user_id) . ".sto"; store($user_file, $user_ref); $log->debug("session initialized and user info stored") if $log->is_debug(); @@ -948,7 +949,7 @@ sub open_user_session ($user_ref, $request_ref) { } sub retrieve_user ($user_id) { - my $user_file = "$data_root/users/" . get_string_id_for_lang("no_language", $user_id) . ".sto"; + my $user_file = "$BASE_DIRS{USERS}/" . get_string_id_for_lang("no_language", $user_id) . ".sto"; my $user_ref; if (-e $user_file) { $user_ref = retrieve($user_file); @@ -983,7 +984,7 @@ sub remove_user_by_org_admin ($orgid, $user_id) { my $user_ref = retrieve_user($user_id); delete $user_ref->{org}; delete $user_ref->{org_id}; - my $user_file = "$data_root/users/" . get_string_id_for_lang("no_language", $user_id) . ".sto"; + my $user_file = "$BASE_DIRS{USERS}/" . get_string_id_for_lang("no_language", $user_id) . ".sto"; store($user_file, $user_ref); return; } @@ -1054,7 +1055,7 @@ sub init_user ($request_ref) { if ($user_id =~ /\@/) { $log->info("got email while initializing user", {email => $user_id}) if $log->is_info(); - my $emails_ref = retrieve("$data_root/users/users_emails.sto"); + my $emails_ref = retrieve("$BASE_DIRS{USERS}/users_emails.sto"); if (not defined $emails_ref->{$user_id}) { # not found, try with lower case email $user_id = lc $user_id; @@ -1080,7 +1081,7 @@ sub init_user ($request_ref) { # If the user exists if (defined $user_id) { - my $user_file = "$data_root/users/" . get_string_id_for_lang("no_language", $user_id) . ".sto"; + my $user_file = "$BASE_DIRS{USERS}/" . get_string_id_for_lang("no_language", $user_id) . ".sto"; if (-e $user_file) { $user_ref = retrieve($user_file); @@ -1140,7 +1141,7 @@ sub init_user ($request_ref) { } if (defined $user_id) { - my $user_file = "$data_root/users/" . get_string_id_for_lang("no_language", $user_id) . ".sto"; + my $user_file = "$BASE_DIRS{USERS}/" . get_string_id_for_lang("no_language", $user_id) . ".sto"; if (-e $user_file) { $user_ref = retrieve($user_file); @@ -1315,7 +1316,7 @@ sub check_session ($user_id, $user_session) { $log->debug("checking session", {user_id => $user_id, users_session => $user_session}) if $log->is_debug(); - my $user_file = "$data_root/users/" . get_string_id_for_lang("no_language", $user_id) . ".sto"; + my $user_file = "$BASE_DIRS{USERS}/" . get_string_id_for_lang("no_language", $user_id) . ".sto"; my $results_ref = {}; diff --git a/lib/startup_apache2.pl b/lib/startup_apache2.pl index a760770aa464b..a9ac40b320105 100755 --- a/lib/startup_apache2.pl +++ b/lib/startup_apache2.pl @@ -68,6 +68,7 @@ Log::Any::Adapter->set('Log4perl'); # Send all logs to Log::Log4perl use ProductOpener::Lang qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Display qw/:all/; use ProductOpener::Products qw/:all/; @@ -148,17 +149,23 @@ sub get_remote_proxy_address { } # set up error logging -open *STDERR, '>', "/$data_root/logs/modperl_error_log" or Carp::croak('Could not open modperl_error_log'); +open *STDERR, '>', "/$BASE_DIRS{LOGS}/modperl_error_log" or Carp::croak('Could not open modperl_error_log'); print {*STDERR} $log or Carp::croak('Unable to write to *STDERR'); +# check folders +my @missing_dirs = @{check_missing_dirs()}; +if (scalar @missing_dirs) { + die("FATAL: Some important directories are missing: " . (join(":", @missing_dirs))); +} + # load large data files into mod_perl memory load_data(); -# This startup script is run as root, it will create the $data_root/tmp directory +# This startup script is run as root, it will create the $BASE_DIRS{CACHE_TMP} directory # if it does not exist, as well as sub-directories for the Template module # We need to set more permissive permissions so that it can be writable by the Apache user. -chmod_recursive(S_IRWXU | S_IRWXG | S_IRWXO, "$data_root/tmp"); +chmod_recursive(S_IRWXU | S_IRWXG | S_IRWXO, $BASE_DIRS{CACHE_TMP}); $log->info('product opener started', {version => $version}); diff --git a/logs/apache2/.empty b/logs/apache2/.empty deleted file mode 100644 index e69de29bb2d1d..0000000000000 diff --git a/logs/nginx/.empty b/logs/nginx/.empty deleted file mode 100644 index e69de29bb2d1d..0000000000000 diff --git a/producers.html b/producers.html deleted file mode 100644 index 32709047f128c..0000000000000 --- a/producers.html +++ /dev/null @@ -1,381 +0,0 @@ - - - - Guide for producers - -
- - - - - -

Guide for producers

- -

This guide explains why and how producers can directly integrate photos and product data into the Open Food Facts database.

- - - -

Introduction

- -

The photos and data on the food products referenced in the Open Food Facts database come from 2 sources:

-
    -
  • crowdsourcing through mobile apps and the Open Food Facts website: contributors scan barcodes, send product photos, ingredient lists and nutrition charts and then enter the data in a structured way.
  • -
  • the addition of data directly from the producers, either manually or automatically.
  • -
- - -

Why add product data to Open Food Facts

- - -

There are many benefits to importing date directly from manufacturers:

- -
    - -
  • The data is complete, up to date, and without risk of error.
  • - -
  • The photos are of better quality than the photos taken by the contributors in very variable conditions.
  • - -
  • The data is then available in more than 100 applications.
  • - -
  • You can easily obtain statistics about your products and export the data of your products supplemented by indicators calculated by Open Food Facts such as the Nutri-Score.
  • -
- - -

Examples of producers who submit photos and product data to Open Food Facts

- -

A growing number of high level French producers are sending us the data of their products: Fleury Michon, Sodebo, System U, Carrefour, Casino, Franprix, Monoprix.

- -

How to add the data of your products in Open Food Facts

- -

Licence

- -

All data sent to Open Food Facts is published under the Open Database License (ODbL), and the photos under the Creative Commons License CC-BY-SA. These licenses allow the data to be freely reusable by all and for all purposes. For more information, see the Terms of Use, Contribution, and Reuse.

- -

What data

- -

All the data you have can be integrated into Open Food Facts: ingredients and nutritional information of course, but also labels, materials used for packaging, traceability of ingredients, instructions for preparation and recycling, ecological footprint etc.

-

We regularly add new fields to the database based on the information on the packages or provided by the manufacturers.

-We have recently added fields on the carbon footprint, and the packaging of products, which are already highlighted on Open Food Facts and in applications that help to change the behavior in terms of recycling.

- -

A database in all languages

- -

The Open Food Facts database, site and mobile applications are also fully multilingual and available in all countries. If you have photos and data in multiple languages, we can also integrate them into Open Food Facts.

- -

Photos and Data

- -

One of the fundamental principles of Open Food Facts is that the user or contributor must be able to verify the information from a photo.

- -

We therefore ask you to send us photos of the product and packaging (possibly as a flat file of the packaging) to support the structured data you send.

- - -

Manual addition

- -

If you have a small number of products whose formulation does not change often, you can create an account on Open Food Facts and add yourself photos and data of your products.

- -

Highly recommended method: Add photos and enter information from the Open Food Facts website .

- -

Alternative method: Use the Android mobile application to scan and then photograph and finally enter a product completely.

- -

Thank you in advance for telling us if you add your products yourself so that we can identify your account as a producer account, and indicate that the information comes directly from your company.

- - -

Automated addition

- -To make importing data easier and faster, we have defined a standard format for images and data: - -

Picture format

- -

At least 3 images are required:

-
    -
  • Front view of product on white background (avoid three-quarter views that do not allow visual recognition of products without barcode scanning)
  • -
  • List of ingredients
  • -
  • Nutritional table
  • -
- -

The front view, ingredients and nutrition chart must be provided in at least the main language of the product. It is recommended that you also provide images for other languages ​​when they appear on the product.

- -

For example, a product intended for the Belgian market may have photos showing the product written in French and written in Dutch.

- -

Other images may also be included:

-
    -
  • Verso and other views of the product (they allow in particular to automatically identify labels logos etc.)
  • -
  • Flat view of the packaging
  • -
- -
Format of image files
-
    -
  • JPEG or PNG format
  • -
  • Size at least 2000 pixels wide or tall
  • -
- -
Name of the image files
- -
[barcode]_[type of image]_[language code].[jpg or png]
- -

For example :

- -

3660140808750_front_en.jpg for the front image of the product whose barcode is 3660140808750

- -

The types of images are:

- -
    -
  • front: front image
  • -
  • ingredients: list of ingredients
  • -
  • nutrition: nutritional chart
  • -
  • back: version
  • -
  • any name you see fit (characters from a to e, no spaces) for other views
  • -
- - -

Data format

- -

The data must be provided in a table in CSV format, with tabulation as field separator character and UTF-8 character encoding.

- -

The first line contains the field names, and each of the products occupies one of the following lines. The order of the fields does not matter, and not all columns need to be present.

- -

Some fields are mandatory and others are optional. We encourage you to fill in as many fields as possible so that the data can be used by as many applications as possible. If in doubt, or if you have data for which there are not yet fields in the Open Food Facts database, you can contact us so that we can add fields and make the best possible match.

- -
Required fields
- -
    -
  • code: product barcode as it appears on the packaging (EAN-13, EAN-8 or other) -
  • lang: 2-letter code of the main language (most present on the packaging) of the product (example: fr for French) -
  • product_name_ [2-letter code of the main language]: product name (in the field product_name_en for the name in French) -
  • generic_name_ [2-letter code of the main language]: Generic product name -
  • brands: brands (several possible values ​​for brands and sub-brands, to be separated by commas) -
  • quantity: quantity, specify the unit, and possibly add in parentheses if the product contains several units (example: 120 g (4 x 30 g)) -
  • categories: product category, in the main product language (example: chocolate cakes) -
  • countries: country where the product is sold, in the main language of the product (several possible values, to be separated by commas) - -
  • ingredients_text_ [2-letter code of the main language]: list of ingredients (in the ingredients_text_fr field for the list in French). Allergens may be indicated in CAPITAL LETTERS or between -
  • allergens: allergens, in the main language of the product, separated by commas -
  • traces: traces of allergens, in the main language of the product, separated by commas -
- -

Among the mandatory fields are the nutritional values ​​that appear on the package, per 100g / 100ml of product as sold.

-

All values ​​must have no unit (the unit is kJ for energy and g for all other fields).

- -
    -
  • energy_100g: energy, in kJ -
  • fat_100g: fat -
  • saturated-fat_100g: saturated fat -
  • carbohydrates_100g: carbohydrates -
  • sugars_100g: sugars -
  • proteins_100g: proteins -
  • salt_100g: salt -
- -

It is strongly recommended to also indicate the fibers and the % of fruits and vegetables so that this information can be taken into account in the calculation of Nutri-Score:

- -
    -
  • fiber_100g: fibers -
  • fruits-vegetables-nuts_100g -
- -
Optional fields
- -
    -
  • labels: labels, in the main language of the product (several possible values, to be separated by commas) (example: AB Bio, MSC, Max Havelaar). Note: the labels must appear on the packaging of the product. -
  • origins: origins of the ingredients, in the main language of the product (several possible values, to be separated by commas) (example: Peru, Périgord) -
  • packaging: materials and forms of the product packaging, in the main language of the product (several possible values, to be separated by commas) (example: can, aluminum) -
  • manufacturing_places: manufacturing locations, in the main language of the product (several possible values, to be separated by commas: city names, countries) -
  • emb_codes: packager codes and European sanitary stamps (several possible values, to be separated by commas) -
  • stores: places of sale (several possible values, to be separated by commas: names of supermarket chains) - -
  • nutri_score: Nutri-Score rating from A to E, only in case it is indicated on the package - -
  • serving_size: quantity of a serving, specify the unit -
- -

Nutritional values ​​can also be indicated for the prepared product (with water, milk etc.). Then add "_prepared" to the name of the field. For example energy_prepared_100g.

- -

It is also possible to indicate the values ​​for other nutrients:

- -
    -
  • Energy-from-fat_100g -
  • butyric-acid_100g -
  • caproic-acid_100g -
  • caprylic-acid_100g -
  • capric-acid_100g -
  • lauric-acid_100g -
  • myristic-acid_100g -
  • palmitic-acid_100g -
  • stearic-acid_100g -
  • arachidic-acid_100g -
  • behenic-acid_100g -
  • lignoceric-acid_100g -
  • cerotic-acid_100g -
  • montanic-acid_100g -
  • melissic-acid_100g -
  • monounsaturated-fat_100g -
      -
    • omega-9-fat_100g
    • -
    -
  • polyunsaturated-fat_100g -
      -
    • omega-6-fat_100g
    • -
    -
  • omega-3-fat_100g -
  • alpha-linolenic-acid_100g -
  • eicosapentaenoic-acid_100g -
  • docosahexaenoic-acid_100g - -
  • linoleic-acid_100g -
  • arachidonic-acid_100g -
  • gamma-linolenic-acid_100g -
  • dihomo-gamma-linolenic-acid_100g - -
  • oleic-acid_100g -
  • elaidic-acid_100g -
  • gondoic-acid_100g -
  • Mead-acid_100g -
  • erucic-acid_100g -
  • nervonic-acid_100g -
  • trans-fat_100g -
  • cholesterol_100g - -
  • sucrose_100g -
  • glucose_100g -
  • fructose_100g -
  • lactose_100g -
  • maltose_100g -
  • maltodextrins_100g -
  • starch_100g -
  • polyols_100g - -
  • casein_100g -
  • serum-proteins_100g -
  • nucleotides_100g - -
  • sodium_100g - in case the salt_100g field is not filled -
  • alcohol_100g - -
  • vitamin-a_100g -
  • beta-carotene_100g -
  • vitamin-d_100g -
  • vitamin-e_100g -
  • vitamin-k_100g -
  • vitamin-c_100g -
  • vitamin-b1_100g -
  • vitamin-b2_100g -
  • vitamin-pp_100g -
  • vitamin-b6_100g -
  • vitamin-b9_100g -
  • folates_100g -
  • vitamin-b12_100g -
  • biotin_100g -
  • pantothenic-acid_100g - -
  • silica_100g -
  • bicarbonate_100g -
  • potassium_100g -
  • chloride_100g -
  • calcium_100g -
  • phosphorus_100g -
  • iron_100g -
  • magnesium_100g -
  • zinc_100g -
  • copper_100g -
  • manganese_100g -
  • fluoride_100g -
  • selenium_100g -
  • chromium_100g -
  • molybdenum_100g -
  • iodine_100g -
  • caffeine_100g -
  • taurine_100g - -
  • ph_100g -
  • collagen-meat-protein-ratio_100g -
  • cocoa_100g -
  • chlorophyl_100g -
  • Carbon-footprint_100g -
  • glycemic-index_100g -
  • Waterpolo hardness_100g -
  • choline_100g -
  • phylloquinone_100g -
  • beta-glucan_100g -
  • inositol_100g -
  • carnitine_100g - -
- - -

Sending photos and data

- -

If the number of products is relatively small (less than 1000 products) and the updates are infrequent (for example every 6 months), it is possible to send us the photos and the CSV file by any means (for example mail for CSV file and WeTransfer, Google Drive, DropBox etc. for photos).

- -

For a larger number of products or a more regular update, we can create an SFTP space where you can manually or automatically send data and photos. Contact us so that we can put this in place.

- - - -

Frequently asked Questions

- -

Is the listing of products free?

- -

The import of the data is completely free. We do not accept any retribution for the inclusion of data. We are very pleased that you have decided to contribute the data of your products to the food transparency, and we thank you for it.

- - -

Will producer data overwrite data entered by contributors?

- -

Producer data is automatically controlled by Open Food Facts with consistency checking algorithms, and then by some contributors. We have full confidence in the data you send us, but we know by experience that typos are possible.

- -

Once checked, they will replace and / or supplement the data entered by the contributors.

- -

In the case of a regular and automated import, the data will replace at every import the updates by contributors, unless a manifest error (which will be reported to you) is reported on a product by a contributor.

- - -

Is it possible to delete products that are no longer sold?

- -

When a product disappears from the shelves, it is quickly consumed, and we find that it is quickly no longer scanned.

-

We then archive the product so that it remains available as an archive for scientific purposes in the context of food cohorts that can last for decades. It is indeed essential to be able to obtain the compositions of the product at a precise date, even if it has changed or disappeared.

- -

If you have historical data on your old products or old versions of your products, we would also be very interested in this historical data, in order to be able to go back in time, to allow scientific analyzes on long time, and to make it possible to visualize the evolution some products.

- -

Producers can also send us the lists of barcodes removed from the sale so that we can label the products appropriately.

- - -

Can animal products, non-food products, cosmetics and other products be integrated into Open Food Facts?

- -

We have created specific projects for cosmetics, for animal feed, as well as for other products (Open Beauty Facts, Open Pet Food Facts and Open Products Facts respectively). We are therefore happy to be able to import your products into the project that suits them.

- - - - -
diff --git a/scripts/agena3000/run_agena3000_import.sh b/scripts/agena3000/run_agena3000_import.sh deleted file mode 100755 index f92922b2d059d..0000000000000 --- a/scripts/agena3000/run_agena3000_import.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/sh - -# Mirror data from Agena3000's server -# access needs to be configured in ~/.netrc -lftp -c "set cmd:default-protocol sftp; open sftp-a3dm.agena3000.com:2222; mirror --Remove-source-files /PROD/Fiches/ /home/sftp/agena3000/PROD/Fiches/" - -cd /srv/off-pro/scripts - -# copy files modified in the last few days - -rm -rf /srv2/off-pro/agena3000-data-tmp -mkdir /srv2/off-pro/agena3000-data-tmp -find /home/sftp/agena3000/PROD/Fiches/ -mtime -2 -type f -exec cp {} /srv2/off-pro/agena3000-data-tmp/ \; - -# turn GS1 XML files into JSON file - -/srv/off-pro/scripts/convert_gs1_xml_to_json_in_dir.pl /srv2/off-pro/agena3000-data-tmp/ - -# convert JSON files to a single CSV file - -export PERL5LIB=. - -/srv/off-pro/scripts/convert_gs1_json_to_off_csv.pl --input-dir /srv2/off-pro/agena3000-data-tmp --output /srv2/off-pro/agena3000-data-tmp/agena3000-data.tsv --confirmation-dir /srv2/off-pro/agena3000-data-tmp/Ack - -# import CSV file - -export PERL5LIB="/srv/off-pro/lib:${PERL5LIB}" -/srv/off-pro/scripts/import_csv_file.pl --user_id agena3000 --org_id agena3000 --source_id agena3000 --source_name Agena3000 --source_url https://agena3000.com/ --manufacturer 1 --comment "Import from Agena3000" --define lc=fr --images_download_dir /srv2/off-pro/agena3000-images-tmp --csv_file /srv2/off-pro/agena3000-data-tmp/agena3000-data.tsv - -# Send confirmation messages to Agena3000 -lftp -c "set cmd:default-protocol sftp; open sftp-a3dm.agena3000.com:2222; mirror -R --Remove-source-files /srv2/off-pro/agena3000-data-tmp/Ack/ /PROD/Ack/" diff --git a/scripts/build_lang.pl b/scripts/build_lang.pl index 0fcf7c4cb9148..eaf0cd901fcec 100755 --- a/scripts/build_lang.pl +++ b/scripts/build_lang.pl @@ -27,6 +27,7 @@ use ProductOpener::Lang qw/:all/; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Tags qw/:all/; use ProductOpener::Food qw/:all/; @@ -45,10 +46,8 @@ # use $server_domain in part of the name so that we have different files # when 2 instances of Product Opener share the same $data_root # as is the case with world.openfoodfacts.org and world.preprod.openfoodfacts.org -if (!-e "$data_root/data") { - mkdir("$data_root/data", 0755) or die("Could not create target directory $data_root/data : $!\n"); -} -store("$data_root/data/Lang.${server_domain}.sto", \%Lang); +ensure_dir_created_or_die($BASE_DIRS{PRIVATE_DATA}); +store("$BASE_DIRS{PRIVATE_DATA}/Lang.${server_domain}.sto", \%Lang); store("$data_root/data/Lang_tags.${server_domain}.sto", $tags_ref); # Generate JSON files for JavaScript I18N diff --git a/scripts/compute_missions_for_user.pl b/scripts/compute_missions_for_user.pl index d2b1e2c8bbed3..b529fe9146ff6 100755 --- a/scripts/compute_missions_for_user.pl +++ b/scripts/compute_missions_for_user.pl @@ -26,6 +26,7 @@ use utf8; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; @@ -48,11 +49,11 @@ my $user_id = $ARGV[0]; -my $user_ref = retrieve("$data_root/users/${user_id}.sto"); +my $user_ref = retrieve("$BASE_DIRS{USERS}/${user_id}.sto"); if (defined $user_ref) { ProductOpener::Missions::compute_missions_for_user($user_ref); - # store("$data_root/users/${user_id}.sto", $user_ref); + # store("$BASE_DIRS{USERS}/${user_id}.sto", $user_ref); } else { print "user_id: $user_id not found\n"; diff --git a/scripts/convert_carrefour_data_off1.sh b/scripts/convert_carrefour_data_off1.sh deleted file mode 100755 index 805d55928cd81..0000000000000 --- a/scripts/convert_carrefour_data_off1.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -./convert_carrefour_data.pl /srv/off/imports/carrefour/data /srv/off/imports/carrefour/Nomenclature_OpenFoodFacts.csv > /srv/off/imports/carrefour/carrefour.csv diff --git a/scripts/convert_gs1_json_to_off_csv.pl b/scripts/convert_gs1_json_to_off_csv.pl index d5b53e993c1f1..3d89b63098cf4 100755 --- a/scripts/convert_gs1_json_to_off_csv.pl +++ b/scripts/convert_gs1_json_to_off_csv.pl @@ -32,6 +32,7 @@ use Getopt::Long; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::GS1 qw/:all/; use ProductOpener::Food qw/:all/; diff --git a/scripts/create_small_categories_nutriments_per_country_for_testing.pl b/scripts/create_small_categories_nutriments_per_country_for_testing.pl index d59bda55f0d8c..e266a701d7875 100755 --- a/scripts/create_small_categories_nutriments_per_country_for_testing.pl +++ b/scripts/create_small_categories_nutriments_per_country_for_testing.pl @@ -6,17 +6,19 @@ use CGI::Carp qw(fatalsToBrowser); use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; # The real categories_nutriments_per_country.world.sto is too big to store for github, # create a smaller version that can be used in unit tests my $categories_nutriments_per_country_ref - = retrieve("$data_root/data/categories_stats/categories_nutriments_per_country.world.sto"); + = retrieve("$BASE_DIRS{PRIVATE_DATA}/categories_stats/categories_nutriments_per_country.world.sto"); my $test_ref = {"en:cakes" => $categories_nutriments_per_country_ref->{"en:cakes"}}; -store("$data_root/data/categories_stats/categories_nutriments_per_country.world.for_unit_tests.sto", $test_ref); +store("$BASE_DIRS{PRIVATE_DATA}/categories_stats/categories_nutriments_per_country.world.for_unit_tests.sto", + $test_ref); exit(0); diff --git a/scripts/deploy/verify-symlinks.sh b/scripts/deploy/verify-symlinks.sh new file mode 100644 index 0000000000000..e3e44d8daaa67 --- /dev/null +++ b/scripts/deploy/verify-symlinks.sh @@ -0,0 +1,194 @@ +#!/usr/bin/env bash +# This script verifies that every important symlink is present on a deployment +# +# short name of service must be provided as argument + +SERVICE=$1 + +KNOWN_SERVICES=(obf off off-pro opf opff) + +declare -A LONG_NAMES +LONG_NAMES[obf]=openbeautyfacts +LONG_NAMES[off]=openfoodfacts +LONG_NAMES[opf]=openproductsfoodfacts +LONG_NAMES[opff]=openpetfoodfacts + +# EXPECTED_LINKS[destination]=target +# in the sens of `ln -s target destination`` +declare -A EXPECTED_LINKS + +function is_pro { + # return -pro if it end by -pro + echo $(expr match "$1" '.*\(-pro\)') +} + +function non_pro_name { + # off-pro --> off, off --> off + echo $1 | sed 's/-pro$//' +} + +function check_args { + # check service name + if ! ( echo $KNOWN_SERVICES | grep -w "$SERVICE" ) + then + >2 echo "unknown service: $SERVICE" + exit -1 + fi + REPO_PATH="/srv/$SERVICE" + # check service is deployed as expected + if [[ ! -d $REPO_PATH/.git ]]; + >2 echo "$REPO_PATH must be a git repository" + exit -2 + fi + ZFS_PATH="/mnt/$SERVICE" + IS_PRO=$(is_pro "$SERVICE") + NON_PRO_SERVICE=$(non_pro_name "$SERVICE") + PRO_SERVICE=$NON_PRO_SERVICE"-pro" + SERVICE_LONG_NAME=${LONG_NAMES[$NON_PRO_SERVICE]} +} + +function compute_expected_links { + # links to check target - dest + # nginx configuration + EXPECTED_LINKS["/etc/nginx/sites-enabled/$SERVICE"]="$REPO_PATH/conf/nginx/sites-available/$SERVICE" + EXPECTED_LINKS["$REPO_PATH/log.conf"]="$REPO_PATH/conf/$SERVICE-log.conf" + EXPECTED_LINKS["$REPO_PATH/minion_log.conf"]="$REPO_PATH/conf/$SERVICE-minion_log.conf" + # config + EXPECTED_LINKS["$REPO_PATH/lib/ProductOpener/Config.pm"]="$REPO_PATH/lib/ProductOpener/Config_$NON_PRO_SERVICE.pm" + EXPECTED_LINKS["$REPO_PATH/po/site-specific"]="$REPO_PATH/po/$SERVICE_LONG_NAME" + # off-web + EXPECTED_LINKS["$REPO_PATH/lang"]="/srv/openfoodfacts-web/lang" + # data linked to zfs storages + EXPECTED_LINKS["$REPO_PATH/data"]="$ZFS_PATH/data" + EXPECTED_LINKS["$REPO_PATH/orgs"]="$ZFS_PATH/orgs" + EXPECTED_LINKS["$REPO_PATH/users"]="$ZFS_PATH/users" + EXPECTED_LINKS["$REPO_PATH/products"]="$ZFS_PATH/products" + EXPECTED_LINKS["$REPO_PATH/html/images/products"]="$ZFS_PATH/images/products" + # public data + EXPECTED_LINKS["$REPO_PATH/html/data"]="$ZFS_PATH/html_data" + EXPECTED_LINKS["$REPO_PATH/html/exports"]="$ZFS_PATH/html_data/exports" + EXPECTED_LINKS["$REPO_PATH/html/dump"]="$ZFS_PATH/html_data/dump" + EXPECTED_LINKS["$REPO_PATH/html/files"]="$ZFS_PATH/html_data/files" + + # .well-known + for path in apple-app-site-association apple-developer-merchantid-domain-association + do + EXPECTED_LINKS["$REPO_PATH/html/.well-known/$path"]="$REPO_PATH/conf/well-known/$SERVICE-$path" + done + # deeper link in zfs storages + EXPECTED_LINKS["$REPO_PATH/deleted.images"]="$ZFS_PATH/deleted.images" + EXPECTED_LINKS["$REPO_PATH/reverted_products"]="$ZFS_PATH/reverted_products" + EXPECTED_LINKS["$REPO_PATH/translate"]="$ZFS_PATH/translate" + + if [[ -z $IS_PRO ]] + then + EXPECTED_LINKS["$REPO_PATH/deleted_products"]="$ZFS_PATH/deleted_products" + EXPECTED_LINKS["$REPO_PATH/deleted_products_images"]="$ZFS_PATH/deleted_products_images" + # producers imports + EXPECTED_LINKS["$REPO_PATH/imports"]="$ZFS_PATH/imports" + else + EXPECTED_LINKS["$REPO_PATH/deleted_private_products"]="$ZFS_PATH/deleted_private_products" + fi + + # caches + EXPECTED_LINKS["$REPO_PATH/build-cache"]="$ZFS_PATH/cache/build-cache" + EXPECTED_LINKS["$REPO_PATH/debug"]="$ZFS_PATH/cache/debug" + EXPECTED_LINKS["$REPO_PATH/new_images"]="$ZFS_PATH/cache/new_images" + EXPECTED_LINKS["$REPO_PATH/tmp"]="$ZFS_PATH/cache/tmp" + EXPECTED_LINKS["$REPO_PATH/export_files"]="$ZFS_PATH/cache/export_files" + + # exchange path + if [[ -z $IS_PRO]] + then + EXPECTED_LINKS["/srv/$PRO_SERVICE/export_files"]="/mnt/$PRO_SERVICE/cache/export_files" + fi + + # link in zfs storages to files in git + EXPECTED_LINKS["$ZFS_PATH/html_data/data-fields.md"]="$REPO_PATH/html/data/data-fields.md" + EXPECTED_LINKS["$ZFS_PATH/html_data/data-fields.txt"]="$REPO_PATH/html/data/data-fields.txt" + + # logs + EXPECTED_LINKS["$REPO_PATH/logs"]="/var/log/$SERVICE" + EXPECTED_LINKS["$REPO_PATH/logs/apache2"]="/var/log/apache2" + EXPECTED_LINKS["$REPO_PATH/logs/nginx"]="/var/log/nginx" + + if [[ -z $IS_PRO ]] + then + # links to other projects to handle data migration between projects + for OTHER_SERVICE in "${KNOWN_SERVICES[@]}" + do + if [[ $OTHER_SERVICE != "$SERVICE" ]] && [[ -z $(is_pro "$$OTHER_SERVICE") ]] + then + EXPECTED_LINKS["/srv/$OTHER_SERVICE/products"]="/mnt/$OTHER_SERVICE/products" + EXPECTED_LINKS["/srv/$OTHER_SERVICE/html/images/products"]="/mnt/$OTHER_SERVICE/images/products" + fi + done + fi + + # nginx links + EXPECTED_LINKS["/etc/nginx/sites-enabled/$SERVICE"]="$REPO_PATH/conf/nginx/sites-available/$SERVICE" + EXPECTED_LINKS["/etc/nginx/snippets/expires-no-json-xml.conf"]="$REPO_PATH/conf/nginx/snippets/expires-no-json-xml.conf" + EXPECTED_LINKS["/etc/nginx/snippets/off.cors-headers.include"]="$REPO_PATH/conf/nginx/snippets/off.cors-headers.include" + EXPECTED_LINKS["/etc/nginx/conf.d/log_format_realip.conf"]="$REPO_PATH/conf/nginx/conf.d/log_format_realip.conf" + EXPECTED_LINKS["/etc/nginx/mime.types"]="$REPO_PATH/conf/nginx/mime.types" + if [[ $SERVICE eq "off" ]] + then + EXPECTED_LINKS["/etc/nginx/snippets/off.domain-redirects.include"]="$REPO_PATH/conf/nginx/off.domain-redirects.include" + EXPECTED_LINKS["/etc/nginx/snippets/off.locations-redirects.include"]="$REPO_PATH/conf/nginx/off.locations-redirects.include" + fi + + # apache2 links + EXPECTED_LINKS["/etc/apache2/ports.conf"]="$REPO_PATH/conf/apache-2.4/$SERVICE-ports.conf" + EXPECTED_LINKS["/etc/apache2/mods-available/mpm_prefork.conf"]="$REPO_PATH/conf/apache-2.4/$SERVICE-mpm_prefork.conf" + EXPECTED_LINKS["/etc/apache2/sites-enabled/$SERVICE"]="$REPO_PATH/conf/apache-2.4/sites-available/$SERVICE" + + # systemd links + for systemd_unit in {apache2,nginx}.service.d email-failures@.service gen_feeds_{,daily}@.{service,timer} + do + EXPECTED_LINKS["/etc/systemd/system/$systemd_unit"]="$REPO_PATH/conf/systemd/$systemd_unit" + done + + # log rotate config + EXPECTED_LINKS["/etc/logrotate.d/apache2"]="$REPO_PATH/conf/logrotate/apache2" + + # Note: other link on old versions: + # /srv/$SERVICE/users_emails.sto -> /srv/$SERVICE/users/users_emails.sto + # /srv/$SERVICE/orgs_glns.sto -> /srv/$SERVICE/orgs/orgs_glns.sto + # +} + +# check links +function check_links { + for target in ${!EXPECTED_LINKS[@]} + do + destination=${EXPECTED_LINKS[$target]} + if [[ $destination -ef $target ]] + then + GOT_ERROR=1 + >2 echo "WRONG link: $target -> $destination" + fi + done +} + + +function other_checks { + # apache2 must run with off user and group + for variable in USER GROUP + do + if ! ( grep "^export APACHE_RUN_$variable=off" /etc/apache2/envvars ) + then + GOT_ERROR=1 + >2 echo "WRONG $variable for apache2: it should be off instead of" $(grep "^export APACHE_RUN_$variable=.*" /etc/apache2/envvars) + fi + done +} + + +# run +check_args +compute_expected_links +GOT_ERROR=0 +check_links +if [[ $GOT_ERROR -ne 0 ]]; then + exit -3 +fi \ No newline at end of file diff --git a/scripts/equadis-import/run_equadis_import.sh b/scripts/equadis-import/run_equadis_import.sh deleted file mode 100755 index 03dd0d61044f3..0000000000000 --- a/scripts/equadis-import/run_equadis_import.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/sh - -cd /srv/off-pro/scripts - -# copy files modified in the last few days - -rm -rf /srv2/off-pro/equadis-data-tmp -mkdir /srv2/off-pro/equadis-data-tmp -find /home/sftp/equadis/data/ -mtime -2 -type f -exec cp {} /srv2/off-pro/equadis-data-tmp/ \; - -# turn Equadis xml files into JSON file - -export NPM_CONFIG_PREFIX=~/.npm-global - -node /srv/off-pro/scripts/convert_gs1_xml_to_json_in_dir.js /srv2/off-pro/equadis-data-tmp/ - -# convert JSON files to a single CSV file - -export PERL5LIB=. - -/srv/off-pro/scripts/convert_gs1_json_to_off_csv.pl --input-dir /srv2/off-pro/equadis-data-tmp --output /srv2/off-pro/equadis-data-tmp/equadis-data.tsv - -# import CSV file - -export PERL5LIB="/srv/off-pro/lib:${PERL5LIB}" -/srv/off-pro/scripts/import_csv_file.pl --user_id equadis --org_id equadis --source_id equadis --source_name Equadis --source_url https://equadis.com/ --manufacturer 1 --comment "Import from Equadis" --define lc=fr --images_download_dir /srv2/off-pro/equadis-images-tmp --csv_file /srv2/off-pro/equadis-data-tmp/equadis-data.tsv diff --git a/scripts/export_battle_food.pl b/scripts/export_battle_food.pl index a3ab0573f1767..7e3272d528b93 100755 --- a/scripts/export_battle_food.pl +++ b/scripts/export_battle_food.pl @@ -26,6 +26,7 @@ use CGI::Carp qw(fatalsToBrowser); use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; @@ -139,7 +140,7 @@ $total++; } - open(my $OUT, ">:encoding(UTF-8)", "$www_root/data/$lang.openfoodfacts.org.products.battlefood.10.json"); + open(my $OUT, ">:encoding(UTF-8)", "$BASE_DIRS{PUBLIC_DATA}/$lang.openfoodfacts.org.products.battlefood.10.json"); my $data = encode_json(\@products); $data =~ s/\.100g/_100g/g; print $OUT $data; diff --git a/scripts/export_database.pl b/scripts/export_database.pl index 69c680ea095c8..1c3c3092bf617 100755 --- a/scripts/export_database.pl +++ b/scripts/export_database.pl @@ -33,6 +33,7 @@ use CGI::Carp qw(fatalsToBrowser); use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; @@ -144,9 +145,9 @@ sub sanitize_field_content { $langs{$l} = 0; - my $csv_filename = "$www_root/data/$lang.$server_domain.products.csv"; - my $rdf_filename = "$www_root/data/$lang.$server_domain.products.rdf"; - my $log_filename = "$www_root/data/$lang.$server_domain.products.bad-chars.log"; + my $csv_filename = "$BASE_DIRS{PUBLIC_DATA}/$lang.$server_domain.products.csv"; + my $rdf_filename = "$BASE_DIRS{PUBLIC_DATA}/$lang.$server_domain.products.rdf"; + my $log_filename = "$BASE_DIRS{PUBLIC_DATA}/$lang.$server_domain.products.bad-chars.log"; print STDERR "Write file: $csv_filename.temp\n"; print STDERR "Write file: $rdf_filename.temp\n"; diff --git a/scripts/export_producers_platform_data_to_public_database.sh b/scripts/export_producers_platform_data_to_public_database.sh index bccf0216348d0..1e83fec7c6122 100755 --- a/scripts/export_producers_platform_data_to_public_database.sh +++ b/scripts/export_producers_platform_data_to_public_database.sh @@ -1,41 +1,31 @@ #!/bin/sh - -cd /srv/off-pro/scripts -export PERL5LIB="../lib:${PERL5LIB}" - -./export_and_import_to_public_database.pl --query states_tags=en:to-be-exported --owner org-barilla-france-sa - -./export_and_import_to_public_database.pl --query states_tags=en:to-be-exported --owner org-ferrero-france-commerciale - -./export_and_import_to_public_database.pl --query states_tags=en:to-be-exported --owner org-unilever-france-gms - -./export_and_import_to_public_database.pl --query states_tags=en:to-be-exported --owner org-unilever-france-rhd - -./export_and_import_to_public_database.pl --query states_tags=en:to-be-exported --owner org-nestle-france - -./export_and_import_to_public_database.pl --query states_tags=en:to-be-exported --owner org-panzani-sa - -./export_and_import_to_public_database.pl --query states_tags=en:to-be-exported --owner org-cristalco - -./export_and_import_to_public_database.pl --query states_tags=en:to-be-exported --owner org-materne - -./export_and_import_to_public_database.pl --query states_tags=en:to-be-exported --owner org-garofalo-france - -./export_and_import_to_public_database.pl --query states_tags=en:to-be-exported --owner org-brasseries-kronenbourg - -./export_and_import_to_public_database.pl --query states_tags=en:to-be-exported --owner org-carrefour - -./export_and_import_to_public_database.pl --query states_tags=en:to-be-exported --owner org-lustucru-frais - -./export_and_import_to_public_database.pl --query states_tags=en:to-be-exported --owner org-nestle-waters - -./export_and_import_to_public_database.pl --query states_tags=en:to-be-exported --owner org-kambly - -./export_and_import_to_public_database.pl --query states_tags=en:to-be-exported --owner org-kambly-france - -./export_and_import_to_public_database.pl --query states_tags=en:to-be-exported --owner org-saint-hubert - -./export_and_import_to_public_database.pl --query states_tags=en:to-be-exported --owner org-d-aucy - -./export_and_import_to_public_database.pl --query states_tags=en:to-be-exported --owner org-lea-nature - +# import various producers data to public platform in automated mode +# this script must be launched in /srv/off-pro/ + +export PERL5LIB="lib:${PERL5LIB}" + +PRODUCERS=( +org-barilla-france-sa +org-ferrero-france-commerciale +org-unilever-france-gms +org-unilever-france-rhd +org-nestle-france +org-panzani-sa +org-cristalco +org-materne +org-garofalo-france +org-brasseries-kronenbourg +org-carrefour +org-lustucru-frais +org-nestle-waters +org-kambly +org-kambly-france +org-saint-hubert +org-d-aucy +org-lea-nature +) + +for producer in ${PRODUCERS[@]} +do + scripts/export_and_import_to_public_database.pl --query states_tags=en:to-be-exported --owner $producer +done diff --git a/scripts/export_products_data_and_images.pl b/scripts/export_products_data_and_images.pl index 50c0001981053..7d4a46109bfc3 100755 --- a/scripts/export_products_data_and_images.pl +++ b/scripts/export_products_data_and_images.pl @@ -24,6 +24,7 @@ use utf8; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Export qw/:all/; use ProductOpener::Display qw/:all/; use ProductOpener::Products qw/:all/; @@ -169,8 +170,8 @@ if ($products_file =~ /\.gz$/) { $tar_cmd = "cvfz"; } - print STDERR "Executing tar command: tar $tar_cmd $products_file -C $data_root/products -T $tmp_file\n"; - system('tar', $tar_cmd, $products_file, "-C", "$data_root/products", "-T", $tmp_file); + print STDERR "Executing tar command: tar $tar_cmd $products_file -C $BASE_DIRS{PRODUCTS} -T $tmp_file\n"; + system('tar', $tar_cmd, $products_file, "-C", $BASE_DIRS{PRODUCTS}, "-T", $tmp_file); } if (defined $images_file) { @@ -179,8 +180,8 @@ if ($images_file =~ /\.gz$/) { $tar_cmd = "cvfz"; } - print STDERR "Executing tar command: tar $tar_cmd $images_file -C $www_root/images/products -T $tmp_file\n"; - system('tar', $tar_cmd, $images_file, "-C", "$www_root/images/products", "-T", $tmp_file); + print STDERR "Executing tar command: tar $tar_cmd $images_file -C $BASE_DIRS{PRODUCTS_IMAGES} -T $tmp_file\n"; + system('tar', $tar_cmd, $images_file, "-C", $BASE_DIRS{PRODUCTS_IMAGES}, "-T", $tmp_file); } print STDERR "$i products exported.\n"; diff --git a/scripts/export_tags_hierarchies.pl b/scripts/export_tags_hierarchies.pl index 18c10b5c598dc..0241ff6d36c2e 100755 --- a/scripts/export_tags_hierarchies.pl +++ b/scripts/export_tags_hierarchies.pl @@ -26,6 +26,7 @@ use CGI::Carp qw(fatalsToBrowser); use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; @@ -48,15 +49,15 @@ # load all tags hierarchies print STDERR "Tags.pm - exporting tags hierarchies\n"; -opendir DH2, "$data_root/lang" or die "Couldn't open $data_root/lang : $!"; +opendir DH2, $BASE_DIRS{LANG} or die "Couldn't open $BASE_DIRS{LANG} : $!"; foreach my $langid (readdir(DH2)) { next if $langid eq '.'; next if $langid eq '..'; print STDERR "Tags.pm - reading tagtypes for lang $langid\n"; next if ((length($langid) ne 2) and not($langid eq 'other')); - if (-e "$data_root/lang/$langid/tags") { - opendir DH, "$data_root/lang/$langid/tags" or die "Couldn't open the current directory: $!"; + if (-e "$BASE_DIRS{LANG}/$langid/tags") { + opendir DH, "$BASE_DIRS{LANG}/$langid/tags" or die "Couldn't open the current directory: $!"; foreach my $tagtype (readdir(DH)) { next if $tagtype !~ /(.*)\.txt/; $tagtype = $1; diff --git a/scripts/extract_images.pl b/scripts/extract_images.pl index 207b4695ef811..87237022fd700 100755 --- a/scripts/extract_images.pl +++ b/scripts/extract_images.pl @@ -37,6 +37,7 @@ use CGI::Carp qw(fatalsToBrowser); use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; @@ -91,7 +92,7 @@ if (defined $product_ref) { - my $dir = "$www_root/images/products/$path"; + my $dir = "$BASE_DIRS{PRODUCTS_IMAGES}/$path"; # Store the highest version number for each imageid diff --git a/scripts/extract_ingredients_test_set.pl b/scripts/extract_ingredients_test_set.pl index 99357350a44fe..f04fb5bb3426f 100755 --- a/scripts/extract_ingredients_test_set.pl +++ b/scripts/extract_ingredients_test_set.pl @@ -37,6 +37,7 @@ use CGI::Carp qw(fatalsToBrowser); use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; @@ -133,7 +134,7 @@ if (defined $product_ref) { - my $dir = "$www_root/images/products/$path"; + my $dir = "$BASE_DIRS{PRODUCTS_IMAGES}/$path"; next if !-e $dir; diff --git a/scripts/extract_nutrition_images_and_crop_data.pl b/scripts/extract_nutrition_images_and_crop_data.pl index d809a60bac824..dcbcc04a7f188 100755 --- a/scripts/extract_nutrition_images_and_crop_data.pl +++ b/scripts/extract_nutrition_images_and_crop_data.pl @@ -37,6 +37,7 @@ use CGI::Carp qw(fatalsToBrowser); use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; @@ -97,7 +98,7 @@ if (defined $product_ref) { - my $dir = "$www_root/images/products/$path"; + my $dir = "$BASE_DIRS{PRODUCTS_IMAGES}/$path"; next if !-e $dir; diff --git a/scripts/extract_nutrition_test_set.pl b/scripts/extract_nutrition_test_set.pl index 821ba1da039ba..b4c132aa3c2bd 100755 --- a/scripts/extract_nutrition_test_set.pl +++ b/scripts/extract_nutrition_test_set.pl @@ -37,6 +37,7 @@ use CGI::Carp qw(fatalsToBrowser); use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; @@ -125,7 +126,7 @@ if (defined $product_ref) { - my $dir = "$www_root/images/products/$path"; + my $dir = "$BASE_DIRS{PRODUCTS_IMAGES}/$path"; next if !-e $dir; diff --git a/scripts/fix_non_normalized_codes.pl b/scripts/fix_non_normalized_codes.pl index 863b1733b0099..bf3efcc79e24b 100755 --- a/scripts/fix_non_normalized_codes.pl +++ b/scripts/fix_non_normalized_codes.pl @@ -37,6 +37,7 @@ =head1 DESCRIPTION use ProductOpener::PerlStandards; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Data qw/:all/; use ProductOpener::Products qw/:all/; use ProductOpener::Store qw/:all/; @@ -49,7 +50,7 @@ ($product_path) # find all .sto files that have a non normalized code # we take a very brute force approach on filename # return a list with path, product_id and normalized_id - my $iter = sto_iter("$data_root/products", qr/product\.sto$/i); + my $iter = sto_iter($BASE_DIRS{PRODUCTS}, qr/product\.sto$/i); my @anomalous = (); while (my $product_path = $iter->()) { my $product_code = product_id_from_path($product_path); @@ -94,7 +95,7 @@ ($product_path, $dry_run, $out) # handle a special case where previous id is higly broken … # and moving would not work my $path_from_old_id = product_path_from_id($product_id); - my $is_duplicate = (-e "$data_root/products/$new_path"); + my $is_duplicate = (-e "$BASE_DIRS{PRODUCTS}/$new_path"); my $is_invalid = $path_from_old_id eq "invalid"; if ($is_duplicate || $is_invalid) { # this is probably older data than the normalized one, we will ditch it ! @@ -155,7 +156,7 @@ ($int_ids_ref, $dry_run) my $path = product_path_from_id($product_ref->{code}); if (!$dry_run) { # Silently replace values in sto (no rev) - store("$data_root/products/$path/product.sto", $product_ref); + store("$BASE_DIRS{PRODUCTS}/$path/product.sto", $product_ref); # Refresh mongodb if ($product_ref->{deleted}) { $products_collection->delete_one({"_id" => $product_ref->{_id}}); @@ -258,7 +259,7 @@ ($dry_run, $out) or die("Error in command line arguments:\n\n$usage"); # fix errors on filesystem -my $product_path = "$data_root/products"; +my $product_path = $BASE_DIRS{PRODUCTS}; fix_non_normalized_sto($product_path, $dry_run, \*STDOUT); # now that we don't have any non normalized codes on filesystem, we can fix Mongodb remove_int_barcode_mongo($dry_run, \*STDOUT); diff --git a/scripts/gen_feeds_daily_off.sh b/scripts/gen_feeds_daily_off.sh index 38ecd1540760f..b7194c8ee48b4 100755 --- a/scripts/gen_feeds_daily_off.sh +++ b/scripts/gen_feeds_daily_off.sh @@ -1,4 +1,9 @@ -#!/bin/sh +#!/usr/bin/env bash + +cd /srv/off + +# load paths +. <(perl -e 'use ProductOpener::Paths qw/:all/; print base_paths_loading_script()') cd /srv/off/scripts export PERL5LIB="../lib:${PERL5LIB}" @@ -7,9 +12,9 @@ export PERL5LIB="../lib:${PERL5LIB}" ./gen_top_tags_per_country.pl #./compute_missions.pl ./export_database.pl -./mongodb_dump.sh /srv2/off/html openfoodfacts 10.0.0.3 off +./mongodb_dump.sh /srv/off/html openfoodfacts 10.0.0.3 off -cd /srv2/off/html/data +cd $OFF_PUBLIC_DATA_DIR gzip < en.openfoodfacts.org.products.rdf > en.openfoodfacts.org.products.rdf.gz gzip < fr.openfoodfacts.org.products.rdf > fr.openfoodfacts.org.products.rdf.gz @@ -20,17 +25,15 @@ cd /srv/off/scripts # Small products data and images export for Docker dev environments # for about 1/10000th of the products contained in production. -./export_products_data_and_images.pl --sample-mod 10000,0 --products-file /srv/off/html/exports/products.random-modulo-10000.tar.gz --images-file /srv/off/html/exports/products.random-modulo-10000.images.tar.gz +./export_products_data_and_images.pl --sample-mod 10000,0 --products-file $OFF_PUBLIC_EXPORTS_DIR/products.random-modulo-10000.tar.gz --images-file $OFF_PUBLIC_EXPORTS_DIR/products.random-modulo-10000.images.tar.gz ./generate_dump_for_offline_apps_off.py -cd /srv2/off/html/data/offline +cd /srv/off/html/data/offline zip en.openfoodfacts.org.products.small.csv.zip en.openfoodfacts.org.products.small.csv -# Equadis import -/srv/off-pro/scripts/equadis-import/run_equadis_import.sh -/srv/off-pro/scripts/agena3000/run_agena3000_import.sh +# Exports for Carrefour +cd /srv/off +./scripts/export_csv_file.pl --fields code,nutrition_grades_tags --query editors_tags=carrefour --separator ';' > $OFF_PUBLIC_DATA_DIR/exports/carrefour_nutriscore.csv + +./scripts/export_csv_file.pl --fields code,nutrition_grades_tags --separator ';' > $OFF_PUBLIC_DATA_DIR/exports/nutriscore.csv -# Made near me static pages - disabled for now (too slow) -# ./generate_madenearme_page.pl uk en > /srv/off/html/madenearme-uk.html -# ./generate_madenearme_page.pl world en > /srv/off/html/madenearme.html -# ./generate_madenearme_page.pl fr fr > /srv/off/html/cestemballepresdechezvous.html diff --git a/scripts/gen_pro_users_emails_list.pl b/scripts/gen_pro_users_emails_list.pl index 390e4a95c3009..af2264f2c326e 100755 --- a/scripts/gen_pro_users_emails_list.pl +++ b/scripts/gen_pro_users_emails_list.pl @@ -26,6 +26,7 @@ use CGI::Carp qw(fatalsToBrowser); use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; require ProductOpener::GeoIP; @@ -33,7 +34,7 @@ my @userids; if (scalar $#userids < 0) { - opendir DH, "$data_root/users" or die "Couldn't open the current directory: $!"; + opendir DH, $BASE_DIRS{USERS} or die "Couldn't open the current directory: $!"; @userids = sort(readdir(DH)); closedir(DH); } @@ -42,7 +43,7 @@ next if $userid eq "." or $userid eq ".."; next if $userid eq 'all'; - my $user_ref = retrieve("$data_root/users/$userid"); + my $user_ref = retrieve("$BASE_DIRS{USERS}/$userid"); if ((defined $user_ref->{org}) and ($user_ref->{org} ne "")) { my $country = ProductOpener::GeoIP::get_country_code_for_ip($user_ref->{ip}); diff --git a/scripts/gen_sucres.pl b/scripts/gen_sucres.pl index 1ddcfd23ec489..74edaa918ff72 100755 --- a/scripts/gen_sucres.pl +++ b/scripts/gen_sucres.pl @@ -26,6 +26,7 @@ use CGI::Carp qw(fatalsToBrowser); use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; @@ -49,6 +50,15 @@ use Encode; use JSON::PP; +print STDERR ("Please fix this script before using it:\n" + . "1- do not write to lang/ (its git controlled)\n" + . "2- use Paths.pm for pathes (not /srv/sugar),\n" + . "3- only do one script of gen_sugar.pl and gen_sucre.pl,\n" + . "5- use matomo instead of GA\n" + . "4- fix bugs\n" + . "Or perhaps rework all this to use a single html page + json data\n"); +die(); + # Generate a list of the top brands, categories, users, additives etc. my @fields = qw ( @@ -615,7 +625,7 @@ $html .= ""; - open(my $OUT, ">:encoding(UTF-8)", "$data_root/lang/$lang/texts/sugar.html"); + open(my $OUT, ">:encoding(UTF-8)", "$BASE_DIRS{LANG}/$lang/texts/sugar.html"); print $OUT $html; close $OUT; diff --git a/scripts/gen_sugar.pl b/scripts/gen_sugar.pl index 9ebbd2b20b11c..d5e43da2372ff 100755 --- a/scripts/gen_sugar.pl +++ b/scripts/gen_sugar.pl @@ -27,6 +27,7 @@ use ProductOpener::Config qw/:all/; use ProductOpener::Store qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; use ProductOpener::Tags qw/:all/; @@ -49,6 +50,15 @@ use Encode; use JSON::PP; +print STDERR ("Please fix this script before using it:\n" + . "1- do not write to lang/ (its git controlled)\n" + . "2- use Paths.pm for pathes (not /srv/sugar),\n" + . "3- only do one script of gen_sugar.pl and gen_sucre.pl,\n" + . "5- use matomo instead of GA\n" + . "4- fix bugs\n" + . "Or perhaps rework all this to use a single html page + json data\n"); +die(); + # Generate a list of the top brands, categories, users, additives etc. my @fields = qw ( @@ -621,7 +631,7 @@ $html .= ""; - open(my $OUT, ">:encoding(UTF-8)", "$data_root/lang/$lang/texts/sugar.html"); + open(my $OUT, ">:encoding(UTF-8)", "$BASE_DIRS{LANG}/$lang/texts/sugar.html"); print $OUT $html; close $OUT; diff --git a/scripts/gen_top_tags_per_country.pl b/scripts/gen_top_tags_per_country.pl index 4c9b9c5b540b9..633b3c7096ec2 100755 --- a/scripts/gen_top_tags_per_country.pl +++ b/scripts/gen_top_tags_per_country.pl @@ -24,6 +24,7 @@ use utf8; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; @@ -46,19 +47,12 @@ use File::Path qw(mkpath); use JSON::PP; -# Output will be in the $data_root/data directory +# Output will be in the $BASE_DIRS{PRIVATE_DATA} directory # data/index: data related to the Open Food Hunt operation (old): points for countries, users and ambassadors # data/categories_stats: statistics for the nutrients of categories, used to compare products to their categories -(-e "$data_root/data") - or mkdir("$data_root/data", oct(755)) - or die("Could not create target directory $data_root/data : $!\n"); -(-e "$data_root/data/index") - or mkdir("$data_root/data/index", oct(755)) - or die("Could not create target directory $data_root/data/index : $!\n"); -(-e "$data_root/data/categories_stats") - or mkdir("$data_root/data/categories_stats", oct(755)) - or die("Could not create target directory $data_root/data/categories_stats : $!\n"); +ensure_dir_created_or_die("$BASE_DIRS{PRIVATE_DATA}/index"); +ensure_dir_created_or_die("$BASE_DIRS{PRIVATE_DATA}/categories_stats"); # Generate a list of the top brands, categories, users, additives etc. @@ -410,7 +404,7 @@ # compute points # Read ambassadors.txt my %ambassadors = (); -if (open(my $IN, q{<}, "$data_root/data/ambassadors.txt")) { +if (open(my $IN, q{<}, "$BASE_DIRS{PRIVATE_DATA}/ambassadors.txt")) { while (<$IN>) { chomp(); if (/\s+/) { @@ -421,7 +415,7 @@ } } else { - print STDERR "$data_root/data/ambassadors.txt does not exist\n"; + print STDERR "$BASE_DIRS{PRIVATE_DATA}/ambassadors.txt does not exist\n"; } my %ambassadors_countries_points = (_all_ => {}); @@ -451,11 +445,11 @@ } } -store("$data_root/data/index/countries_points.sto", \%countries_points); -store("$data_root/data/index/users_points.sto", \%users_points); +store("$BASE_DIRS{PRIVATE_DATA}/index/countries_points.sto", \%countries_points); +store("$BASE_DIRS{PRIVATE_DATA}/index/users_points.sto", \%users_points); -store("$data_root/data/index/ambassadors_countries_points.sto", \%ambassadors_countries_points); -store("$data_root/data/index/ambassadors_users_points.sto", \%ambassadors_users_points); +store("$BASE_DIRS{PRIVATE_DATA}/index/ambassadors_countries_points.sto", \%ambassadors_countries_points); +store("$BASE_DIRS{PRIVATE_DATA}/index/ambassadors_users_points.sto", \%ambassadors_users_points); foreach my $country (keys %{$properties{countries}}) { @@ -502,7 +496,7 @@ } } - store("$data_root/data/categories_stats/categories_nutriments_per_country.$cc.sto", \%categories); + store("$BASE_DIRS{PRIVATE_DATA}/categories_stats/categories_nutriments_per_country.$cc.sto", \%categories); # Dates @@ -534,131 +528,130 @@ } } -# Open Food Facts - What's in my yogurt? +# # Open Food Facts - What's in my yogurt? - disabled +# if ($server_domain eq 'openfoodfacts.org') { +# print "Starting yogurts_countries.html...\n"; -if ($server_domain eq 'openfoodfacts.org') { - print "Starting yogurts_countries.html...\n"; +# open(my $DEBUG, ">:encoding(UTF-8)", "/home/yogurt/html/yogurts_debug"); - open(my $DEBUG, ">:encoding(UTF-8)", "/home/yogurt/html/yogurts_debug"); +# my $html = ""; +# my $c = 0; +# foreach my $country ( +# sort { +# ($countries_tags{$b}{categories}{"en:yogurts"} // 0) +# <=> ($countries_tags{$a}{categories}{"en:yogurts"} // 0) +# } keys %countries +# ) +# { - my $html = ""; - my $c = 0; - foreach my $country ( - sort { - ($countries_tags{$b}{categories}{"en:yogurts"} // 0) - <=> ($countries_tags{$a}{categories}{"en:yogurts"} // 0) - } keys %countries - ) - { +# print $DEBUG "yogurts - $country - " +# . ($countries_tags{$country}{categories}{"en:yogurts"} // 'undefined') . "\n"; +# print STDERR "yogurts - $country - " +# . ($countries_tags{$country}{categories}{"en:yogurts"} // 'undefined') . "\n"; +# if (($countries_tags{$country}{categories}{"en:yogurts"} // 0) > 0) { +# my $cc = lc($properties{countries}{$country}{"country_code_2:en"}); +# if ($country eq 'en:world') { +# $cc = 'world'; +# } +# $lc = $country_languages{$cc}[0]; # first official language - print $DEBUG "yogurts - $country - " - . ($countries_tags{$country}{categories}{"en:yogurts"} // 'undefined') . "\n"; - print STDERR "yogurts - $country - " - . ($countries_tags{$country}{categories}{"en:yogurts"} // 'undefined') . "\n"; - if (($countries_tags{$country}{categories}{"en:yogurts"} // 0) > 0) { - my $cc = lc($properties{countries}{$country}{"country_code_2:en"}); - if ($country eq 'en:world') { - $cc = 'world'; - } - $lc = $country_languages{$cc}[0]; # first official language +# if (not exists $Langs{$lc}) { +# $lc = 'en'; +# } - if (not exists $Langs{$lc}) { - $lc = 'en'; - } +# print $DEBUG "yogurts - cc: $cc - lc: $lc \n"; - print $DEBUG "yogurts - cc: $cc - lc: $lc \n"; +# $cc ne '' or next; +# $c++; - $cc ne '' or next; - $c++; +# my $n = $countries_tags{$country}{categories}{"en:yogurts"}; +# $n =~ s/(\d)(?=(\d{3})+$)/$1/g; +# my $link +# = "" +# . display_taxonomy_tag('en', 'countries', $country) . ""; - my $n = $countries_tags{$country}{categories}{"en:yogurts"}; - $n =~ s/(\d)(?=(\d{3})+$)/$1/g; - my $link - = "" - . display_taxonomy_tag('en', 'countries', $country) . ""; +# $html .= "
  • $link - " . $countries_tags{$country}{categories}{"en:yogurts"} . " yogurts
  • \n"; +# } - $html .= "
  • $link - " . $countries_tags{$country}{categories}{"en:yogurts"} . " yogurts
  • \n"; - } +# } +# $html =~ s/ 1 yogurts/ 1 yogurt/g; - } - $html =~ s/ 1 yogurts/ 1 yogurt/g; - - my $yogurts = $countries_tags{"en:world"}{categories}{"en:yogurts"}; +# my $yogurts = $countries_tags{"en:world"}{categories}{"en:yogurts"}; - $html - = "

    $yogurts yogurts opened so far!

    \n

    $yogurts yogurts sold in $c countries and territories:

    \n
      \n$html
    \n"; +# $html +# = "

    $yogurts yogurts opened so far!

    \n

    $yogurts yogurts sold in $c countries and territories:

    \n
      \n$html
    \n"; - open(my $OUT, ">:encoding(UTF-8)", "/home/yogurt/html/yogurts_countries.html"); - print $OUT $html; - close $OUT; +# open(my $OUT, ">:encoding(UTF-8)", "/home/yogurt/html/yogurts_countries.html"); +# print $OUT $html; +# close $OUT; - close $DEBUG; +# close $DEBUG; -} +# } # Open Beauty Facts - What's in my shampoo? -if ($server_domain eq 'openbeautyfacts.org') { - print "Starting shampoos_countries.html...\n"; +# if ($server_domain eq 'openbeautyfacts.org') { +# print "Starting shampoos_countries.html...\n"; - open(my $DEBUG, ">:encoding(UTF-8)", "/home/shampoo/html/shampoos_debug"); +# open(my $DEBUG, ">:encoding(UTF-8)", "/home/shampoo/html/shampoos_debug"); - my $html = ""; - my $c = 0; - foreach my $country ( - sort { - ($countries_tags{$b}{categories}{"en:shampoos"} // 0) - <=> ($countries_tags{$a}{categories}{"en:shampoos"} // 0) - } keys %countries - ) - { +# my $html = ""; +# my $c = 0; +# foreach my $country ( +# sort { +# ($countries_tags{$b}{categories}{"en:shampoos"} // 0) +# <=> ($countries_tags{$a}{categories}{"en:shampoos"} // 0) +# } keys %countries +# ) +# { - print $DEBUG "shampoos - $country - " - . ($countries_tags{$country}{categories}{"en:shampoos"} // 'undefined') . "\n"; - print STDERR "shampoos - $country - " - . ($countries_tags{$country}{categories}{"en:shampoos"} // 'undefined') . "\n"; - if (($countries_tags{$country}{categories}{"en:shampoos"} // 0) > 0) { - my $cc = lc($properties{countries}{$country}{"country_code_2:en"}); - if ($country eq 'en:world') { - $cc = 'world'; - } - $lc = $country_languages{$cc}[0]; # first official language +# print $DEBUG "shampoos - $country - " +# . ($countries_tags{$country}{categories}{"en:shampoos"} // 'undefined') . "\n"; +# print STDERR "shampoos - $country - " +# . ($countries_tags{$country}{categories}{"en:shampoos"} // 'undefined') . "\n"; +# if (($countries_tags{$country}{categories}{"en:shampoos"} // 0) > 0) { +# my $cc = lc($properties{countries}{$country}{"country_code_2:en"}); +# if ($country eq 'en:world') { +# $cc = 'world'; +# } +# $lc = $country_languages{$cc}[0]; # first official language - if (not exists $Langs{$lc}) { - $lc = 'en'; - } +# if (not exists $Langs{$lc}) { +# $lc = 'en'; +# } - print $DEBUG "shampoos - cc: $cc - lc: $lc \n"; +# print $DEBUG "shampoos - cc: $cc - lc: $lc \n"; - $cc ne '' or next; - $c++; +# $cc ne '' or next; +# $c++; - my $n = $countries_tags{$country}{categories}{"en:shampoos"}; - $n =~ s/(\d)(?=(\d{3})+$)/$1/g; - my $link - = "" - . display_taxonomy_tag('en', 'countries', $country) . ""; +# my $n = $countries_tags{$country}{categories}{"en:shampoos"}; +# $n =~ s/(\d)(?=(\d{3})+$)/$1/g; +# my $link +# = "" +# . display_taxonomy_tag('en', 'countries', $country) . ""; - $html .= "
  • $link - " . $countries_tags{$country}{categories}{"en:shampoos"} . " shampoos
  • \n"; - } +# $html .= "
  • $link - " . $countries_tags{$country}{categories}{"en:shampoos"} . " shampoos
  • \n"; +# } - } - $html =~ s/ 1 shampoos/ 1 shampoo/g; +# } +# $html =~ s/ 1 shampoos/ 1 shampoo/g; - my $shampoos = $countries_tags{"en:world"}{categories}{"en:shampoos"}; +# my $shampoos = $countries_tags{"en:world"}{categories}{"en:shampoos"}; - $html - = "

    $shampoos shampoos opened so far!

    \n

    $shampoos shampoos sold in $c countries and territories:

    \n
      \n$html
    \n"; +# $html +# = "

    $shampoos shampoos opened so far!

    \n

    $shampoos shampoos sold in $c countries and territories:

    \n
      \n$html
    \n"; - open(my $OUT, ">:encoding(UTF-8)", "/home/shampoo/html/shampoos_countries.html"); - print $OUT $html; - close $OUT; +# open(my $OUT, ">:encoding(UTF-8)", "/home/shampoo/html/shampoos_countries.html"); +# print $OUT $html; +# close $OUT; - close $DEBUG; +# close $DEBUG; -} +# } # Number of products and complete products @@ -684,7 +677,14 @@ print "found meta products_graph_country_$cc.png image\n"; } - foreach my $lc (@{$country_languages{$cc}}) { + my @languages = (@{$country_languages{$cc}}); + if ($cc eq "world") { + # all languages + @languages = keys %Langs; + } + # also always add english + push @languages, "en" unless grep {$_ eq 'en'} @languages; + foreach my $lc (@languages) { $lang = $lc; @@ -813,17 +813,16 @@ HTML ; - print "products_stats - saving $data_root/lang/$lang/texts/products_stats_$cc.html\n"; - my $stats_dir = "$data_root/lang/$lang/texts"; - (-e $stats_dir) or mkpath($stats_dir, {"mode" => oct(755)}); + my $stats_dir = "$BASE_DIRS{PUBLIC_DATA}/products_stats/$lang"; + print "products_stats - saving $stats_dir/products_stats_$cc.html\n"; + ensure_dir_created_or_die($stats_dir); if (open(my $OUT, ">:encoding(UTF-8)", "$stats_dir/products_stats_$cc.html")) { print $OUT $html; close $OUT; } else { - print STDERR "Failed to write to '$data_root/lang/$lang/texts/products_stats_$cc.html'\n"; + print STDERR "Failed to write to '$stats_dir/products_stats_$cc.html'\n"; } - } } @@ -952,8 +951,9 @@ HTML ; - -open(my $OUT, ">:encoding(UTF-8)", "$www_root/products_countries.js"); +my $stats_dir = "$BASE_DIRS{PUBLIC_DATA}/products_stats/"; +ensure_dir_created_or_die($stats_dir); +open(my $OUT, ">:encoding(UTF-8)", "$stats_dir/products_countries.js"); print $OUT $html; close $OUT; diff --git a/scripts/gen_users_emails.pl b/scripts/gen_users_emails.pl index 90865b988c193..9d4dda3a4302e 100755 --- a/scripts/gen_users_emails.pl +++ b/scripts/gen_users_emails.pl @@ -26,12 +26,13 @@ use CGI::Carp qw(fatalsToBrowser); use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; my @userids; if (scalar $#userids < 0) { - opendir DH, "$data_root/users" or die "Couldn't open the current directory: $!"; + opendir DH, $BASE_DIRS{USERS} or die "Couldn't open the current directory: $!"; @userids = sort(readdir(DH)); closedir(DH); } @@ -40,7 +41,7 @@ next if $userid eq "." or $userid eq ".."; next if $userid eq 'all'; - my $user_ref = retrieve("$data_root/users/$userid"); + my $user_ref = retrieve("$BASE_DIRS{USERS}/$userid"); my $first = ''; if (!exists $user_ref->{discussion}) { diff --git a/scripts/gen_users_emails_list.pl b/scripts/gen_users_emails_list.pl index c567adc4864c2..c42f9f09c937a 100755 --- a/scripts/gen_users_emails_list.pl +++ b/scripts/gen_users_emails_list.pl @@ -66,13 +66,14 @@ =head1 DESCRIPTION use CGI::Carp qw(fatalsToBrowser); use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; my @userids; my $arg = $ARGV[0] || ""; if (scalar $#userids < 0) { - opendir DH, "$data_root/users" or die "Couldn't open the current directory: $!"; + opendir DH, $BASE_DIRS{USERS} or die "Couldn't open the current directory: $!"; @userids = sort(readdir(DH)); closedir(DH); } @@ -81,7 +82,7 @@ =head1 DESCRIPTION next if $userid eq "." or $userid eq ".."; next if $userid eq 'all'; - my $user_ref = retrieve("$data_root/users/$userid"); + my $user_ref = retrieve("$BASE_DIRS{USERS}/$userid"); my $first = ''; if (!exists $user_ref->{discussion}) { diff --git a/scripts/gen_users_lists.pl b/scripts/gen_users_lists.pl index 4ecbcba508455..602ad5eca8689 100755 --- a/scripts/gen_users_lists.pl +++ b/scripts/gen_users_lists.pl @@ -26,6 +26,7 @@ use CGI::Carp qw(fatalsToBrowser); use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Users qw/:all/; @@ -34,7 +35,7 @@ my %emails = (); if (scalar $#userids < 0) { - opendir DH, "$data_root/users" or die "Couldn't open the current directory: $!"; + opendir DH, $BASE_DIRS{USERS} or die "Couldn't open the current directory: $!"; @userids = sort(readdir(DH)); closedir(DH); } @@ -43,7 +44,7 @@ next if $userid eq "." or $userid eq ".."; next if $userid eq 'all'; - my $user_ref = retrieve("$data_root/users/$userid"); + my $user_ref = retrieve("$BASE_DIRS{USERS}/$userid"); $userid =~ s/\.sto$//; @@ -55,7 +56,7 @@ } } -store("$data_root/users_emails.sto", \%emails); +store("$BASE_DIRS{USERS}/users_emails.sto", \%emails); exit(0); diff --git a/scripts/gen_users_names.pl b/scripts/gen_users_names.pl index b269243b85d25..1ba387be1e91f 100755 --- a/scripts/gen_users_names.pl +++ b/scripts/gen_users_names.pl @@ -26,12 +26,13 @@ use CGI::Carp qw(fatalsToBrowser); use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; my @userids; if (scalar $#userids < 0) { - opendir DH, "$data_root/users" or die "Couldn't open the current directory: $!"; + opendir DH, $BASE_DIRS{USERS} or die "Couldn't open the current directory: $!"; @userids = sort(readdir(DH)); closedir(DH); } @@ -40,7 +41,7 @@ next if $userid eq "." or $userid eq ".."; next if $userid eq 'all'; - my $user_ref = retrieve("$data_root/users/$userid"); + my $user_ref = retrieve("$BASE_DIRS{USERS}/$userid"); my $first = ''; if (!exists $user_ref->{discussion}) { diff --git a/scripts/generate_madenearme_page.pl b/scripts/generate_madenearme_page.pl index 2a97e646e5679..cfb7720c6551c 100755 --- a/scripts/generate_madenearme_page.pl +++ b/scripts/generate_madenearme_page.pl @@ -26,6 +26,8 @@ use CGI qw/:cgi :form escapeHTML/; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; @@ -125,7 +127,7 @@ ($jsonl_path, $country) $log->info("finding products", {lc => $lc, cc => $cc, country => $country}) if $log->is_info(); -my $jsonl_path = "$www_root/data/openfoodfacts-products.jsonl.gz"; +my $jsonl_path = "$BASE_DIRS{PUBLIC_DATA}/openfoodfacts-products.jsonl.gz"; my $products_iter = iter_products_from_jsonl($jsonl_path, $country); $request_ref->{map_options} = $map_options{$cc} || ""; diff --git a/scripts/generate_madenearme_pages.sh b/scripts/generate_madenearme_pages.sh new file mode 100644 index 0000000000000..fbf998d44f360 --- /dev/null +++ b/scripts/generate_madenearme_pages.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +# get pathes +. <(perl -e 'use ProductOpener::Paths qw/:all/; print base_paths_loading_script()') + +# Made near me static pages generation +./scripts/generate_madenearme_page.pl uk en > $OFF_PUBLIC_DATA_DIR/madenearme-uk.html +./scripts/generate_madenearme_page.pl world en > $OFF_PUBLIC_DATA_DIR/madenearme.html +./scripts/generate_madenearme_page.pl fr fr > $OFF_PUBLIC_DATA_DIR/cestemballepresdechezvous.html diff --git a/scripts/generate_perl_html_doc_from_pod.pl b/scripts/generate_perl_html_doc_from_pod.pl index 5ab589ee602df..7aae9db1252d9 100755 --- a/scripts/generate_perl_html_doc_from_pod.pl +++ b/scripts/generate_perl_html_doc_from_pod.pl @@ -27,10 +27,7 @@ =head1 NAME =head1 SYNOPSIS -The script needs to be run from the root of the Product Opener installation -(e.g. /srv/off/) - - ./scripts/generate_perl_html_doc_from_pod.pl +The script is run by C =cut @@ -38,6 +35,23 @@ =head1 SYNOPSIS use utf8; use Pod::Simple::HTMLBatch; +use Getopt::Long; + +my $usage = <new; @@ -53,4 +67,4 @@ =head1 SYNOPSIS '); $batchconv->css_flurry(0); $batchconv->javascript_flurry(0); -$batchconv->batch_convert(["cgi", "scripts", "lib"], "html/files/doc/perl"); +$batchconv->batch_convert(["cgi", "scripts", "lib"], $target_dir); diff --git a/scripts/import_carrefour_pro_off1.sh b/scripts/import_carrefour_pro_off1.sh deleted file mode 100755 index 9e2893fae2b61..0000000000000 --- a/scripts/import_carrefour_pro_off1.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh - -./import_csv_file.pl --csv_file /srv/off/imports/carrefour/carrefour.csv --user_id carrefour --comment "Import Carrefour" --source_id "org-carrefour" --source_name "Carrefour" --source_url "https://www.carrefour.fr" --manufacturer --org_id carrefour --define lc=fr - diff --git a/scripts/import_csv_file.pl b/scripts/import_csv_file.pl index 0b1c120800b4a..551c81853db26 100755 --- a/scripts/import_csv_file.pl +++ b/scripts/import_csv_file.pl @@ -24,6 +24,7 @@ use utf8; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; @@ -222,7 +223,7 @@ print STDERR $stat . "\t" . (scalar keys %{$stats_ref->{$stat}}) . "\n"; - open(my $out, ">", "$data_root/tmp/import.$stat.txt") or print "Could not create import.$stat.txt : $!\n"; + open(my $out, ">", "$BASE_DIRS{CACHE_TMP}/import.$stat.txt") or print "Could not create import.$stat.txt : $!\n"; foreach my $code (sort keys %{$stats_ref->{$stat}}) { print $out $code . "\n"; diff --git a/scripts/imports/agena3000/run_agena3000_import.sh b/scripts/imports/agena3000/run_agena3000_import.sh new file mode 100755 index 0000000000000..79dc90f8aa17d --- /dev/null +++ b/scripts/imports/agena3000/run_agena3000_import.sh @@ -0,0 +1,62 @@ +#!/usr/bin/env bash +# do not continue on failure +set -e + +# load utils +. scripts/imports/imports_utils.sh + +# this script must be launch from server root (/srv/off-pro) +export PERL5LIB=lib:$PERL5LIB + +# load paths +. <(perl -e 'use ProductOpener::Paths qw/:all/; print base_paths_loading_script()') + +if [[ -z "$OFF_SFTP_HOME_DIR" ]] +then + >&2 echo "SFTP_HOME not defined, exiting" + exit 10 +fi + +# Mirror data from Agena3000's server +# access needs to be configured in ~/.netrc +declare -x LFTP_HOME=$OFF_PRIVATE_DATA_DIR/secrets/ + +# copy files from Agena3000's server (mirroring) +lftp -c "set cmd:default-protocol sftp; open sftp-a3dm.agena3000.com:2222; mirror --Remove-source-files /PROD/Fiches/ $OFF_SFTP_HOME_DIR/agena3000/PROD/Fiches/" + +# copy files modified since last run +DATA_TMP_DIR=$OFF_CACHE_TMP_DIR/agena3000-data + +SUCCESS_FILE_PATH="$OFF_PRIVATE_DATA_DIR/agena3000-import-success" + +IMPORT_SINCE=$(import_since $SUCCESS_FILE_PATH) + +# copy files modified in the last succesful run +rm -rf $DATA_TMP_DIR +mkdir $DATA_TMP_DIR +find $OFF_SFTP_HOME_DIR/agena3000/PROD/Fiches/ -mtime -$IMPORT_SINCE -type f -exec cp {} $DATA_TMP_DIR/ \; + +# turn GS1 XML files into JSON file +./scripts/convert_gs1_xml_to_json_in_dir.pl $DATA_TMP_DIR || exit 100; + +# convert JSON files to a single CSV file +./scripts/convert_gs1_json_to_off_csv.pl \ + --input-dir $DATA_TMP_DIR --output $DATA_TMP_DIR/agena3000-data.tsv \ + --confirmation-dir $DATA_TMP_DIR/Ack + +# STOP here to test ! +# exit 1 + +# import CSV file +./scripts/import_csv_file.pl \ + --user_id agena3000 --org_id agena3000 --source_id agena3000 \ + --source_name Agena3000 --source_url https://agena3000.com/ \ + --manufacturer 1 --comment "Import from Agena3000" --define lc=fr \ + --images_download_dir $DATA_TMP_DIR \ + --csv_file $DATA_TMP_DIR/agena3000-data.tsv + +# Send confirmation messages to Agena3000 +lftp -c "set cmd:default-protocol sftp; open sftp-a3dm.agena3000.com:2222; mirror -R --Remove-source-files $DATA_TMP_DIR/Ack/ /PROD/Ack/" + +# mark sucessful run +mark_successful_run $SUCCESS_FILE_PATH diff --git a/scripts/imports/carrefour/Nomenclature_OpenFoodFacts.csv b/scripts/imports/carrefour/Nomenclature_OpenFoodFacts.csv new file mode 100644 index 0000000000000..516071d159484 --- /dev/null +++ b/scripts/imports/carrefour/Nomenclature_OpenFoodFacts.csv @@ -0,0 +1,5490 @@ +[Produit] EAN [Produit] Secteur [Produit] Nomenclature +3184830001332 LIQUIDES Mousseux d'appellation +3184830001349 LIQUIDES Mousseux d'appellation +3184830025550 EPICERIE Confiserie de chocolat +3184830025550 EPICERIE Confiserie de chocolat +3184830027950 EPICERIE Cafés moulus +3184830028049 EPICERIE Cafés en grains +3184830028070 EPICERIE Cafés moulus +3184830028100 EPICERIE Cafés en grains +3184830028131 EPICERIE Cafés moulus +3184830028162 EPICERIE Cafés en grains +3184830028193 EPICERIE Cafés moulus +3184830028223 EPICERIE Cafés en grains +3184830028438 EPICERIE Cafés en dosettes +3184830028469 EPICERIE Cafés en dosettes +3184830032015 PRODUITS FRAIS Volailles Découpes / Préparations +3184830032046 PRODUITS FRAIS Volailles Découpes / Préparations +3184830032169 PRODUITS FRAIS Autres découpes de porc +3184830032190 PRODUITS FRAIS Saumon fumés +3184830032220 PRODUITS FRAIS Saumon fumés +3184830032251 PRODUITS FRAIS Saumon fumés +3184830032572 PRODUITS FRAIS Surimi +3184830032602 PRODUITS FRAIS Surimi +3184830032886 PRODUITS FRAIS Bacs Crèmes Glacées +3184830032909 PRODUITS FRAIS Saumon fumés +3184830032916 PRODUITS FRAIS Saumon fumés +3184830032947 PRODUITS FRAIS Autres poissons fumés +3184830032978 PRODUITS FRAIS Autres poissons fumés +3184830033791 PRODUITS FRAIS Crèmes longue conservation +3184830034231 PRODUITS FRAIS Oeufs +3184830034361 PRODUITS FRAIS Autres saucisses +3184830034422 PRODUITS FRAIS Autres saucisses +3184830034453 PRODUITS FRAIS Beurres Sans sel +3184830034484 PRODUITS FRAIS Baies et fruits entiers surgelés +3184830034507 PRODUITS FRAIS Cocktails de fruits surgelés +3184830034552 PRODUITS FRAIS Baies et fruits entiers surgelés +3184830034729 PRODUITS FRAIS Salades +3184830034897 PRODUITS FRAIS Lardons +3184830034927 PRODUITS FRAIS Lardons +3184830034958 PRODUITS FRAIS Lardons +3184830034989 PRODUITS FRAIS Poitrine de porc +3184830035016 PRODUITS FRAIS Poitrine de porc +3184830035047 PRODUITS FRAIS Poitrine de porc +3184830049754 EPICERIE Cafés moulus +3184830051634 EPICERIE Carottes +3184830051634 EPICERIE Carottes +3184830052976 EPICERIE Moutardes +3184830052983 EPICERIE Moutardes +3184830053010 EPICERIE Moutardes +3184830053041 EPICERIE Moutardes +3184830054161 LIQUIDES ALCOOLS BOUL/PATISS. +3184830054222 LIQUIDES ALCOOLS BOUL/PATISS. +3184830054284 LIQUIDES ALCOOLS BOUL/PATISS. +3184830054376 LIQUIDES ALCOOLS BOUL/PATISS. +3184830054383 LIQUIDES ALCOOLS BOUL/PATISS. +3184830054765 EPICERIE Autres mélanges de légumes +3184830055540 EPICERIE Biscuits sucrés Secs +3184830055687 EPICERIE Biscuits sucrés Secs +3184830055694 EPICERIE Biscuits sucrés Secs +3184830057230 EPICERIE Desserts a preparer +3184830057261 EPICERIE Desserts a preparer +3184830057322 EPICERIE Desserts a preparer +3184830057353 EPICERIE Desserts a preparer +3184830057384 EPICERIE Desserts a preparer +3184830057414 EPICERIE Desserts a preparer +3184830057513 EPICERIE Desserts a preparer +3184830057544 EPICERIE Desserts a preparer +3184830057575 EPICERIE Desserts a preparer +3184830057698 EPICERIE Desserts a preparer +3184830057759 EPICERIE ,Chocolat patissier,,couverture, +3184830057759 EPICERIE ,Chocolat patissier,,couverture, +3184830057780 EPICERIE ,Chocolat patissier,,couverture, +3184830057780 EPICERIE ,Chocolat patissier,,couverture, +3184830057780 EPICERIE ,Chocolat patissier,,couverture, +3184830057810 EPICERIE ,Chocolat patissier,,couverture, +3184830057810 EPICERIE ,Chocolat patissier,,couverture, +3184830057841 EPICERIE ,Chocolat patissier,,couverture, +3184830057841 EPICERIE ,Chocolat patissier,,couverture, +3184830057872 PRODUITS FRAIS Traiteur sucré +3184830057902 PRODUITS FRAIS Traiteur sucré +3184830057964 PRODUITS FRAIS Traiteur sucré +3184830058022 EPICERIE ,Chocolat patissier,,couverture, +3184830058022 EPICERIE ,Chocolat patissier,,couverture, +3184830060964 PRODUITS FRAIS Bœuf haché / Préparation / Découpe +3184830061046 EPICERIE Conserves de Poires +3184830061169 EPICERIE Conserves d'Abricots +3184830061190 EPICERIE Conserves d'Abricots +3184830061220 EPICERIE Conserves de Poires +3184830061350 PRODUITS FRAIS Fromages de chevre +3184830061664 EPICERIE Levures +3184830061664 EPICERIE ,Aromes,, colorants,, decors, +3184830061763 EPICERIE ,Aromes,, colorants,, decors, +3184830061763 EPICERIE Levures +3184830061794 EPICERIE ,Aromes,, colorants,, decors, +3184830061794 EPICERIE ,Aromes,, colorants,, decors, +3184830061794 EPICERIE ,Aromes,, colorants,, decors, +3184830062449 PRODUITS FRAIS Bœuf haché / Préparation / Découpe +3184830062654 PRODUITS FRAIS Bœuf haché / Préparation / Découpe +3184830062708 PRODUITS FRAIS Bœuf haché / Préparation / Découpe +3184830063613 PRODUITS FRAIS Crèmes fraiches epaisses +3184830063620 EPICERIE Biscuits sucrés Secs +3184830063651 EPICERIE Biscuits sucrés Secs +3184830063682 EPICERIE Biscuits sucrés Secs +3184830064153 PRODUITS FRAIS Fromages blanc nature +3184830065143 PRODUITS FRAIS Charc.volaille et autre viande +3184830065495 PRODUITS FRAIS Salades +3184830066461 PRODUITS FRAIS Pains de mie élaboré +3184830066492 EPICERIE Desserts a preparer +3184830066508 EPICERIE Desserts a preparer +3184830066539 EPICERIE Desserts a preparer +3184830067031 PRODUITS FRAIS ,Quiches,, tartes,, tourtes surgelées, +3184830067055 EPICERIE Cafés moulus +3184830067116 EPICERIE Cafés en grains +3184830101407 PRODUITS FRAIS Pains de mie élaboré +3184830101520 PRODUITS FRAIS Gateaux glacés à partager +3184830101537 EPICERIE ,Coulis,, nappages, +3184830101704 EPICERIE ,Coulis,, nappages, +3184830101759 EPICERIE ,Coulis,, nappages, +3184830101780 EPICERIE ,Coulis,, nappages, +3184830101933 PRODUITS FRAIS Fromages blanc nature +3184830102060 PRODUITS FRAIS Patisseries et tartes surgelées +3184830134405 PRODUITS FRAIS Foie gras +3184830134726 EPICERIE Desserts a preparer +3184830134764 PRODUITS FRAIS ,Brioche,, buns,, specialite individuelle, +3237580171838 EPICERIE Autres produits patisserie +3245390019806 EPICERIE Sauces chaudes à base de tomate et tomate frito +3245390020314 LIQUIDES Cidres +3245390020321 LIQUIDES Cidres +3245390020390 LIQUIDES Purs Jus de Fruits - Pomme +3245390021540 PRODUITS FRAIS Quenelles +3245390021557 PRODUITS FRAIS Quenelles +3245390024572 PRODUITS FRAIS Rillettes +3245390026491 PRODUITS FRAIS ,Quiches,, tartes,, tourtes surgelées, +3245390028150 EPICERIE Sauces chaudes - pâtes - riz +3245390028884 PRODUITS FRAIS Autres saucisses +3245390031402 EPICERIE Biscuits sucrés Fourres +3245390035547 PRODUITS FRAIS Autres poissons fumés +3245390035547 PRODUITS FRAIS Autres poissons fumés +3245390036056 EPICERIE Conserves Plats cuisines base de legumes +3245390037176 EPICERIE Petits pains type suédois +3245390037183 EPICERIE Petits pains type suédois +3245390037190 EPICERIE Riz parfumés (Basmati & Thaï) +3245390039163 EPICERIE Conserves Plats cuisines base de legumes +3245390039668 EPICERIE Biscuits sucrés Secs +3245390043474 PRODUITS FRAIS Quenelles +3245390048653 PRODUITS FRAIS Foie gras +3245390048660 PRODUITS FRAIS Foie gras +3245390060839 PRODUITS FRAIS Autres saucisses +3245390066022 EPICERIE Bonbons gélifiés +3245390075048 EPICERIE Confitures d autres fruits +3245390082589 EPICERIE Conserves de poissons tartinables +3245390082596 EPICERIE Conserves de poissons tartinables +3245390089816 PRODUITS FRAIS Autres produits traiteur frais +3245390089854 PRODUITS FRAIS Autres produits traiteur frais +3245390093769 PRODUITS FRAIS Autres saucisses +3245390108197 EPICERIE Conserves de Thon +3245390108241 EPICERIE Conserves de Thon +3245390108258 EPICERIE Conserves de Thon +3245390117076 PRODUITS FRAIS Foie gras +3245390125712 EPICERIE Pâtés +3245390129840 PRODUITS FRAIS Fromages de chevre +3245390132918 PRODUITS FRAIS Pates pressées non cuites +3245390141033 EPICERIE Croquettes sec +3245390147943 PRODUITS FRAIS Autres produits preparés +3245390159090 LIQUIDES Vins doux naturels +3245390181947 PRODUITS FRAIS Gateaux glacés à partager +3245390181954 PRODUITS FRAIS Autres produits preparés +3245390189844 PRODUITS FRAIS Foie gras +3245390192417 PRODUITS FRAIS Pizzas surgelées - Feu de bois +3245390207838 PRODUITS FRAIS Comte +3245390207838 PRODUITS FRAIS Comte +3245390207838 PRODUITS FRAIS Comte +3245390211927 PRODUITS FRAIS Pates fourrees +3245390220660 EPICERIE Conserves de poissons tartinables +3245390221698 PRODUITS FRAIS Beurres Sans sel +3245390221728 PRODUITS FRAIS Beurres Sales +3245390221780 EPICERIE Carottes +3245390226549 PRODUITS FRAIS Autres saucisses +3245390502810 PRODUITS FRAIS Préparation pommes de terres +3245390236135 PRODUITS FRAIS Foie gras +3245390502810 PRODUITS FRAIS Préparation pommes de terres +3245411216818 PRODUITS FRAIS Fromages frais type nature +3245390591937 EPICERIE Boissons chocolatées instantanées +3245390787064 PRODUITS FRAIS Préparation pommes de terres +3245390886989 EPICERIE Pommes de terre +3245394312811 EPICERIE Bonbons gélifiés +3245394673127 EPICERIE Bonbons gélifiés +3245397004652 PRODUITS FRAIS Frites surgelées +3245397162789 EPICERIE Biscuits sucrés Au chocolat +3245410085064 LIQUIDES Mousseux d'appellation +3245410085064 LIQUIDES Mousseux d'appellation +3245411216818 PRODUITS FRAIS Fromages frais type nature +3245411157944 EPICERIE Produits diététiques A base de soja +3245411307769 PRODUITS FRAIS Pates à tarte fraiches +3245411307769 PRODUITS FRAIS Pates à tarte fraiches +3245411253844 EPICERIE Produits diététiques Galettes de riz +3245411253844 EPICERIE Produits diététiques Galettes de riz +3245411439897 PRODUITS FRAIS Spécialités festives (Bûches - Bûchettes...) +3245411439897 PRODUITS FRAIS Spécialités festives (Bûches - Bûchettes...) +3245411439903 PRODUITS FRAIS Spécialités festives (Bûches - Bûchettes...) +3245411439903 PRODUITS FRAIS Spécialités festives (Bûches - Bûchettes...) +3245411440176 PRODUITS FRAIS Plats cuisinés surgelés - a base de pates +3245411440176 PRODUITS FRAIS Plats cuisinés surgelés - a base de pates +3245411730581 PRODUITS FRAIS Plats cuisinés surgelés - poisson/fruit m +3245411730581 PRODUITS FRAIS Plats cuisinés surgelés - poisson/fruit m +3245411400965 EPICERIE Compotes pots / coupelles +3245411823139 PRODUITS FRAIS Libre service - Autres volailles +3245411823139 PRODUITS FRAIS Libre service - Autres volailles +3245411823139 PRODUITS FRAIS Libre service - Autres volailles +3245411823498 PRODUITS FRAIS Libre service - Autres volailles +3245411823498 PRODUITS FRAIS Libre service - Autres volailles +3245411851149 PRODUITS FRAIS Crèmes longue conservation +3245411851149 PRODUITS FRAIS Crèmes longue conservation +3245411851149 PRODUITS FRAIS Crèmes longue conservation +3245411573669 EPICERIE Produits diététiques Autres sucrés +3245411640620 EPICERIE Boissons chocolatées instantanées +3245411640798 PFT Fruits moelleux +3245411640804 PFT Fruits moelleux +3245411640835 PFT Pruneaux +3245411653118 EPICERIE Confiserie et chocolats paques +3245412001444 EPICERIE Conserves Asperges +3245411756710 EPICERIE Biscuits sucrés Aux fruits +3245411756789 EPICERIE Biscuits sucrés Aux fruits +3245412001444 EPICERIE Conserves Asperges +3245412051661 PRODUITS FRAIS Panettone/brioche/prd tranche +3245412051661 PRODUITS FRAIS Panettone/brioche/prd tranche +3245411868086 EPICERIE Confiserie et chocolats noel +3245411869427 EPICERIE Confiserie et chocolats noel +3245411878832 EPICERIE Conserves d'Ananas +3245411891800 PRODUITS FRAIS Saumon fumés +3245411891855 PRODUITS FRAIS Saumon fumés +3245412457128 PRODUITS FRAIS Patisseries industrielles - gateaux a trancher +3245412457128 PRODUITS FRAIS Patisseries industrielles - gateaux a trancher +3245412477478 PRODUITS FRAIS Saumon fumés +3245412477478 PRODUITS FRAIS Saumon fumés +3245412487996 PRODUITS FRAIS Panettone/brioche/prd tranche +3245412487996 PRODUITS FRAIS Panettone/brioche/prd tranche +3245412487996 PRODUITS FRAIS Panettone/brioche/prd tranche +3245412487996 PRODUITS FRAIS Panettone/brioche/prd tranche +3245412496509 PRODUITS FRAIS Panettone/brioche/prd tranche +3245412496509 PRODUITS FRAIS Panettone/brioche/prd tranche +3245412542831 EPICERIE Conserves de Sardines +3245412542831 EPICERIE Conserves de Sardines +3245412542862 EPICERIE Conserves de Sardines +3245412542862 EPICERIE Conserves de Sardines +3245412567216 PRODUITS FRAIS Pains de mie élaboré +3245412567216 PRODUITS FRAIS Pains de mie élaboré +3245412681592 EPICERIE Conserves de Peches +3245412681592 EPICERIE Conserves de Peches +3245412681592 EPICERIE Conserves de Peches +3245412718649 EPICERIE Conserves d'Abricots +3245412718649 EPICERIE Conserves d'Abricots +3245412730764 PRODUITS FRAIS Compotes de pommes +3245412730764 PRODUITS FRAIS Compotes pommes + fruits +3245412730764 PRODUITS FRAIS Compotes pommes + fruits +3245412730764 PRODUITS FRAIS Compotes pommes + fruits +3245412304941 EPICERIE Chocolat tablette - noirs +3245412730771 PRODUITS FRAIS Compotes pommes + fruits +3245412730771 PRODUITS FRAIS Compotes pommes + fruits +3245412730771 PRODUITS FRAIS Compotes de pommes +3245412730870 PRODUITS FRAIS Compotes pommes + fruits +3245412730870 PRODUITS FRAIS Compotes pommes + fruits +3245412730917 PRODUITS FRAIS Compotes pommes + fruits +3245412730917 PRODUITS FRAIS Compotes pommes + fruits +3245412730924 PRODUITS FRAIS Compotes pommes + fruits +3245412730924 PRODUITS FRAIS Compotes pommes + fruits +3245412801013 PRODUITS FRAIS Pates à tarte fraiches +3245412801013 PRODUITS FRAIS Pates à tarte fraiches +3245412847059 PRODUITS FRAIS Oeufs +3245412847059 PRODUITS FRAIS Oeufs +3245412849381 EPICERIE Huile de colza +3245412849381 EPICERIE Huile de colza +3245412849381 EPICERIE Huile de colza +3245412414909 EPICERIE Confiserie et chocolats noel +3245412414916 EPICERIE Confiserie et chocolats noel +3245412966620 PRODUITS FRAIS Libre service - Produits carnes prepares +3245412966620 PRODUITS FRAIS Libre service - Produits carnes prepares +3245412966637 PRODUITS FRAIS Libre service - Produits carnes prepares +3245412966637 PRODUITS FRAIS Libre service - Produits carnes prepares +3245412997785 PRODUITS FRAIS Autres pains industriels +3245412997785 PRODUITS FRAIS Autres pains industriels +3245413167064 PRODUITS FRAIS Libre service - Autres volailles +3245413167064 PRODUITS FRAIS Libre service - Autres volailles +3245413167064 PRODUITS FRAIS Libre service - Autres volailles +3245412563034 EPICERIE Conserves - Autres plats cuisines +3245412563041 EPICERIE Conserves - Autres plats cuisines +3245412563256 EPICERIE Conserves - Autres plats cuisines +3245412563331 EPICERIE Conserves - Autres plats cuisines +3245412568329 EPICERIE Conserves - Autres plats cuisines +3245412568749 EPICERIE Conserves - Autres plats cuisines +3245412569081 EPICERIE Conserves - Autres plats cuisines +3245412569098 EPICERIE Conserves - Autres plats cuisines +3245413205452 PRODUITS FRAIS Libre service - Produits carnes prepares +3245413205452 PRODUITS FRAIS Libre service - Produits carnes prepares +3245412590214 EPICERIE Produits diététiques Autres sucrés +3245413330338 PRODUITS FRAIS Libre service - Produits carnes prepares +3245413330338 PRODUITS FRAIS Libre service - Produits carnes prepares +3245413330338 PRODUITS FRAIS Libre service - Produits carnes prepares +3245413330338 PRODUITS FRAIS Libre service - Produits carnes prepares +3245413330352 PRODUITS FRAIS Libre service - Produits carnes prepares +3245413330352 PRODUITS FRAIS Libre service - Produits carnes prepares +3245413330352 PRODUITS FRAIS Libre service - Produits carnes prepares +3245413330499 PRODUITS FRAIS Libre service - Produits carnes prepares +3245413330499 PRODUITS FRAIS Libre service - Produits carnes prepares +3245413330499 PRODUITS FRAIS Libre service - Produits carnes prepares +3245413330499 PRODUITS FRAIS Libre service - Produits carnes prepares +3245412699160 EPICERIE Cafés en grains +3245413330499 PRODUITS FRAIS Libre service - Produits carnes prepares +3245413543202 PRODUITS FRAIS Bœuf haché / Préparation / Découpe +3245413543202 PRODUITS FRAIS Bœuf haché / Préparation / Découpe +3245413543202 PRODUITS FRAIS Bœuf haché / Préparation / Découpe +3245413553300 PRODUITS FRAIS Autres patisseries et gateaux industriels +3245413553300 PRODUITS FRAIS Autres patisseries et gateaux industriels +3245413553379 PRODUITS FRAIS Autres patisseries et gateaux industriels +3245413553379 PRODUITS FRAIS Autres patisseries et gateaux industriels +3245413821614 PRODUITS FRAIS Panettone/brioche/prd tranche +3245413821614 PRODUITS FRAIS Panettone/brioche/prd tranche +3245412742569 EPICERIE ,Coulis,, nappages, +3245412749018 PRODUITS FRAIS Produits exotiques +3245413821614 PRODUITS FRAIS Panettone/brioche/prd tranche +3245412749957 PRODUITS FRAIS Entrées exotiques +3245412846991 PRODUITS FRAIS Oeufs +3245412846991 PRODUITS FRAIS Oeufs +3245412846991 PRODUITS FRAIS Oeufs +3245412846991 PRODUITS FRAIS Oeufs +3245412846991 PRODUITS FRAIS Oeufs +3245413881410 PRODUITS FRAIS Libre service - Produits carnes prepares +3245413881410 PRODUITS FRAIS Libre service - Produits carnes prepares +3245413881410 PRODUITS FRAIS Libre service - Produits carnes prepares +3245413881410 PRODUITS FRAIS Libre service - Produits carnes prepares +3245413881410 PRODUITS FRAIS Libre service - Produits carnes prepares +3245413881458 PRODUITS FRAIS Charc.volaille et autre viande +3245413881458 PRODUITS FRAIS Charc.volaille et autre viande +3245413937629 PRODUITS FRAIS Libre service - Produits carnes prepares +3245413937629 PRODUITS FRAIS Libre service - Produits carnes prepares +3245414091351 PRODUITS FRAIS ,Quiches,, tartes,, tourtes surgelées, +3245414091351 PRODUITS FRAIS ,Quiches,, tartes,, tourtes surgelées, +3245412950773 EPICERIE Confiserie et chocolats noel +3245412954467 EPICERIE Confiserie et chocolats noel +3245412962318 EPICERIE Confiserie et chocolats noel +3245412968150 EPICERIE Moutardes +3245412980152 EPICERIE Chocolat tablette - noirs +3245414192508 PRODUITS FRAIS Laits longue conservation natu +3245414192508 PRODUITS FRAIS Laits longue conservation natu +3245414192508 PRODUITS FRAIS Laits longue conservation natu +3245414192508 PRODUITS FRAIS Laits longue conservation natu +3245414192508 PRODUITS FRAIS Laits longue conservation natu +3245414192508 PRODUITS FRAIS Laits longue conservation natu +3245414192508 PRODUITS FRAIS Laits longue conservation natu +3245414192508 PRODUITS FRAIS Laits longue conservation natu +3245414349971 EPICERIE Compotes pots / coupelles +3245414349971 EPICERIE Compotes pots / coupelles +3245413152527 PFT Sachet/Barquettes Monovarietes +3245413152527 PFT Sachet/Barquettes Monovarietes +3245413152527 PFT Sachet/Barquettes Monovarietes +3245413152527 PFT Sachet/Barquettes Monovarietes +3245413152527 PFT Sachet/Barquettes Monovarietes +3245413152527 PFT Sachet/Barquettes Monovarietes +3245413152527 PFT Sachet/Barquettes Monovarietes +3245413152527 PFT Sachet/Barquettes Monovarietes +3245413157522 PFT Salade Sachet/Barquettes Autre +3245413157522 PFT Salade Sachet/Barquettes Autre +3245413157522 PFT Salade Sachet/Barquettes Autre +3245413157522 PFT Salade Sachet/Barquettes Autre +3245413157522 PFT Salade Sachet/Barquettes Autre +3245413157522 PFT Salade Sachet/Barquettes Autre +3245413157522 PFT Salade Sachet/Barquettes Autre +3245413157522 PFT Salade Sachet/Barquettes Autre +3245413157522 PFT Salade Sachet/Barquettes Autre +3245413451804 EPICERIE Produits diététiques Autres sucrés +3245413458513 EPICERIE Produits diététiques Autres salés +3245413495457 EPICERIE Confiserie et chocolats noel +3245413497901 EPICERIE Conserves - Autres plats cuisines +3245413527134 PRODUITS FRAIS Dessert patissier +3270190007890 EPICERIE Cafés moulus +3270190007890 EPICERIE Cafés moulus +3270190020073 PRODUITS FRAIS Plats cuisinés surgelés - a base de pates +3270190020073 PRODUITS FRAIS Plats cuisinés surgelés - a base de pates +3270190020103 PRODUITS FRAIS Bœuf haché / Préparation / Découpe +3245413575579 PRODUITS FRAIS Autres patisseries et gateaux industriels +3245413579225 PRODUITS FRAIS Autres patisseries et gateaux industriels +3245413579256 PRODUITS FRAIS Autres patisseries et gateaux industriels +3245413579287 PRODUITS FRAIS Autres patisseries et gateaux industriels +3270190020103 PRODUITS FRAIS Bœuf haché / Préparation / Découpe +3270190020103 PRODUITS FRAIS Bœuf haché / Préparation / Découpe +3270190020103 PRODUITS FRAIS Bœuf haché / Préparation / Découpe +3270190020288 PRODUITS FRAIS Beurres Sans sel +3270190020288 PRODUITS FRAIS Beurres Sans sel +3270190020288 PRODUITS FRAIS Beurres Sans sel +3270190020288 PRODUITS FRAIS Beurres Sans sel +3270190020295 PRODUITS FRAIS Beurres Sales +3245413754196 EPICERIE Confiserie et chocolats paques +3245413758866 LIQUIDES Sirops concentrés - Autres sirops +3245413761576 EPICERIE Confiserie et chocolats paques +3245413761590 EPICERIE Confiserie et chocolats paques +3245413761804 EPICERIE Confiserie et chocolats paques +3245413761842 EPICERIE Confiserie et chocolats paques +3245413766960 EPICERIE Confiserie et chocolats paques +3270190020295 PRODUITS FRAIS Beurres Sales +3270190020356 PRODUITS FRAIS Légumes verts surgelés +3270190020356 PRODUITS FRAIS Légumes verts surgelés +3270190020356 PRODUITS FRAIS Légumes verts surgelés +3245413781284 LIQUIDES Boissons anisées sans alcool +3270190020356 PRODUITS FRAIS Légumes verts surgelés +3270190020394 PRODUITS FRAIS Légumes verts surgelés +3270190020394 PRODUITS FRAIS Légumes verts surgelés +3270190020394 PRODUITS FRAIS Légumes verts surgelés +3270190020561 PRODUITS FRAIS Beurres Sales +3270190020561 PRODUITS FRAIS Beurres Sales +3270190020660 PRODUITS FRAIS Légumes verts surgelés +3270190020660 PRODUITS FRAIS Légumes verts surgelés +3270190020660 PRODUITS FRAIS Légumes verts surgelés +3270190020660 PRODUITS FRAIS Légumes verts surgelés +3270190020868 PRODUITS FRAIS Crèmes fraiches epaisses +3270190020868 PRODUITS FRAIS Crèmes fraiches epaisses +3270190020868 PRODUITS FRAIS Crèmes fraiches epaisses +3270190020875 PRODUITS FRAIS Crèmes fraiches epaisses +3270190020875 PRODUITS FRAIS Crèmes fraiches epaisses +3270190020875 PRODUITS FRAIS Crèmes fraiches epaisses +3270190020875 PRODUITS FRAIS Crèmes fraiches epaisses +3270190020936 PRODUITS FRAIS Fromages blanc allegés +3270190020998 PRODUITS FRAIS Crèmes fraiches epaisses +3270190020998 PRODUITS FRAIS Crèmes fraiches epaisses +3270190020998 PRODUITS FRAIS Crèmes fraiches epaisses +3270190021001 PRODUITS FRAIS Crèmes fraiches epaisses +3270190021001 PRODUITS FRAIS Crèmes fraiches epaisses +3270190021001 PRODUITS FRAIS Crèmes fraiches epaisses +3270190021063 PRODUITS FRAIS Oeufs +3270190021063 PRODUITS FRAIS Oeufs +3270190021063 PRODUITS FRAIS Oeufs +3270190021063 PRODUITS FRAIS Oeufs +3270190021063 PRODUITS FRAIS Oeufs +3270190021063 PRODUITS FRAIS Oeufs +3270190021063 PRODUITS FRAIS Oeufs +3270190021063 PRODUITS FRAIS Oeufs +3270190021087 PRODUITS FRAIS Fromages blanc nature +3270190021087 PRODUITS FRAIS Fromages blanc nature +3270190021087 PRODUITS FRAIS Fromages blanc nature +3270190021148 PRODUITS FRAIS Coulommiers +3270190021148 PRODUITS FRAIS Coulommiers +3270190021285 PRODUITS FRAIS Oeufs +3270190021285 PRODUITS FRAIS Oeufs +3270190021285 PRODUITS FRAIS Oeufs +3270190021285 PRODUITS FRAIS Oeufs +3245413898562 EPICERIE Conserves - Autres plats cuisines +3270190021285 PRODUITS FRAIS Oeufs +3270190021285 PRODUITS FRAIS Oeufs +3270190021285 PRODUITS FRAIS Oeufs +3245413942876 PRODUITS FRAIS Pates fourrees +3270190022510 PRODUITS FRAIS Pates à tarte fraiches +3245413985811 PFT Sachet/Barquettes Monovarietes +3245413985811 PFT Sachet/Barquettes Monovarietes +3270190022510 PRODUITS FRAIS Pates à tarte fraiches +3245414009622 EPICERIE Confiserie et chocolats noel +3270190022510 PRODUITS FRAIS Pates à tarte fraiches +3245414061071 PFT Sachet/Barquettes Monovarietes +3245414061071 PFT Sachet/Barquettes Monovarietes +3245414061071 PFT Sachet/Barquettes Monovarietes +3245414061071 PFT Sachet/Barquettes Monovarietes +3245414061071 PFT Sachet/Barquettes Monovarietes +3245414062139 PFT Sachet/Barquettes Composees +3245414062139 PFT Sachet/Barquettes Composees +3245414068759 PFT Sachet/Barquettes Monovarietes +3245414068759 PFT Sachet/Barquettes Monovarietes +3270190022510 PRODUITS FRAIS Pates à tarte fraiches +3270190022527 PRODUITS FRAIS Pates à tarte fraiches +3245414079069 PRODUITS FRAIS Saumon fumés +3270190022527 PRODUITS FRAIS Pates à tarte fraiches +3270190022527 PRODUITS FRAIS Pates à tarte fraiches +3245414081499 EPICERIE ,Coulis,, nappages, +3245414087965 PFT Fruits moelleux +3245414090057 PFT Pruneaux +3245414090057 PFT Pruneaux +3245414090354 PFT Pruneaux +3245414090354 PFT +3270190022527 PRODUITS FRAIS Pates à tarte fraiches +3270190022534 PRODUITS FRAIS Pates à tarte fraiches +3270190022534 PRODUITS FRAIS Pates à tarte fraiches +3270190022534 PRODUITS FRAIS Pates à tarte fraiches +3270190022534 PRODUITS FRAIS Pates à tarte fraiches +3270190022565 PRODUITS FRAIS Oeufs +3270190022565 PRODUITS FRAIS Oeufs +3270190022565 PRODUITS FRAIS Oeufs +3270190022565 PRODUITS FRAIS Oeufs +3270190022565 PRODUITS FRAIS Oeufs +3270190022565 PRODUITS FRAIS Oeufs +3270190022565 PRODUITS FRAIS Oeufs +3270190022596 PRODUITS FRAIS Pates à tarte fraiches +3270190022596 PRODUITS FRAIS Pates à tarte fraiches +3270190022596 PRODUITS FRAIS Pates à tarte fraiches +3270190022596 PRODUITS FRAIS Pates à tarte fraiches +3270190022824 PRODUITS FRAIS Beurres Sans sel +3270190022824 PRODUITS FRAIS Beurres Sans sel +3270190022831 PRODUITS FRAIS Beurres Sans sel +3270190022831 PRODUITS FRAIS Beurres Sans sel +3270190023661 PRODUITS FRAIS Lardons +3270190023661 PRODUITS FRAIS Lardons +3270190023678 PRODUITS FRAIS Lardons +3270190023678 PRODUITS FRAIS Lardons +3270190024835 PRODUITS FRAIS Panettone/brioche/prd tranche +3270190024835 PRODUITS FRAIS Panettone/brioche/prd tranche +3270190024835 PRODUITS FRAIS Panettone/brioche/prd tranche +3270190025566 PRODUITS FRAIS Beurres Sales +3270190025566 PRODUITS FRAIS Beurres Sales +3270190025566 PRODUITS FRAIS Beurres Sales +3270190025566 PRODUITS FRAIS Beurres Sales +3270190025696 PRODUITS FRAIS Fromages de chevre +3270190025696 PRODUITS FRAIS Fromages de chevre +3270190026662 PRODUITS FRAIS Mélanges de legumes/garniture surgelés +3270190026662 PRODUITS FRAIS Mélanges de legumes/garniture surgelés +3270190026730 PRODUITS FRAIS Plats cuisinés surgelés - specialites +3270190026822 PRODUITS FRAIS Yaourts sante et biologique nature +3270190026822 PRODUITS FRAIS Yaourts sante et biologique nature +3245414241718 LIQUIDES Sirops concentrés - Autres sirops +3245414259034 EPICERIE ,Gateaux roules,, fourres, +3245414260535 EPICERIE ,Gateaux roules,, fourres, +3245414260658 EPICERIE ,Gateaux roules,, fourres, +3270190028055 PRODUITS FRAIS Spécialités festives (Bûches - Bûchettes...) +3270190028055 PRODUITS FRAIS Spécialités festives (Bûches - Bûchettes...) +3245414302174 EPICERIE ,Cakes aux fruits,, fourres, +3270190031659 PRODUITS FRAIS Libre service - Autres volailles +3270190031659 PRODUITS FRAIS Libre service - Autres volailles +3270190031659 PRODUITS FRAIS Libre service - Autres volailles +3270190031659 PRODUITS FRAIS Libre service - Autres volailles +3270190112389 EPICERIE Conserves Chataîgnes +3270190112389 EPICERIE Conserves Chataîgnes +3270190117308 EPICERIE Farine blanche +3270190117308 EPICERIE Farine blanche +3270190117315 EPICERIE Farine blanche +3270190117315 EPICERIE Farine blanche +3245414459106 EPICERIE Desserts a preparer +3270190118800 EPICERIE Huiles Tournesol +3270190118800 EPICERIE Huiles Tournesol +3245414485686 EPICERIE Confiserie et chocolats paques +3270190118862 EPICERIE Huiles Tournesol +3270190118862 EPICERIE Huiles Tournesol +3270190118862 EPICERIE Huiles Tournesol +3270190118879 EPICERIE Huiles Arachide +3270190118879 EPICERIE Huiles Arachide +3270190119968 LIQUIDES Nectars d'orange +3270190119968 LIQUIDES Nectars d'orange +3270190119968 LIQUIDES Nectars d'orange +3270190121930 LIQUIDES Sirops concentrés à base de plantes +3245414637467 PRODUITS FRAIS Dessert patissier +3245414637696 PRODUITS FRAIS Dessert patissier +3245414640320 PRODUITS FRAIS Crèmes dessert +3270190121930 LIQUIDES Sirops concentrés à base de plantes +3270190121947 LIQUIDES Sirops concentrés à base de fruits +3270190121947 LIQUIDES Sirops concentrés à base de fruits +3270190122197 EPICERIE Conserves de Peches +3270190122197 EPICERIE Conserves de Peches +3270190122197 EPICERIE Conserves de Peches +3245414663565 PRODUITS FRAIS Autres saucisses +3245414667136 PRODUITS FRAIS Plats cuisinés surgelés - a base de viande +3245414667136 PRODUITS FRAIS Plats cuisinés surgelés - a base de viande +3245414667181 PRODUITS FRAIS Crêpes et galettes salées surgelées +3245414668508 PRODUITS FRAIS Chorizo +3248340033624 LIQUIDES Jus de pomme bio +3270190138778 EPICERIE Miels +3270190138778 EPICERIE Miels +3270190153917 EPICERIE Conserves de Haricots verts cueillis et rangés main +3270190153917 EPICERIE Conserves de Haricots verts cueillis et rangés main +3270190153917 EPICERIE Conserves de Haricots verts cueillis et rangés main +3270190153917 EPICERIE Conserves de Haricots verts cueillis et rangés main +3270190006824 LIQUIDES Vins doux naturels +3270190171720 EPICERIE Compotes pots / coupelles +3270190171720 EPICERIE Compotes pots / coupelles +3270190171720 EPICERIE Compotes pots / coupelles +3270190171737 EPICERIE Compotes pots / coupelles +3270190171737 EPICERIE Compotes pots / coupelles +3270190171737 EPICERIE Compotes pots / coupelles +3270190178460 EPICERIE Conserves de Tomates pelées +3270190178460 EPICERIE Conserves de Tomates pelées +3270190178460 EPICERIE Conserves de Tomates pelées +3270190008194 EPICERIE Boissons chocolatées instantanées +3270190008200 EPICERIE Boissons chocolatées instantanées +3270190178477 EPICERIE Conserves Coeur de palmier +3270190178477 EPICERIE Conserves Coeur de palmier +3270190178477 EPICERIE Conserves Coeur de palmier +3270190178514 EPICERIE Conserves Asperges +3270190178514 EPICERIE Conserves Asperges +3270190178521 EPICERIE Conserves Asperges +3270190178521 EPICERIE Conserves Asperges +3270190178545 EPICERIE Macédoine de légumes +3270190178545 EPICERIE Macédoine de légumes +3270190178927 EPICERIE Petits pains type suédois +3270190178927 EPICERIE Petits pains type suédois +3270190178927 EPICERIE Petits pains type suédois +3270190180982 EPICERIE Conserves de Tomates concassées +3270190180982 EPICERIE Conserves de Tomates concassées +3270190180982 EPICERIE Conserves de Tomates concassées +3270190181262 EPICERIE Compotes pots / coupelles +3270190181262 EPICERIE Compotes pots / coupelles +3270190184560 EPICERIE Conserves de Thon +3270190184560 EPICERIE Conserves de Thon +3270190184560 EPICERIE Conserves de Thon +3270190184577 EPICERIE Conserves de Thon +3270190184577 EPICERIE Conserves de Thon +3270190190349 PRODUITS FRAIS Patisseries industrielles - gateaux a trancher +3270190190349 PRODUITS FRAIS Patisseries industrielles - gateaux a trancher +3270190192749 EPICERIE Conserves de Tomates pelées +3270190020936 PRODUITS FRAIS Fromages blanc allegés +3270190192749 EPICERIE Conserves de Tomates pelées +3270190192749 EPICERIE Conserves de Tomates pelées +3270190192749 EPICERIE Conserves de Tomates pelées +3270190202769 PRODUITS FRAIS Plats cuisinés surgelés - specialites +3270190202769 PRODUITS FRAIS Plats cuisinés surgelés - specialites +3270190203261 PRODUITS FRAIS Spécialités festives (Bûches - Bûchettes...) +3270190203261 PRODUITS FRAIS Spécialités festives (Bûches - Bûchettes...) +3270190203414 PRODUITS FRAIS Charc.volaille et autre viande +3270190203414 PRODUITS FRAIS Charc.volaille et autre viande +3270190204008 PRODUITS FRAIS Pates à tarte fraiches +3270190204008 PRODUITS FRAIS Pates à tarte fraiches +3270190204015 PRODUITS FRAIS Pates à tarte fraiches +3270190204015 PRODUITS FRAIS Pates à tarte fraiches +3270190204152 PRODUITS FRAIS Autres legumes surgelés +3270190204152 PRODUITS FRAIS Autres legumes surgelés +3270190204367 PRODUITS FRAIS Dessert patissier +3270190204367 PRODUITS FRAIS Dessert patissier +3270190205678 PRODUITS FRAIS Oeufs +3270190021735 PFT Fruits moelleux +3270190205678 PRODUITS FRAIS Oeufs +3270190205678 PRODUITS FRAIS Oeufs +3270190021841 PFT Sachet/Barquettes Composees +3270190021841 PFT Sachet/Barquettes Composees +3270190021841 PFT Sachet/Barquettes Composees +3270190021841 PFT Sachet/Barquettes Composees +3270190021841 PFT Sachet/Barquettes Composees +3270190021841 PFT Sachet/Barquettes Composees +3270190021841 PFT Sachet/Barquettes Composees +3270190021858 PFT Sachet/Barquettes Monovarietes +3270190021858 PFT Sachet/Barquettes Monovarietes +3270190021858 PFT Sachet/Barquettes Monovarietes +3270190021858 PFT Sachet/Barquettes Monovarietes +3270190021858 PFT Sachet/Barquettes Monovarietes +3270190021865 PFT Sachet/Barquettes Monovarietes +3270190021865 PFT Sachet/Barquettes Monovarietes +3270190021865 PFT Sachet/Barquettes Monovarietes +3270190021865 PFT Sachet/Barquettes Monovarietes +3270190021865 PFT Sachet/Barquettes Monovarietes +3270190021865 PFT Sachet/Barquettes Monovarietes +3270190021865 PFT Sachet/Barquettes Monovarietes +3270190021872 PFT Sachet/Barquettes Monovarietes +3270190021872 PFT Sachet/Barquettes Monovarietes +3270190021872 PFT Sachet/Barquettes Monovarietes +3270190021872 PFT Sachet/Barquettes Monovarietes +3270190021872 PFT Sachet/Barquettes Monovarietes +3270190021872 PFT Sachet/Barquettes Monovarietes +3270190021889 PFT Sachet/Barquettes Monovarietes +3270190021889 PFT Sachet/Barquettes Monovarietes +3270190021889 PFT Sachet/Barquettes Monovarietes +3270190021889 PFT Sachet/Barquettes Monovarietes +3270190021889 PFT Sachet/Barquettes Monovarietes +3270190021889 PFT Sachet/Barquettes Monovarietes +3270190021889 PFT Sachet/Barquettes Monovarietes +3270190021889 PFT Sachet/Barquettes Monovarietes +3270190021889 PFT Sachet/Barquettes Monovarietes +3270190205678 PRODUITS FRAIS Oeufs +3270190022350 PFT Sachet/Barquettes Composees +3270190022350 PFT Sachet/Barquettes Composees +3270190022350 PFT Sachet/Barquettes Composees +3270190022350 PFT Sachet/Barquettes Composees +3270190022367 PFT Sachet/Barquettes Composees +3270190022367 PFT Sachet/Barquettes Composees +3270190022367 PFT Sachet/Barquettes Composees +3270190022367 PFT Sachet/Barquettes Composees +3270190022367 PFT Sachet/Barquettes Composees +3270190205678 PRODUITS FRAIS Oeufs +3270190205678 PRODUITS FRAIS Oeufs +3270190205678 PRODUITS FRAIS Oeufs +3270190205685 PRODUITS FRAIS Oeufs +3270190205685 PRODUITS FRAIS Oeufs +3270190205685 PRODUITS FRAIS Oeufs +3270190205685 PRODUITS FRAIS Oeufs +3270190205685 PRODUITS FRAIS Oeufs +3270190205685 PRODUITS FRAIS Oeufs +3270190205685 PRODUITS FRAIS Oeufs +3270190207450 PRODUITS FRAIS Beurres Sans sel +3270190207450 PRODUITS FRAIS Beurres Sans sel +3270190207467 PRODUITS FRAIS Beurres Sales +3270190207467 PRODUITS FRAIS Beurres Sales +3270190207498 PRODUITS FRAIS Salades +3270190207498 PRODUITS FRAIS Salades +3270190207689 PRODUITS FRAIS Emmentals rapes +3270190207689 PRODUITS FRAIS Emmentals rapes +3270190207689 PRODUITS FRAIS Emmentals rapes +3270190022671 PFT Fruits moelleux +3270190207696 PRODUITS FRAIS Emmentals rapes +3270190207696 PRODUITS FRAIS Emmentals rapes +3270190207696 PRODUITS FRAIS Emmentals rapes +3270190207696 PRODUITS FRAIS Emmentals rapes +3270190207696 PRODUITS FRAIS Emmentals rapes +3270190207696 PRODUITS FRAIS Emmentals rapes +3270190207696 PRODUITS FRAIS Emmentals rapes +3270190207696 PRODUITS FRAIS Emmentals rapes +3270190207696 PRODUITS FRAIS Emmentals rapes +3270190207702 PRODUITS FRAIS Raclette +3270190207702 PRODUITS FRAIS Raclette +3270190207702 PRODUITS FRAIS Raclette +3270190023487 PFT Sachet/Barquettes Composees +3270190023487 PFT Sachet/Barquettes Composees +3270190023487 PFT Sachet/Barquettes Composees +3270190023487 PFT Sachet/Barquettes Composees +3270190023487 PFT Sachet/Barquettes Composees +3270190207917 PRODUITS FRAIS Pains de mie élaboré +3270190207917 PRODUITS FRAIS Pains de mie élaboré +3270190208211 PRODUITS FRAIS Libre service - Produits carnes prepares +3270190208211 PRODUITS FRAIS Libre service - Produits carnes prepares +3270190208228 PRODUITS FRAIS Libre service - Produits carnes prepares +3270190208228 PRODUITS FRAIS Libre service - Produits carnes prepares +3270190208303 PRODUITS FRAIS Légumes cuisines/ Purées / Gratins +3270190208303 PRODUITS FRAIS Légumes cuisines/ Purées / Gratins +3270190025290 PRODUITS FRAIS Saumon fumés +3270190025337 PRODUITS FRAIS Laits longue conservation natu +3270190025337 PRODUITS FRAIS Laits longue conservation natu +3270190025337 PRODUITS FRAIS Laits longue conservation natu +3270190025337 PRODUITS FRAIS Laits longue conservation natu +3270190025337 PRODUITS FRAIS Laits longue conservation natu +3270190025337 PRODUITS FRAIS Laits longue conservation natu +3270190025337 PRODUITS FRAIS Laits longue conservation natu +3270190025504 PRODUITS FRAIS Crèmes fraiches epaisses +3270190025795 PRODUITS FRAIS Beurres Sans sel +3270190025795 PRODUITS FRAIS Beurres Sans sel +3270190025801 PRODUITS FRAIS Beurres Sales +3270190025801 PRODUITS FRAIS Beurres Sales +3270190026631 PFT Fruits secs a coque +3270190026655 PFT Fruits moelleux +3270190026730 PRODUITS FRAIS Plats cuisinés surgelés - specialites +3270190218869 PRODUITS FRAIS Emmentals blocs +3270190218869 PRODUITS FRAIS Emmentals blocs +3270190218869 PRODUITS FRAIS Emmentals blocs +3270190696650 EPICERIE Minerale +3270190696650 EPICERIE Minerale +3270190874539 PRODUITS FRAIS Libre service - Poulets +3270190874539 PRODUITS FRAIS Libre service - Poulets +3270190874539 PRODUITS FRAIS Libre service - Poulets +3270190874546 PRODUITS FRAIS Libre service - Poulets +3270190874546 PRODUITS FRAIS Libre service - Poulets +3270190874546 PRODUITS FRAIS Libre service - Poulets +3270190874546 PRODUITS FRAIS Libre service - Poulets +3270190874546 PRODUITS FRAIS Libre service - Poulets +3270190874553 PRODUITS FRAIS Libre service - Poulets +3270190874553 PRODUITS FRAIS Libre service - Poulets +3270190874553 PRODUITS FRAIS Libre service - Poulets +3270190874553 PRODUITS FRAIS Libre service - Poulets +3270190874560 PRODUITS FRAIS Libre service - Poulets +3270190874560 PRODUITS FRAIS Libre service - Poulets +3270190874560 PRODUITS FRAIS Libre service - Poulets +3270190874560 PRODUITS FRAIS Libre service - Poulets +3270190874560 PRODUITS FRAIS Libre service - Poulets +3270190874560 PRODUITS FRAIS Libre service - Poulets +3270190874577 PRODUITS FRAIS Libre service - Poulets +3270190874577 PRODUITS FRAIS Libre service - Poulets +3270190874577 PRODUITS FRAIS Libre service - Poulets +3270190874577 PRODUITS FRAIS Libre service - Poulets +3270190874584 PRODUITS FRAIS Libre service - Poulets +3270190874584 PRODUITS FRAIS Libre service - Poulets +3270190874584 PRODUITS FRAIS Libre service - Poulets +3270190874584 PRODUITS FRAIS Libre service - Poulets +3270190874584 PRODUITS FRAIS Libre service - Poulets +3270190874584 PRODUITS FRAIS Libre service - Poulets +3390500127589 EPICERIE Agglomerante +3390500127589 EPICERIE Agglomerante +3560070015009 PRODUITS FRAIS Préparation pommes de terres +3560070015009 PRODUITS FRAIS Préparation pommes de terres +3560070046775 PRODUITS FRAIS Roquefort +3560070046775 PRODUITS FRAIS Roquefort +3560070046867 PRODUITS FRAIS Frites surgelées +3560070046867 PRODUITS FRAIS Frites surgelées +3270190127765 EPICERIE Chocolat tablette - noirs +3270190128151 EPICERIE Chocolat tablette - au lait +3270190128717 EPICERIE Produits diététiques A base de soja +3270190128724 EPICERIE Farine blanche +3270190129509 EPICERIE Biscuits sucrés Fourres +3270190129615 EPICERIE Huiles de spécialité +3270190129622 EPICERIE Huiles de spécialité +3270190129639 EPICERIE Huiles de spécialité +3560070057597 PRODUITS FRAIS Frites surgelées +3560070057597 PRODUITS FRAIS Frites surgelées +3560070057658 PRODUITS FRAIS Frites surgelées +3560070057658 PRODUITS FRAIS Frites surgelées +3560070060252 PRODUITS FRAIS Fromages frais - Spécialité italienne +3270190131328 LIQUIDES Rhums ambres +3560070060252 PRODUITS FRAIS Fromages frais - Spécialité italienne +3560070060252 PRODUITS FRAIS Fromages frais - Spécialité italienne +3560070060832 PRODUITS FRAIS Fromages frais - Spécialité italienne +3560070060832 PRODUITS FRAIS Fromages frais - Spécialité italienne +3560070060832 PRODUITS FRAIS Fromages frais - Spécialité italienne +3270190141303 EPICERIE Confiserie et chocolats noel +3270190141419 EPICERIE Confiserie et chocolats noel +3270190143611 LIQUIDES Vins doux naturels +3270190146421 EPICERIE Autres farines +3270190150633 LIQUIDES Autres fruits gazéifiées +3270190151654 EPICERIE Chocolat tablette - noirs +3270190174936 EPICERIE Chocolat tablette - au lait +3270190174936 EPICERIE Chocolat tablette - au lait +3560070122165 PRODUITS FRAIS Légumes verts surgelés +3560070122165 PRODUITS FRAIS Légumes verts surgelés +3560070122165 PRODUITS FRAIS Légumes verts surgelés +3560070122257 PRODUITS FRAIS Légumes verts surgelés +3560070122257 PRODUITS FRAIS Légumes verts surgelés +3560070122257 PRODUITS FRAIS Légumes verts surgelés +3560070122349 PRODUITS FRAIS Autres legumes surgelés +3560070122349 PRODUITS FRAIS Autres legumes surgelés +3270190178460 EPICERIE Conserves de Tomates pelées +3560070122349 PRODUITS FRAIS Autres legumes surgelés +3560070122349 PRODUITS FRAIS Autres legumes surgelés +3270190179177 EPICERIE Autre pdt confiserie de sucre +3270190179214 EPICERIE Confiserie et chocolats noel +3270190182566 EPICERIE Confiserie et chocolats paques +3270190182603 EPICERIE Confiserie et chocolats paques +3270190182603 EPICERIE Confiserie et chocolats paques +3560070139941 PRODUITS FRAIS Légumes verts surgelés +3560070139941 PRODUITS FRAIS Légumes verts surgelés +3560070140121 PRODUITS FRAIS Autres legumes surgelés +3560070140121 PRODUITS FRAIS Autres legumes surgelés +3560070140305 PRODUITS FRAIS Légumes verts surgelés +3560070140305 PRODUITS FRAIS Légumes verts surgelés +3560070143368 PRODUITS FRAIS Préparation pommes de terres +3560070143368 PRODUITS FRAIS Préparation pommes de terres +3560070143368 PRODUITS FRAIS Préparation pommes de terres +3270190191216 EPICERIE Confiserie et chocolats paques +3270190191285 EPICERIE Confiserie et chocolats paques +3270190191285 EPICERIE Confiserie et chocolats paques +3270190191292 EPICERIE Confiserie et chocolats paques +3270190191377 EPICERIE Petits pains type suédois +3560070150908 EPICERIE Conserves d'Ananas +3560070150908 EPICERIE Conserves d'Ananas +3560070150908 EPICERIE Conserves d'Ananas +3560070167470 LIQUIDES Purs Jus de Fruits - Orange +3560070167470 LIQUIDES Purs Jus de Fruits - Orange +3270190205524 PRODUITS FRAIS Libre service - Autres volailles +3270190205524 PRODUITS FRAIS Libre service - Autres volailles +3270190205524 PRODUITS FRAIS Libre service - Autres volailles +3270190205524 PRODUITS FRAIS Libre service - Autres volailles +3270190205531 PRODUITS FRAIS Libre service - Autres volailles +3270190205531 PRODUITS FRAIS Libre service - Autres volailles +3270190205531 PRODUITS FRAIS Libre service - Autres volailles +3270190205531 PRODUITS FRAIS Libre service - Autres volailles +3560070181872 EPICERIE Conserves de Haricots blancs +3560070181872 EPICERIE Conserves de Haricots blancs +3560070181902 EPICERIE Conserves de Haricots blancs sauce tomate +3560070181902 EPICERIE Conserves de Haricots blancs sauce tomate +3560070185672 EPICERIE Conserves Autres fruits +3270190207337 PRODUITS FRAIS Légumes verts surgelés +3270190207337 PRODUITS FRAIS Légumes verts surgelés +3270190207344 PRODUITS FRAIS Légumes verts surgelés +3270190207351 PRODUITS FRAIS Légumes verts surgelés +3270190207351 PRODUITS FRAIS Légumes verts surgelés +3270190207351 PRODUITS FRAIS Légumes verts surgelés +3270190207351 PRODUITS FRAIS Légumes verts surgelés +3270190207368 PRODUITS FRAIS Légumes verts surgelés +3270190207368 PRODUITS FRAIS Légumes verts surgelés +3560070185672 EPICERIE Conserves Autres fruits +3560070185672 EPICERIE Conserves Autres fruits +3560070197743 EPICERIE Conserves Artichauts +3560070197743 EPICERIE Conserves Artichauts +3560070197774 EPICERIE Conserves Artichauts +3560070197774 EPICERIE Conserves Artichauts +3560070198504 EPICERIE Conserves Asperges +3560070198504 EPICERIE Conserves Asperges +3560070203864 EPICERIE Conserves Asperges +3560070203864 EPICERIE Conserves Asperges +3560070203864 EPICERIE Conserves Asperges +3560070210503 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560070210503 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560070210503 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560070210534 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560070210534 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560070210596 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560070210596 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560070210596 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560070210626 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560070210626 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560070210626 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560070212743 EPICERIE Conserves de Petits pois carottes +3560070212743 EPICERIE Conserves de Petits pois carottes +3560070212743 EPICERIE Conserves de Petits pois carottes +3270190209355 PFT Sachet/Barquettes Monovarietes +3270190209355 PFT Sachet/Barquettes Monovarietes +3270190209355 PFT Sachet/Barquettes Monovarietes +3270190209355 PFT Sachet/Barquettes Monovarietes +3270190209355 PFT Sachet/Barquettes Monovarietes +3270190209362 PFT Salade Sachet/Barquettes Autre +3270190209362 PFT Salade Sachet/Barquettes Autre +3270190209362 PFT Salade Sachet/Barquettes Autre +3270190209362 PFT Salade Sachet/Barquettes Autre +3270190209362 PFT Salade Sachet/Barquettes Autre +3270190209362 PFT Salade Sachet/Barquettes Autre +3560070215898 EPICERIE Conserves de Tomates concassées +3560070215898 EPICERIE Conserves de Tomates concassées +3560070216864 EPICERIE Conserves de Thon +3560070216864 EPICERIE Conserves de Thon +3560070216864 EPICERIE Conserves de Thon +3560070220731 EPICERIE Miels +3560070220731 EPICERIE Miels +3560070224999 PRODUITS FRAIS Poissons surgelés entiers +3560070224999 PRODUITS FRAIS Poissons surgelés entiers +3560070224999 PRODUITS FRAIS Poissons surgelés entiers +3560070224999 PRODUITS FRAIS Poissons surgelés entiers +3270190209904 PRODUITS FRAIS Roquefort +3560070227280 PRODUITS FRAIS Autres Poissons surgelés +3560070227280 PRODUITS FRAIS Autres Poissons surgelés +3560070227280 PRODUITS FRAIS Autres Poissons surgelés +3560070227280 PRODUITS FRAIS Autres Poissons surgelés +3560070234271 EPICERIE Conserves Artichauts +3560070234271 EPICERIE Conserves Artichauts +3560070257096 PRODUITS FRAIS Fromages frais aromatises +3560070257096 PRODUITS FRAIS Fromages frais aromatises +3560070262281 EPICERIE Conserves de Sardines +3560070262281 EPICERIE Conserves de Sardines +3560070272570 EPICERIE Conserves Artichauts +3560070272570 EPICERIE Conserves Artichauts +3560070273454 EPICERIE Conserves de Haricots blancs +3560070273454 EPICERIE Conserves de Haricots blancs +3560070273546 EPICERIE Conserves de Pois chiches +3493373037013 EPICERIE Conserves de Petits pois carottes +3493373037020 EPICERIE Conserves de Haricots verts +3493375072036 EPICERIE Conserves de Petits pois +3560070273546 EPICERIE Conserves de Pois chiches +3560070274055 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560070274055 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560070274055 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560070274055 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560070274055 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560070274055 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560070274116 PRODUITS FRAIS Noix st jacques/petoncle/coquilles surgelés +3560070274116 PRODUITS FRAIS Noix st jacques/petoncle/coquilles surgelés +3560070274116 PRODUITS FRAIS Noix st jacques/petoncle/coquilles surgelés +3560070274116 PRODUITS FRAIS Noix st jacques/petoncle/coquilles surgelés +3560070274116 PRODUITS FRAIS Noix st jacques/petoncle/coquilles surgelés +3560070274178 PRODUITS FRAIS Autres fruits de mer/preparés surgelés +3560070274178 PRODUITS FRAIS Autres fruits de mer/preparés surgelés +3560070274178 PRODUITS FRAIS Autres fruits de mer/preparés surgelés +3560070274178 PRODUITS FRAIS Autres fruits de mer/preparés surgelés +3560070274178 PRODUITS FRAIS Autres fruits de mer/preparés surgelés +3560070274178 PRODUITS FRAIS Autres fruits de mer/preparés surgelés +3560070274178 PRODUITS FRAIS Autres fruits de mer/preparés surgelés +3560070274178 PRODUITS FRAIS Autres fruits de mer/preparés surgelés +3560070274444 PRODUITS FRAIS Cocktail/garniture/salad f mer surgelés +3560070274444 PRODUITS FRAIS Cocktail/garniture/salad f mer surgelés +3560070274444 PRODUITS FRAIS Cocktail/garniture/salad f mer surgelés +3560070274444 PRODUITS FRAIS Cocktail/garniture/salad f mer surgelés +3560070274444 PRODUITS FRAIS Cocktail/garniture/salad f mer surgelés +3560070274444 PRODUITS FRAIS Cocktail/garniture/salad f mer surgelés +3560070274444 PRODUITS FRAIS Cocktail/garniture/salad f mer surgelés +3560070274444 PRODUITS FRAIS Cocktail/garniture/salad f mer surgelés +3560070274444 PRODUITS FRAIS Cocktail/garniture/salad f mer surgelés +3560070274444 PRODUITS FRAIS Cocktail/garniture/salad f mer surgelés +3560070274444 PRODUITS FRAIS Cocktail/garniture/salad f mer surgelés +3560070274444 PRODUITS FRAIS Cocktail/garniture/salad f mer surgelés +3560070274444 PRODUITS FRAIS Cocktail/garniture/salad f mer surgelés +3560070274444 PRODUITS FRAIS Cocktail/garniture/salad f mer surgelés +3560070275762 PRODUITS FRAIS ,Langoustes,, homards,, crabes surgelés, +3560070275762 PRODUITS FRAIS ,Langoustes,, homards,, crabes surgelés, +3560070275793 PRODUITS FRAIS ,Langoustes,, homards,, crabes surgelés, +3560070275793 PRODUITS FRAIS ,Langoustes,, homards,, crabes surgelés, +3560070275793 PRODUITS FRAIS ,Langoustes,, homards,, crabes surgelés, +3560070275793 PRODUITS FRAIS ,Langoustes,, homards,, crabes surgelés, +3560070277650 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560070277650 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560070277650 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560070048908 EPICERIE Biscuits sucrés Fourres +3560070048939 EPICERIE Biscuits sucrés Fourres +3560070280520 EPICERIE Conserves de Tomates - Concentré +3560070280520 EPICERIE Conserves de Tomates - Concentré +3560070280551 EPICERIE Conserves de Tomates - Concentré +3560070280551 EPICERIE Conserves de Tomates - Concentré +3560070095162 LIQUIDES Bières Blondes +3560070095209 LIQUIDES Bières Blondes +3560070099610 EPICERIE Olives vertes +3560070099641 EPICERIE Olives noires +3560070300051 PRODUITS FRAIS Noix st jacques/petoncle/coquilles surgelés +3560070300051 PRODUITS FRAIS Noix st jacques/petoncle/coquilles surgelés +3560070300051 PRODUITS FRAIS Noix st jacques/petoncle/coquilles surgelés +3560070300051 PRODUITS FRAIS Noix st jacques/petoncle/coquilles surgelés +3560070300679 PRODUITS FRAIS Calamar/encornet/poulpe/seches surgelés +3560070300679 PRODUITS FRAIS Calamar/encornet/poulpe/seches surgelés +3560070300679 PRODUITS FRAIS Calamar/encornet/poulpe/seches surgelés +3560070302109 EPICERIE Macédoine de légumes +3560070302109 EPICERIE Macédoine de légumes +3560070302253 EPICERIE Conserves de Petits pois +3560070302253 EPICERIE Conserves de Petits pois +3560070302253 EPICERIE Conserves de Petits pois +3560070302284 EPICERIE Conserves de Flageolets +3560070302284 EPICERIE Conserves de Flageolets +3560070308545 PRODUITS FRAIS Légumes verts surgelés +3560070308545 PRODUITS FRAIS Légumes verts surgelés +3560070308576 PRODUITS FRAIS Légumes verts surgelés +3560070308576 PRODUITS FRAIS Autres légumes surgelés et soupes - Soupes +3560070310043 EPICERIE Conserves de Petits pois carottes +3560070310043 EPICERIE Conserves de Petits pois carottes +3560070310043 EPICERIE Conserves de Petits pois carottes +3560070310043 EPICERIE Conserves de Petits pois carottes +3560070118373 LIQUIDES Vodkas +3560070118489 LIQUIDES Vodkas +3560070118489 LIQUIDES Vodkas +3560070118571 LIQUIDES Gins +3560070320288 EPICERIE Conserves de Petits pois +3560070320288 EPICERIE Conserves de Petits pois +3560070320288 EPICERIE Conserves de Petits pois +3560070322787 EPICERIE Conserves de Petits pois carottes +3560070322787 EPICERIE Conserves de Petits pois carottes +3560070322787 EPICERIE Conserves de Petits pois carottes +3560070322787 EPICERIE Conserves de Petits pois carottes +3560070322817 EPICERIE Conserves de Petits pois carottes +3560070322817 EPICERIE Conserves de Petits pois carottes +3560070322817 EPICERIE Conserves de Petits pois carottes +3560070322817 EPICERIE Conserves de Petits pois carottes +3560070322817 EPICERIE Conserves de Petits pois carottes +3560070323036 EPICERIE Conserves de Haricots verts +3560070323036 EPICERIE Conserves de Haricots verts +3560070323036 EPICERIE Conserves de Haricots verts +3560070323036 EPICERIE Conserves de Haricots verts +3560070323036 EPICERIE Conserves de Haricots verts +3560070323036 EPICERIE Conserves de Haricots verts +3560070323067 EPICERIE Conserves de Haricots verts +3560070323067 EPICERIE Conserves de Haricots verts +3560070323067 EPICERIE Conserves de Haricots verts +3560070323067 EPICERIE Conserves de Haricots verts +3560070323067 EPICERIE Conserves de Haricots verts +3560070323067 EPICERIE Conserves de Haricots verts +3560070323098 EPICERIE Conserves de Haricots verts +3560070323098 EPICERIE Conserves de Haricots verts +3560070323289 EPICERIE Sauces chaudes à base de tomate et tomate frito +3560070323289 EPICERIE Sauces chaudes à base de tomate et tomate frito +3560070323289 EPICERIE Sauces chaudes à base de tomate et tomate frito +3560070326396 EPICERIE Conserves de Flageolets +3560070326396 EPICERIE Conserves de Flageolets +3560070326396 EPICERIE Conserves de Flageolets +3560070326396 EPICERIE Conserves de Flageolets +3560070326396 EPICERIE Conserves de Flageolets +3560070326396 EPICERIE Conserves de Flageolets +3560070326396 EPICERIE Conserves de Flageolets +3560070326976 PRODUITS FRAIS Autres fruits de mer/preparés surgelés +3560070326976 PRODUITS FRAIS Autres fruits de mer/preparés surgelés +3560070135127 EPICERIE Cafés solubles +3560070326976 PRODUITS FRAIS Autres fruits de mer/preparés surgelés +3560070326976 PRODUITS FRAIS Autres fruits de mer/preparés surgelés +3560070326976 PRODUITS FRAIS Autres fruits de mer/preparés surgelés +3560070327638 PRODUITS FRAIS Poissons surgelés natures filets +3560070327638 PRODUITS FRAIS Poissons surgelés natures filets +3560070327638 PRODUITS FRAIS Poissons surgelés natures filets +3560070327638 PRODUITS FRAIS Poissons surgelés natures filets +3560070327638 PRODUITS FRAIS Poissons surgelés natures filets +3560070329441 EPICERIE Conserves de Lentilles +3560070329441 EPICERIE Conserves de Lentilles +3560070330201 EPICERIE Conserves de Flageolets +3560070330201 EPICERIE Conserves de Flageolets +3560070330201 EPICERIE Conserves de Flageolets +3560070330201 EPICERIE Conserves de Flageolets +3560070330201 EPICERIE Conserves de Flageolets +3560070330201 EPICERIE Conserves de Flageolets +3560070330201 EPICERIE Conserves de Flageolets +3560070330201 EPICERIE Conserves de Flageolets +3560070149506 LIQUIDES Vodkas +3560070338641 LIQUIDES Purs Jus de Fruits - Orange +3560070338641 LIQUIDES Purs Jus de Fruits - Orange +3560070341627 LIQUIDES Autres boissons non-gazeifiees Aux fruits +3560070341627 LIQUIDES Autres boissons non-gazeifiees Aux fruits +3560070350889 EPICERIE Conserves Chataîgnes +3560070153916 EPICERIE Pâtes alimentaires sèches +3560070153947 EPICERIE Pâtes alimentaires sèches +3560070153978 EPICERIE Pâtes alimentaires sèches +3560070154005 EPICERIE Pâtes alimentaires sèches +3560070154715 EPICERIE Pâtes alimentaires sèches +3560070355877 PRODUITS FRAIS Gateaux glacés à partager +3560070355877 PRODUITS FRAIS Gateaux glacés à partager +3560070357307 PRODUITS FRAIS Poissons surgelés nature tranche/morceau +3560070357307 PRODUITS FRAIS Poissons surgelés nature tranche/morceau +3560070357307 PRODUITS FRAIS Poissons surgelés nature tranche/morceau +3560070357307 PRODUITS FRAIS Poissons surgelés nature tranche/morceau +3560070358151 EPICERIE Pâtés +3560070358151 EPICERIE Pâtés +3560070360963 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560070360963 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560070360963 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560070360963 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560070360963 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560070360994 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560070360994 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560070360994 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560070360994 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560070360994 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560070374571 PRODUITS FRAIS ,Langoustes,, homards,, crabes surgelés, +3560070374571 PRODUITS FRAIS ,Langoustes,, homards,, crabes surgelés, +3560070374571 PRODUITS FRAIS ,Langoustes,, homards,, crabes surgelés, +3560070374571 PRODUITS FRAIS ,Langoustes,, homards,, crabes surgelés, +3560070177110 PRODUITS FRAIS Autres cremes +3560070387687 EPICERIE Croquettes sec +3560070387687 EPICERIE Croquettes sec +3560070393763 PRODUITS FRAIS Crevettes +3560070393763 PRODUITS FRAIS Crevettes +3560070393824 PRODUITS FRAIS Crevettes +3560070393824 PRODUITS FRAIS Crevettes +3560070186020 EPICERIE Pâtes alimentaires sèches +3560070186051 EPICERIE Pâtes alimentaires sèches Spécialités +3560070408184 EPICERIE Conserves Artichauts +3560070193219 LIQUIDES Bières Spécialité +3560070408184 EPICERIE Conserves Artichauts +3560070415755 EPICERIE Thés parfumés +3560070415755 EPICERIE Thés parfumés +3560070416608 PRODUITS FRAIS Libre service - Autres volailles +3560070416608 PRODUITS FRAIS Libre service - Autres volailles +3560070206476 EPICERIE Conserves Artichauts +3560070206506 EPICERIE Conserves Artichauts +3560070428823 EPICERIE Chocolat tablette - fourres +3560070428823 EPICERIE Chocolat tablette - fourres +3560070428854 EPICERIE Chocolat tablette - fourres +3560070428854 EPICERIE Chocolat tablette - fourres +3560070429899 LIQUIDES Eaux gazeuses Bouteilles plastique +3560070429899 LIQUIDES Eaux gazeuses Bouteilles plastique +3560070429905 LIQUIDES Eaux gazeuses Bouteilles plastique +3560070429905 LIQUIDES Eaux gazeuses Bouteilles plastique +3560070438686 EPICERIE Conserves Artichauts +3560070438686 EPICERIE Conserves Artichauts +3560070225859 LIQUIDES Vodkas +3560070229840 EPICERIE Conserves Coeur de palmier +3560070229871 EPICERIE Conserves Coeur de palmier +3560070229901 EPICERIE Conserves Coeur de palmier +3560070479467 EPICERIE Conserves de Tomates pelées +3560070234219 PRODUITS FRAIS Crèmes longue conservation +3560070479467 EPICERIE Conserves de Tomates pelées +3560070479900 LIQUIDES Jus de légumes +3560070479900 LIQUIDES Jus de légumes +3560070240821 EPICERIE Conserves Asperges +3560070240883 EPICERIE Conserves Asperges +3560070249343 EPICERIE ,Chocolat tablette - amande,,noisette,,riz, +3560070253371 PRODUITS FRAIS Autres legumes surgelés +3560070253371 PRODUITS FRAIS Autres legumes surgelés +3560070254873 EPICERIE Miels +3560070254903 EPICERIE Miels +3560070258512 LIQUIDES Whiskies écossais blend +3560070258512 LIQUIDES Whiskies écossais blend +3560070260584 PRODUITS FRAIS Champignons surgelés +3560070260584 PRODUITS FRAIS Champignons surgelés +3560070260645 EPICERIE Pochon humide chat +3560070260690 EPICERIE Barquette humide chien +3560070498239 PRODUITS FRAIS Libre service - Autres volailles +3560070498239 PRODUITS FRAIS Libre service - Autres volailles +3560070498239 PRODUITS FRAIS Libre service - Autres volailles +3560070498239 PRODUITS FRAIS Libre service - Autres volailles +3560070498260 PRODUITS FRAIS Libre service - Autres volailles +3560070498260 PRODUITS FRAIS Libre service - Autres volailles +3560070498291 PRODUITS FRAIS Libre service - Autres volailles +3560070498291 PRODUITS FRAIS Libre service - Autres volailles +3560070265459 LIQUIDES Autres boissons non-gazeifiees Aux fruits +3560070501236 PRODUITS FRAIS Autres produits traiteur frais +3560070501236 PRODUITS FRAIS Autres produits traiteur frais +3560070504701 EPICERIE Confiserie de chocolat +3560070504701 EPICERIE Confiserie de chocolat +3560070539208 EPICERIE Conserves de Petits pois carottes +3560070539208 EPICERIE Conserves de Petits pois carottes +3560070540631 EPICERIE Conserves de Haricots verts cueillis et rangés main +3560070540631 EPICERIE Conserves de Haricots verts cueillis et rangés main +3560070540631 EPICERIE Conserves de Haricots verts cueillis et rangés main +3560070540631 EPICERIE Conserves de Haricots verts cueillis et rangés main +3560070555581 PRODUITS FRAIS Pates à tarte fraiches +3560070555581 PRODUITS FRAIS Pates à tarte fraiches +3560070555611 PRODUITS FRAIS Pates à tarte fraiches +3560070555611 PRODUITS FRAIS Pates à tarte fraiches +3560070556434 PRODUITS FRAIS Patisseries industrielles - gateaux a trancher +3560070556434 PRODUITS FRAIS Patisseries industrielles - gateaux a trancher +3560070279012 EPICERIE Conserves Artichauts +3560070562374 EPICERIE Conserves de Petits pois +3560070280551 EPICERIE Conserves de Tomates - Concentré +3560070562374 EPICERIE Conserves de Petits pois +3560070562374 EPICERIE Conserves de Petits pois +3560070569090 PRODUITS FRAIS Libre service - Produits carnes prepares +3560070569090 PRODUITS FRAIS Libre service - Produits carnes prepares +3560070569120 PRODUITS FRAIS Libre service - Produits carnes prepares +3560070569120 PRODUITS FRAIS Libre service - Poulets +3560070569120 PRODUITS FRAIS Libre service - Poulets +3560070569151 PRODUITS FRAIS Libre service - Produits carnes prepares +3560070569151 PRODUITS FRAIS Libre service - Produits carnes prepares +3560070569151 PRODUITS FRAIS Libre service - Produits carnes prepares +3560070287628 LIQUIDES Whiskies écossais blend +3560070287895 LIQUIDES Bières Spécialité +3560070290819 EPICERIE Biscuits sucrés Aux fruits +3560070290840 EPICERIE Biscuits sucrés Aux fruits +3560070291014 LIQUIDES Cidres +3560070291021 LIQUIDES Cidres +3560070583379 LIQUIDES Purs Jus de Fruits - Autres +3560070583379 LIQUIDES Purs Jus de Fruits - Autres +3560070302536 LIQUIDES Liqueurs de vodka aromatisées +3560070302567 LIQUIDES Liqueurs de vodka aromatisées +3560070590551 PRODUITS FRAIS Beurres Sans sel +3560070590551 PRODUITS FRAIS Beurres Sans sel +3560070309207 LIQUIDES Nectars de Poire +3560070309207 LIQUIDES Nectars de Poire +3560070309269 LIQUIDES Nectars - Autres fruits +3560070309269 LIQUIDES Nectars Multifruits +3560070309351 LIQUIDES Nectars - Autres fruits +3560070309351 LIQUIDES Nectars - Autres fruits +3560070309917 EPICERIE Thés parfumés +3560070603794 PRODUITS FRAIS Foie gras +3560070316243 EPICERIE Biscuits sucrés Au chocolat +3560070603794 PRODUITS FRAIS Foie gras +3560070604319 EPICERIE Conserves Coeur de palmier +3560070604319 EPICERIE Conserves Coeur de palmier +3560070606931 PRODUITS FRAIS Pains hamburgers et hot-dogs +3560070606931 PRODUITS FRAIS Pains hamburgers et hot-dogs +3560070609529 PRODUITS FRAIS Entrées +3560070609529 PRODUITS FRAIS Entrées +3560070319497 PRODUITS FRAIS Légumes verts surgelés +3560070613564 PRODUITS FRAIS Crèmes longue conservation +3560070613564 PRODUITS FRAIS Crèmes longue conservation +3560070613564 PRODUITS FRAIS Crèmes longue conservation +3560070655298 PRODUITS FRAIS Poissons surgelés et preparations panee +3560070655298 PRODUITS FRAIS Poissons surgelés et preparations panee +3560070655298 PRODUITS FRAIS Poissons surgelés et preparations panee +3560070655298 PRODUITS FRAIS Poissons surgelés et preparations panee +3560070323470 PRODUITS FRAIS Crèmes fraiches epaisses +3560070658053 EPICERIE Conserves de Haricots verts +3560070658053 EPICERIE Conserves de Haricots verts +3560070658053 EPICERIE Conserves de Haricots verts +3560070683529 EPICERIE Conserves Artichauts +3560070683529 EPICERIE Conserves Artichauts +3560070330515 EPICERIE Chicorées - cafés +3560070330836 EPICERIE Autres céréales +3560070330867 EPICERIE Autres céréales +3560070330959 EPICERIE Cafés solubles +3560070330980 EPICERIE Cafés solubles +3560070332670 LIQUIDES Purs Jus de Fruits - Orange +3560070332670 LIQUIDES Purs Jus de Fruits - Orange +3560070332670 LIQUIDES Purs Jus de Fruits - Orange +3560070332670 LIQUIDES Purs Jus de Fruits - Orange +3560070332847 LIQUIDES Jus de pomme à base de concentré +3560070332847 LIQUIDES Jus de pomme à base de concentré +3560070333066 LIQUIDES Jus multifruits à base de concentré +3560070333066 LIQUIDES Jus multifruits à base de concentré +3560070333127 LIQUIDES Jus d'orange à base de concentré +3560070333127 LIQUIDES Jus d'orange à base de concentré +3560070334940 EPICERIE Conserves de Haricots verts +3560070334940 EPICERIE Conserves de Haricots verts +3560070335060 EPICERIE Conserves de Tomates pelées +3560070335060 EPICERIE Conserves de Tomates pelées +3560070335060 EPICERIE Conserves de Tomates pelées +3560070335060 EPICERIE Conserves de Tomates pelées +3560070335060 EPICERIE Conserves de Tomates pelées +3560070335121 EPICERIE Conserves de Tomates - Concentré +3560070335121 EPICERIE Conserves de Tomates - Concentré +3560070336548 PRODUITS FRAIS Glaces Batonnets +3560070336548 PRODUITS FRAIS Glaces Batonnets +3560070336548 PRODUITS FRAIS Glaces Batonnets +3560070336548 PRODUITS FRAIS Glaces Batonnets +3560070336630 PRODUITS FRAIS Glaces Batonnets +3560070336630 PRODUITS FRAIS Glaces Batonnets +3560070339204 LIQUIDES Sirops concentrés à base de fruits +3560070339228 LIQUIDES Sirops concentrés à base de plantes +3560070339433 EPICERIE Autre pdt confiserie de sucre +3560070339433 EPICERIE Autre pdt confiserie de sucre +3560070339464 EPICERIE Bonbons durs aux plantes +3560070340224 EPICERIE Moutardes +3560070340316 EPICERIE Huiles Tournesol +3560070340316 EPICERIE Huiles Tournesol +3560070340316 EPICERIE Huiles Tournesol +3560070342167 EPICERIE Biscuits sucrés Secs +3560070342167 EPICERIE Biscuits sucrés Secs +3560070342464 EPICERIE Biscuits sucrés Fourres +3560070342464 EPICERIE Biscuits sucrés Fourres +3560070342495 EPICERIE Biscuits sucrés Fourres +3560070343393 PRODUITS FRAIS Panettone/brioche/prd tranche +3560070343607 PRODUITS FRAIS Libre service - Poulets +3560070343607 PRODUITS FRAIS Libre service - Poulets +3560070343607 PRODUITS FRAIS Libre service - Poulets +3560070343607 PRODUITS FRAIS Libre service - Poulets +3560070343607 PRODUITS FRAIS Libre service - Poulets +3560070343607 PRODUITS FRAIS Libre service - Poulets +3560070343607 PRODUITS FRAIS Libre service - Poulets +3560070343607 PRODUITS FRAIS Libre service - Poulets +3560070344628 EPICERIE Conserves Artichauts +3560070344970 PRODUITS FRAIS Pains hamburgers et hot-dogs +3560070345250 PRODUITS FRAIS Salades +3560070711994 PRODUITS FRAIS Feuilletés/croissants/pains chocolat +3560070711994 PRODUITS FRAIS Feuilletés/croissants/pains chocolat +3560070348503 PRODUITS FRAIS Pizzas surgelées - Cuite sur pierre +3560070348596 PRODUITS FRAIS Panettone/brioche/prd tranche +3560070348596 PRODUITS FRAIS Panettone/brioche/prd tranche +3560070349319 PRODUITS FRAIS Salades +3560070349647 PRODUITS FRAIS Crèmes fraiches epaisses +3560070349647 PRODUITS FRAIS Crèmes fraiches epaisses +3560070349647 PRODUITS FRAIS Crèmes fraiches epaisses +3560070349692 PRODUITS FRAIS Crèmes fraiches epaisses +3560070349692 PRODUITS FRAIS Crèmes fraiches epaisses +3560070349692 PRODUITS FRAIS Crèmes fraiches epaisses +3560070349692 PRODUITS FRAIS Crèmes fraiches epaisses +3560070349746 PRODUITS FRAIS Camemberts +3560070349746 PRODUITS FRAIS Camemberts +3560070350889 EPICERIE Conserves Chataîgnes +3560070715619 EPICERIE Conserves Chataîgnes +3560070715619 EPICERIE Conserves Chataîgnes +3560070354504 PRODUITS FRAIS Fromages blanc aromatises / fruits +3560070354771 PRODUITS FRAIS Fromages blanc aromatises / fruits +3560070354924 PRODUITS FRAIS Plat cuis./prépar.pate légume +3560070355143 LIQUIDES Autres boissons non-gazeifiees Au thé +3560070356362 PRODUITS FRAIS Fromage italien +3560070356393 PRODUITS FRAIS Fromage italien +3560070357062 PRODUITS FRAIS Légumes cuisines/ Purées / Gratins +3560070357932 PRODUITS FRAIS Autres découpes de porc +3560070361946 EPICERIE Cafés solubles +3560070361991 EPICERIE Cafés moulus +3560070361991 EPICERIE Cafés moulus +3560070361991 EPICERIE Cafés moulus +3560070361991 EPICERIE Cafés moulus +3560070362035 EPICERIE Cafés moulus +3560070362127 EPICERIE Cafés moulus +3560070362127 EPICERIE Cafés moulus +3560070362127 EPICERIE Cafés moulus +3560070362127 EPICERIE Cafés moulus +3560070730636 PRODUITS FRAIS Spécialités festives (Bûches - Bûchettes...) +3560070730636 PRODUITS FRAIS Spécialités festives (Bûches - Bûchettes...) +3560070364824 EPICERIE Conserves de Tomates - Concentré +3560070364824 EPICERIE Conserves de Tomates - Concentré +3560070368082 EPICERIE Confiserie et chocolats noel +3560070368341 EPICERIE Confiserie et chocolats noel +3560070368372 EPICERIE Confiserie et chocolats noel +3560070368402 EPICERIE Confiserie et chocolats noel +3560070368433 EPICERIE Confiserie et chocolats noel +3560070368464 EPICERIE Confiserie et chocolats noel +3560070368495 EPICERIE Confiserie et chocolats noel +3560070370122 PRODUITS FRAIS Salades +3560070370153 PRODUITS FRAIS Salades +3560070370313 PRODUITS FRAIS Salades +3560070370436 PRODUITS FRAIS Panettone/brioche/prd tranche +3560070738335 EPICERIE Conserves de Petits pois +3560070738335 EPICERIE Conserves de Petits pois +3560070738335 EPICERIE Conserves de Petits pois +3560070738335 EPICERIE Conserves de Petits pois +3560070738335 EPICERIE Conserves de Petits pois +3560070372591 PRODUITS FRAIS Yaourts sante et biologique aromatisé +3560070372997 PFT Sachet/Barquettes Monovarietes +3560070372997 PFT Sachet/Barquettes Monovarietes +3560070738366 EPICERIE Conserves de Petits pois +3560070738366 EPICERIE Conserves de Petits pois +3560070738366 EPICERIE Conserves de Petits pois +3560070738366 EPICERIE Conserves de Petits pois +3560070738366 EPICERIE Conserves de Petits pois +3560070741670 PRODUITS FRAIS Bœuf haché / Préparation / Découpe +3560070741670 PRODUITS FRAIS Bœuf haché / Préparation / Découpe +3560070742332 PRODUITS FRAIS Emincés alumettes de viande +3560070742332 PRODUITS FRAIS Emincés alumettes de viande +3560070378906 PRODUITS FRAIS Poitrine de porc +3560070379514 PRODUITS FRAIS Emmentals blocs +3560070379514 PRODUITS FRAIS Emmentals blocs +3560070379514 PRODUITS FRAIS Emmentals blocs +3560070379514 PRODUITS FRAIS Emmentals blocs +3560070379514 PRODUITS FRAIS Emmentals blocs +3560070379514 PRODUITS FRAIS Emmentals blocs +3560070379736 EPICERIE Produits diététiques Autres salés +3560070379736 EPICERIE Produits diététiques Autres salés +3560070382828 PRODUITS FRAIS Saucissons cuits +3560070384181 PFT Sachet/Barquettes Monovarietes +3560070384181 PFT Sachet/Barquettes Monovarietes +3560070384181 PFT Sachet/Barquettes Monovarietes +3560070384181 PFT Sachet/Barquettes Monovarietes +3560070384181 PFT Sachet/Barquettes Monovarietes +3560070384181 PFT Sachet/Barquettes Monovarietes +3560070384181 PFT Sachet/Barquettes Monovarietes +3560070384259 PFT Sachet/Barquettes Monovarietes +3560070384259 PFT Sachet/Barquettes Monovarietes +3560070384259 PFT Sachet/Barquettes Monovarietes +3560070384259 PFT Sachet/Barquettes Monovarietes +3560070384259 PFT Sachet/Barquettes Monovarietes +3560070384259 PFT Sachet/Barquettes Monovarietes +3560070384259 PFT Sachet/Barquettes Monovarietes +3560070384259 PFT Sachet/Barquettes Monovarietes +3560070384259 PFT Sachet/Barquettes Monovarietes +3560070386352 EPICERIE Conserves - Autres plats cuisines +3560070386536 EPICERIE Barres céréalières +3560070386567 EPICERIE Barres céréalières +3560070386734 PRODUITS FRAIS Autres saucisses +3560070386826 PRODUITS FRAIS Foie gras +3560070387427 EPICERIE Produits diététiques Autres sucrés +3560070752157 EPICERIE Conserves de Haricots verts +3560070390953 PRODUITS FRAIS Traiteur sucré +3560070390984 PRODUITS FRAIS Traiteur sucré +3560070391011 PRODUITS FRAIS Traiteur sucré +3560070391042 PRODUITS FRAIS Traiteur sucré +3560070752157 EPICERIE Conserves de Haricots verts +3560070753895 PRODUITS FRAIS Raclette +3560070753895 PRODUITS FRAIS Raclette +3560070753895 PRODUITS FRAIS Raclette +3560070393350 PRODUITS FRAIS Préparation pommes de terres +3560070393350 PRODUITS FRAIS Préparation pommes de terres +3560070394791 LIQUIDES Tequilas +3560070394791 LIQUIDES Tequilas +3560070394975 PFT Salade Sachet/Barquettes Autre +3560070394975 PFT Salade Sachet/Barquettes Autre +3560070394975 PFT +3560070395750 EPICERIE Conserves de Haricots verts cueillis et rangés main +3560070396511 EPICERIE Mayonnaise +3560070398287 PRODUITS FRAIS Raclette +3560070398287 PRODUITS FRAIS Raclette +3560070400003 PRODUITS FRAIS Pains de mie élaboré +3560070400034 PRODUITS FRAIS Pains de mie élaboré +3560070400065 PRODUITS FRAIS Autres produits de panification industrielles +3560070400096 PRODUITS FRAIS Autres produits de panification industrielles +3560070400126 PRODUITS FRAIS Panettone/brioche/prd tranche +3560070400188 PRODUITS FRAIS Pains de mie élaboré +3560070400218 PRODUITS FRAIS Pains de mie élaboré +3560070756568 PRODUITS FRAIS Libre service - Produits carnes prepares +3560070401734 PRODUITS FRAIS Pates natures +3560070403073 PRODUITS FRAIS Patisseries industrielles - Madeleines +3560070405923 PRODUITS FRAIS Autres saucisses +3560070405954 PRODUITS FRAIS Autres saucisses +3560070406135 LIQUIDES Rhums blancs +3560070407118 EPICERIE Autres Aliments infantiles hors lait +3560070410774 PFT Aide patisserie +3560070410897 PFT Fruits moelleux +3560070410927 PFT Fruits Secs Aperitif +3560070410927 PFT Fruits Secs Aperitif +3560070411405 PRODUITS FRAIS Jambons crus +3560070412150 EPICERIE Confitures de fruits rouges +3560070415663 EPICERIE Cafés en grains +3560070773275 PRODUITS FRAIS Oeufs +3560070773275 PRODUITS FRAIS Oeufs +3560070773275 PRODUITS FRAIS Oeufs +3560070773275 PRODUITS FRAIS Oeufs +3560070773275 PRODUITS FRAIS Oeufs +3560070774425 PRODUITS FRAIS Glaces Batonnets +3560070774425 PRODUITS FRAIS Glaces Batonnets +3560070776177 EPICERIE ,Chocolat tablette - amande,,noisette,,riz, +3560070776177 EPICERIE ,Chocolat tablette - amande,,noisette,,riz, +3560070776207 EPICERIE ,Chocolat tablette - amande,,noisette,,riz, +3560070776207 EPICERIE ,Chocolat tablette - amande,,noisette,,riz, +3560070421398 EPICERIE Conserves de Haricots verts cueillis et rangés main +3560070423088 LIQUIDES Nectars - Autres fruits +3560070423088 LIQUIDES Autres boissons non-gazeifiees Aux fruits +3560070423309 PRODUITS FRAIS Fromage hollandais +3560070423309 PRODUITS FRAIS Fromage hollandais +3560070425143 EPICERIE Pâtes alimentaires sèches Spécialités +3560070427673 EPICERIE Confiserie et chocolats paques +3560070427857 EPICERIE Confiserie et chocolats paques +3560070427888 EPICERIE Confiserie et chocolats paques +3560070782758 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560070782758 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560070782758 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560070782758 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560070782789 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560070782789 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560070782789 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560070782789 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560070782789 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560070782789 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560070782789 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560070787074 PRODUITS FRAIS Jambons cuits +3560070787074 PRODUITS FRAIS Jambons cuits +3560070787074 PRODUITS FRAIS Jambons cuits +3560070434657 LIQUIDES Autres boissons non-gazeifiees Aux fruits +3560070435210 EPICERIE Sauces chaudes à base de tomate et tomate frito +3560070435210 EPICERIE Sauces chaudes à base de tomate et tomate frito +3560070436217 PRODUITS FRAIS Riz et semoule +3560070437580 PRODUITS FRAIS Raclette +3560070439171 EPICERIE Conserves Artichauts +3560070440191 EPICERIE Cafés solubles +3560070440375 EPICERIE Conserves Asperges +3560070440405 EPICERIE Conserves Poivrons +3560070443291 EPICERIE Produits diététiques Galettes de riz +3560070444366 PRODUITS FRAIS Légumes cuisines/ Purées / Gratins +3560070444373 PRODUITS FRAIS Légumes verts surgelés +3560070444373 PRODUITS FRAIS Légumes verts surgelés +3560070444373 PRODUITS FRAIS Légumes verts surgelés +3560070799367 PRODUITS FRAIS Fromage hollandais +3560070799367 PRODUITS FRAIS Fromage hollandais +3560070446117 EPICERIE Compotes gourdes +3560070446193 EPICERIE Compotes gourdes +3560070446193 EPICERIE Compotes gourdes +3560070446193 EPICERIE Compotes gourdes +3560070446506 PRODUITS FRAIS Volailles Découpes / Préparations +3560070448722 PRODUITS FRAIS Bœuf haché / Préparation / Découpe +3560070448753 PRODUITS FRAIS Bœuf haché / Préparation / Découpe +3560070448814 PRODUITS FRAIS Bœuf haché / Préparation / Découpe +3560070449514 EPICERIE Barres céréalières +3560070449606 EPICERIE Barres céréalières +3560070450732 EPICERIE Conserves de Thon +3560070451685 PRODUITS FRAIS Camemberts +3560070451685 PRODUITS FRAIS Camemberts +3560070453337 LIQUIDES Purs Jus de Fruits - Multifruits +3560070453337 LIQUIDES Purs Jus de Fruits - Multifruits +3560070453337 LIQUIDES Purs Jus de Fruits - Multifruits +3560070454778 PRODUITS FRAIS Pates à tarte fraiches +3560070456987 PRODUITS FRAIS Libre service - Poulets +3560070463800 PRODUITS FRAIS Spec.sucree dont crepe gauffre +3560070466894 EPICERIE Corn flakes +3560070467945 PRODUITS FRAIS Pates à tarte fraiches +3560070470501 PRODUITS FRAIS Emmentals rapes +3560070470501 PRODUITS FRAIS Emmentals rapes +3560070470501 PRODUITS FRAIS Emmentals rapes +3560070470501 PRODUITS FRAIS Emmentals rapes +3560070470501 PRODUITS FRAIS Emmentals rapes +3560070470501 PRODUITS FRAIS Emmentals rapes +3560070472888 EPICERIE Pates à tartiner chocolat +3560070472918 EPICERIE Chocolat tablette - noirs +3560070472949 EPICERIE Chocolat tablette - noirs +3560070472970 EPICERIE ,Chocolat tablette - amande,,noisette,,riz, +3560070474189 PRODUITS FRAIS Pates natures +3560070476022 EPICERIE Confiserie et chocolats noel +3560070476923 PFT Autres Legumes a cuire +3560070477340 EPICERIE Cafés en dosettes +3560070477371 EPICERIE Cafés en dosettes +3560070478668 EPICERIE Produits diététiques Autres sucrés +3560070478750 EPICERIE ,Cakes aux fruits,, fourres, +3560070478811 EPICERIE ,Cakes aux fruits,, fourres, +3560070479467 EPICERIE Conserves de Tomates pelées +3560070479467 EPICERIE Conserves de Tomates pelées +3560070479467 EPICERIE Conserves de Tomates pelées +3560070484225 EPICERIE Biscuits sucrés Au chocolat +3560070484225 EPICERIE Biscuits sucrés Au chocolat +3560070484447 PRODUITS FRAIS Autres legumes surgelés +3560070484447 PRODUITS FRAIS Autres legumes surgelés +3560070484447 PRODUITS FRAIS Autres legumes surgelés +3560070823246 LIQUIDES Purs Jus de Fruits - Orange +3560070823246 LIQUIDES Purs Jus de Fruits - Orange +3560070486243 EPICERIE Cafés moulus +3560070486380 PRODUITS FRAIS Charc.volaille et autre viande +3560070486687 PRODUITS FRAIS Libre service - Poulets +3560070486687 PRODUITS FRAIS Libre service - Poulets +3560070486717 PRODUITS FRAIS Libre service - Poulets +3560070486717 PRODUITS FRAIS Libre service - Poulets +3560070486748 PRODUITS FRAIS Libre service - Poulets +3560070486748 PRODUITS FRAIS Libre service - Poulets +3560070486779 PRODUITS FRAIS Libre service - Poulets +3560070486779 PRODUITS FRAIS Libre service - Poulets +3560070486861 PRODUITS FRAIS Libre service - Poulets +3560070486861 PRODUITS FRAIS Libre service - Poulets +3560070486892 PRODUITS FRAIS Libre service - Poulets +3560070486892 PRODUITS FRAIS Libre service - Poulets +3560070486984 PRODUITS FRAIS Libre service - Autres volailles +3560070486984 PRODUITS FRAIS Libre service - Autres volailles +3560070487011 PRODUITS FRAIS Libre service - Autres volailles +3560070487011 PRODUITS FRAIS Libre service - Autres volailles +3560070487042 PRODUITS FRAIS Libre service - Autres volailles +3560070487042 PRODUITS FRAIS Libre service - Autres volailles +3560070487073 PRODUITS FRAIS Libre service - Produits carnes prepares +3560070487103 PRODUITS FRAIS Libre service - Produits carnes prepares +3560070823895 EPICERIE Miels +3560070823895 EPICERIE Miels +3560070824151 PRODUITS FRAIS Plats cuisinés surgelés - a base de volaile +3560070824151 PRODUITS FRAIS Plats cuisinés surgelés - a base de volaile +3560070488483 LIQUIDES Eaux plates Bouteille plastique +3560070488490 LIQUIDES Eaux plates Bouteille plastique +3560070824434 PRODUITS FRAIS Surimi surgelés +3560070824434 PRODUITS FRAIS Surimi surgelés +3560070824823 LIQUIDES Autres fruits gazéifiées +3560070824823 LIQUIDES Autres fruits gazéifiées +3560070824830 LIQUIDES Autres fruits gazéifiées +3560070492497 PRODUITS FRAIS Bœuf haché / Préparation / Découpe +3560070492497 PRODUITS FRAIS Bœuf haché / Préparation / Découpe +3560070824830 LIQUIDES Autres fruits gazéifiées +3560070495948 PRODUITS FRAIS Frites surgelées +3560070495948 PRODUITS FRAIS Frites surgelées +3560070826216 PRODUITS FRAIS Poissons surgelés nature tranche/morceau +3560070826216 PRODUITS FRAIS Poissons surgelés nature tranche/morceau +3560070826216 PRODUITS FRAIS Poissons surgelés nature tranche/morceau +3560070827893 EPICERIE Vegetale +3560070827893 EPICERIE Vegetale +3560070498796 EPICERIE Pâtés +3560070499366 EPICERIE ,Coulis,, nappages, +3560070499748 PRODUITS FRAIS Bœuf haché / Préparation / Découpe +3560070499779 PRODUITS FRAIS Bœuf haché / Préparation / Découpe +3560070499809 PRODUITS FRAIS Bœuf haché / Préparation / Découpe +3560070829149 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560070829149 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560070829293 LIQUIDES Purs Jus de Fruits - Autres +3560070503384 EPICERIE Ketchup +3560070503735 PRODUITS FRAIS Charc.volaille et autre viande +3560070503766 PRODUITS FRAIS Charc.volaille et autre viande +3560070503797 PRODUITS FRAIS Charc.volaille et autre viande +3560070503827 PRODUITS FRAIS Charc.volaille et autre viande +3560070829293 LIQUIDES Purs Jus de Fruits - Autres +3560070829309 LIQUIDES Purs Jus de Fruits - Autres +3560070504732 EPICERIE Confiserie de chocolat +3560070504732 EPICERIE Confiserie de chocolat +3560070504794 EPICERIE Confiserie de chocolat +3560070829309 LIQUIDES Purs Jus de Fruits - Autres +3560070506408 PRODUITS FRAIS Raclette +3560070510139 EPICERIE ,Gateaux roules,, fourres, +3560070511778 EPICERIE Conserves Plats cuisines base de legumes +3560070513208 EPICERIE Conserves Coeur de palmier +3560070513208 EPICERIE Conserves Coeur de palmier +3560070513208 EPICERIE Conserves Coeur de palmier +3560070830381 EPICERIE Thés parfumés +3560070513567 PRODUITS FRAIS Charc.volaille et autre viande +3560070513789 PRODUITS FRAIS Panés +3560070513819 PRODUITS FRAIS Panés +3560070513840 PRODUITS FRAIS Panés +3560070830381 EPICERIE Thés parfumés +3560070514724 PRODUITS FRAIS Fromage italien +3560070515325 PRODUITS FRAIS Traiteur sucré +3560070519309 EPICERIE Autres céréales +3560070520381 EPICERIE Autres céréales +3560070520411 EPICERIE Sauces chaudes - pâtes - riz +3560070837052 EPICERIE Riz parfumés (Basmati & Thaï) +3560070837052 EPICERIE Riz parfumés (Basmati & Thaï) +3560070529636 PRODUITS FRAIS Poissons surgelés nature tranche/morceau +3560070530090 PRODUITS FRAIS Desserts - Mousses +3560070530595 PRODUITS FRAIS Fromages frais - Féta +3560070531455 EPICERIE Levures +3560070532308 EPICERIE Caramels et spécialités +3560070837984 EPICERIE Riz parfumés (Basmati & Thaï) +3560070837984 EPICERIE Riz parfumés (Basmati & Thaï) +3560070838844 PRODUITS FRAIS Spécialités festives (Bûches - Bûchettes...) +3560070838844 PRODUITS FRAIS Spécialités festives (Bûches - Bûchettes...) +3560070838875 PRODUITS FRAIS Spécialités festives (Bûches - Bûchettes...) +3560070838875 PRODUITS FRAIS Spécialités festives (Bûches - Bûchettes...) +3560070537464 EPICERIE Autres sauces chaudes +3560070538652 EPICERIE Epices et herbes +3560070538805 EPICERIE ,Aides culinaires,, boillons solides et court bouillon, +3560070852086 EPICERIE Thés parfumés +3560070541270 PRODUITS FRAIS Dessert patissier +3560070541362 PRODUITS FRAIS Crèmes dessert +3560070855926 PRODUITS FRAIS Charc.volaille et autre viande +3560070855926 PRODUITS FRAIS Charc.volaille et autre viande +3560070542642 PRODUITS FRAIS Yaourts sante et biologique aux fruits +3560070543243 PRODUITS FRAIS Volailles Découpes / Préparations +3560070548118 LIQUIDES Sirops concentrés à base de fruits +3560070552498 PRODUITS FRAIS Autres legumes surgelés +3560070552498 PRODUITS FRAIS Autres legumes surgelés +3560070554300 PRODUITS FRAIS Autres cremes +3560070554393 LIQUIDES Boissons apéritives ss alcool +3560070884193 PRODUITS FRAIS Légumes verts surgelés +3560070884193 PRODUITS FRAIS Légumes verts surgelés +3560070558445 PRODUITS FRAIS Poitrine de porc +3560070559879 PRODUITS FRAIS Saumon fumés +3560070559879 PRODUITS FRAIS Saumon fumés +3560070559879 PRODUITS FRAIS Saumon fumés +3560070559879 PRODUITS FRAIS Saumon fumés +3560070561216 PRODUITS FRAIS Salades +3560070561216 PRODUITS FRAIS Salades +3560070563746 PRODUITS FRAIS Sandwichs +3560070563777 PRODUITS FRAIS Sandwichs +3560070564019 PRODUITS FRAIS Sandwichs +3560070565672 PRODUITS FRAIS Sandwichs +3560070566235 PRODUITS FRAIS Salades +3560070568802 PRODUITS FRAIS Légumes verts surgelés +3560070568802 PRODUITS FRAIS Légumes verts surgelés +3560070568833 PRODUITS FRAIS Légumes verts surgelés +3560070568833 PRODUITS FRAIS Légumes verts surgelés +3560070568833 PRODUITS FRAIS Légumes verts surgelés +3560070568864 PRODUITS FRAIS Autres legumes surgelés +3560070568864 PRODUITS FRAIS Autres legumes surgelés +3560070892976 EPICERIE Friandise chien +3560070892976 EPICERIE Friandise chien +3560070569182 PRODUITS FRAIS Libre service - Produits carnes prepares +3560070569212 PRODUITS FRAIS Libre service - Produits carnes prepares +3560070569243 PRODUITS FRAIS Libre service - Poulets +3560070569274 PRODUITS FRAIS Libre service - Produits carnes prepares +3560070571222 PRODUITS FRAIS Légumes cuisines/ Purées / Gratins +3560070571222 PRODUITS FRAIS Légumes cuisines/ Purées / Gratins +3560070572304 EPICERIE Conserves de Tomates pelées +3560070572304 EPICERIE Conserves de Tomates pelées +3560070573073 EPICERIE ,Gateaux roules,, fourres, +3560070575459 LIQUIDES Vins doux naturels +3560070907472 EPICERIE Conserves de Haricots verts cueillis et rangés main +3560070907472 EPICERIE Conserves de Haricots verts cueillis et rangés main +3560070580965 LIQUIDES Autres cocktails +3560070581078 LIQUIDES Bières Blondes +3560070582587 EPICERIE Corn flakes +3560070582648 EPICERIE Autres céréales +3560070586042 PRODUITS FRAIS Laits longue conservation natu +3560070586073 PRODUITS FRAIS Laits longue conservation natu +3560070586721 PFT Crudite Composee +3560070588725 EPICERIE Cafés en grains +3560070588923 PRODUITS FRAIS Spec.sucree dont crepe gauffre +3560070925636 PRODUITS FRAIS Libre service - Autres volailles +3560070925636 PRODUITS FRAIS Libre service - Autres volailles +3560070928255 EPICERIE Infusions classiques +3560070928255 EPICERIE Infusions classiques +3560070928316 EPICERIE Thés parfumés +3560070928316 EPICERIE Thés parfumés +3560070592630 LIQUIDES Autres boissons non-gazeifiees Aux fruits +3560070930036 PRODUITS FRAIS Comte +3560070930036 PRODUITS FRAIS Comte +3560070930036 PRODUITS FRAIS Comte +3560070930128 PRODUITS FRAIS Comte +3560070930128 PRODUITS FRAIS Comte +3560070595587 EPICERIE Desserts a preparer +3560070937868 PRODUITS FRAIS Frites surgelées +3560070937868 PRODUITS FRAIS Frites surgelées +3560070598717 PRODUITS FRAIS Noix st jacques/petoncle/coquilles surgelés +3560070598717 PRODUITS FRAIS Noix st jacques/petoncle/coquilles surgelés +3560070598717 PRODUITS FRAIS Noix st jacques/petoncle/coquilles surgelés +3560070598717 PRODUITS FRAIS Noix st jacques/petoncle/coquilles surgelés +3560070598717 PRODUITS FRAIS Noix st jacques/petoncle/coquilles surgelés +3560070603077 EPICERIE Conserves Asperges +3560070604340 PRODUITS FRAIS Bœuf haché / Préparation / Découpe +3560070605583 PRODUITS FRAIS ,Quiches,, tartes,, tourtes surgelées, +3560070605637 EPICERIE Conserves - Autres plats cuisines +3560070606856 PRODUITS FRAIS Patisseries industrielles - gateaux a trancher +3560070606856 PRODUITS FRAIS Patisseries industrielles - gateaux a trancher +3560070606900 PRODUITS FRAIS Spec.sucree dont crepe gauffre +3560070955527 EPICERIE Conserves de Thon +3560070955527 EPICERIE Conserves de Thon +3560070614172 EPICERIE Autres céréales +3560070616114 PRODUITS FRAIS Frites surgelées +3560070616114 PRODUITS FRAIS Frites surgelées +3560070962037 PRODUITS FRAIS Panettone/brioche/prd tranche +3560070962037 PRODUITS FRAIS Panettone/brioche/prd tranche +3560070962037 PRODUITS FRAIS Panettone/brioche/prd tranche +3560070619580 PRODUITS FRAIS Pains de mie élaboré +3560070636662 EPICERIE Semoules de ble / Couscous +3560070649594 PRODUITS FRAIS Libre service - Poulets +3560070649716 EPICERIE ,Gateaux roules,, fourres, +3560070669349 EPICERIE Biscuits sucrés Secs +3560070669981 EPICERIE Chocolat tablette - noirs +3560070670017 EPICERIE Chocolat tablette - noirs +3560070670048 EPICERIE Chocolat tablette - noirs +3560070674558 EPICERIE Sauces chaudes - pâtes - riz +3560070679782 EPICERIE Confiserie et chocolats paques +3560070681501 PRODUITS FRAIS Libre service - Lapins +3560070682027 PRODUITS FRAIS Bacs Crèmes Glacées +3560070684120 EPICERIE Pommes de terre +3560070684120 EPICERIE Pommes de terre +3560070685035 EPICERIE Biscuits sucrés Au chocolat +3560070686148 PRODUITS FRAIS Frites surgelées +3560071001520 EPICERIE Sec chat +3560071001520 EPICERIE Sec chat +3560071001537 EPICERIE Sec chat +3560071001537 EPICERIE Sec chat +3560071001544 EPICERIE Sec chat +3560071001544 EPICERIE Sec chat +3560071001551 EPICERIE Sec chat +3560071001551 EPICERIE Sec chat +3560071001575 EPICERIE Sec chat +3560071001575 EPICERIE Sec chat +3560071001582 EPICERIE Sec chat +3560071001582 EPICERIE Sec chat +3560071001599 EPICERIE Sec chat +3560071001599 EPICERIE Sec chat +3560070691005 EPICERIE Carottes +3560071001605 EPICERIE Sec chat +3560071001605 EPICERIE Sec chat +3560071001612 EPICERIE Sec chat +3560071001612 EPICERIE Sec chat +3560071001636 EPICERIE Sec chat +3560071001636 EPICERIE Sec chat +3560071001643 EPICERIE Sec chat +3560071001643 EPICERIE Sec chat +3560070694419 EPICERIE Epices et herbes +3560070697359 PFT Fruits secs a coque +3560070698356 PRODUITS FRAIS Dessert patissier +3560071003326 PRODUITS FRAIS Poissons surgelés entiers +3560071003326 PRODUITS FRAIS Poissons surgelés entiers +3560071003418 PRODUITS FRAIS Noix st jacques/petoncle/coquilles surgelés +3560071003418 PRODUITS FRAIS Noix st jacques/petoncle/coquilles surgelés +3560071003418 PRODUITS FRAIS Noix st jacques/petoncle/coquilles surgelés +3560070701407 EPICERIE Chocolat tablette - noirs +3560071006402 PRODUITS FRAIS ,Langoustes,, homards,, crabes surgelés, +3560071006402 PRODUITS FRAIS ,Langoustes,, homards,, crabes surgelés, +3560071006402 PRODUITS FRAIS ,Langoustes,, homards,, crabes surgelés, +3560071006822 EPICERIE Conserves de mais +3560071006822 EPICERIE Conserves de mais +3560071006822 EPICERIE Conserves de mais +3560070707294 EPICERIE Sauces chaudes à base de tomate et tomate frito +3560070707294 EPICERIE Sauces chaudes à base de tomate et tomate frito +3560070707294 EPICERIE Sauces chaudes à base de tomate et tomate frito +3560070707294 EPICERIE Sauces chaudes à base de tomate et tomate frito +3560070707874 PRODUITS FRAIS Entrées exotiques +3560070708833 PRODUITS FRAIS Salades +3560070708833 PRODUITS FRAIS Salades +3560070710447 PFT Sachet/Barquettes Composees +3560070710447 PFT Sachet/Barquettes Composees +3560070710447 PFT Sachet/Barquettes Composees +3560070711871 PRODUITS FRAIS Sandwichs +3560071008994 LIQUIDES Autres fruits gazéifiées +3560071008994 LIQUIDES Autres fruits gazéifiées +3560071009007 LIQUIDES Limonades gazéifiées +3560070712786 EPICERIE Cafés moulus +3560070712816 EPICERIE Cafés moulus +3560071009007 LIQUIDES Autres boissons gazéifiées +3560070715459 LIQUIDES Cidres +3560070715565 LIQUIDES Cidres +3560070717545 PRODUITS FRAIS ,Patés,, terrines, +3560070717903 PRODUITS FRAIS Frites surgelées +3560071009984 EPICERIE Chips salees +3560071009984 EPICERIE Chips salees +3560070720859 EPICERIE Chocolat tablette - noirs +3560070722754 LIQUIDES Autres cocktails +3560070724055 EPICERIE Pâtés +3560070726653 PRODUITS FRAIS Yaourts a boire +3560070728190 LIQUIDES Jus d'ananas à base de concentré +3560070728190 LIQUIDES Jus d'ananas à base de concentré +3560070730483 PRODUITS FRAIS Autres desserts glacés +3560070730995 PRODUITS FRAIS Libre service - Poulets +3560070730995 PRODUITS FRAIS Libre service - Poulets +3560070730995 PRODUITS FRAIS Libre service - Poulets +3560070730995 PRODUITS FRAIS Libre service - Poulets +3560070730995 PRODUITS FRAIS Libre service - Poulets +3560070730995 PRODUITS FRAIS Libre service - Poulets +3560070731015 PRODUITS FRAIS Libre service - Poulets +3560070731015 PRODUITS FRAIS Libre service - Poulets +3560070731015 PRODUITS FRAIS Libre service - Poulets +3560070731015 PRODUITS FRAIS Libre service - Poulets +3560070731015 PRODUITS FRAIS Libre service - Poulets +3560070731015 PRODUITS FRAIS Libre service - Poulets +3560071012823 PRODUITS FRAIS Fromage italien +3560070731084 PRODUITS FRAIS Libre service - Poulets +3560071012823 PRODUITS FRAIS Fromage italien +3560071013233 PRODUITS FRAIS Laits longue conservation natu +3560070735235 LIQUIDES Autres boissons non-gazéifiées +3560070735464 EPICERIE Confiserie et chocolats noel +3560071013233 PRODUITS FRAIS Laits longue conservation natu +3560071013240 PRODUITS FRAIS Laits longue conservation natu +3560071013240 PRODUITS FRAIS Laits longue conservation natu +3560070737369 PRODUITS FRAIS Jambons crus +3560070737390 PRODUITS FRAIS Jambons crus +3560070737420 PRODUITS FRAIS Autres saucisses +3560071013400 PRODUITS FRAIS Laits longue conservation natu +3560071013400 PRODUITS FRAIS Laits longue conservation natu +3560070738168 EPICERIE Confiserie et chocolats noel +3560070738199 EPICERIE Confiserie et chocolats noel +3560071013448 PRODUITS FRAIS Laits longue conservation natu +3560071013448 PRODUITS FRAIS Laits longue conservation natu +3560071013455 PRODUITS FRAIS Laits longue conservation natu +3560071013455 PRODUITS FRAIS Laits longue conservation natu +3560071013486 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560071013486 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560071013486 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560071013486 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560070739394 PRODUITS FRAIS Libre service - Poulets +3560070743889 PRODUITS FRAIS Yaourts sante et biologique aux fruits +3560070749089 EPICERIE Conserves - Autres plats cuisines +3560070749805 PRODUITS FRAIS Bœuf haché / Préparation / Découpe +3560070750238 LIQUIDES Autres boissons non-gazeifiees Aux fruits +3560071015398 PRODUITS FRAIS ,Langoustes,, homards,, crabes surgelés, +3560071015398 PRODUITS FRAIS ,Langoustes,, homards,, crabes surgelés, +3560071015404 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560071015404 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560070753772 PRODUITS FRAIS Autres pâtes molles +3560070754526 EPICERIE Autres Aliments infantiles hors lait +3560070756568 PRODUITS FRAIS Libre service - Produits carnes prepares +3560070759293 EPICERIE Biscuits sucrés Secs +3560070760107 PRODUITS FRAIS Autres produits surgelés +3560070760190 PRODUITS FRAIS ,Quiches,, tartes,, tourtes surgelées, +3560070762828 EPICERIE Produits diététiques Autres salés +3560070767328 PFT Fruits moelleux +3560070767656 EPICERIE Laits infantiles liquides +3560070768202 PRODUITS FRAIS Salades +3560070768202 PRODUITS FRAIS Salades +3560070769131 PFT Aide patisserie +3560070769407 PFT Aide patisserie +3560070769438 PFT Fruits moelleux +3560070769469 PFT Fruits Secs Aperitif +3560070769520 PFT Aide patisserie +3560070770489 EPICERIE Chocolat tablette - noirs +3560070774326 PRODUITS FRAIS Glaces Cones et cornets +3560070777174 PRODUITS FRAIS Dessert patissier +3560070780389 EPICERIE Confiserie et chocolats paques +3560070780419 EPICERIE Confiserie et chocolats paques +3560070780440 EPICERIE Confiserie et chocolats paques +3560070781256 PRODUITS FRAIS Saucisses de strasbourg +3560071020750 EPICERIE Huile de colza +3560071020750 EPICERIE Huile de colza +3560071033804 PRODUITS FRAIS Cocktails de fruits surgelés +3560070784066 PRODUITS FRAIS Pains +3560071033804 PRODUITS FRAIS Cocktails de fruits surgelés +3560070790524 PRODUITS FRAIS Autres fromages frais +3560070791064 PRODUITS FRAIS Goûter enfant +3560070791118 LIQUIDES Limonades gazéifiées +3560070800230 EPICERIE Autres céréales +3560070800261 EPICERIE Autres céréales +3560070800292 EPICERIE Autres céréales +3560070800322 EPICERIE Autres céréales +3560070800384 EPICERIE Autres céréales +3560071081133 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560071081133 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560071081133 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560071081133 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560071082154 EPICERIE Sec chat +3560071082154 EPICERIE Sec chat +3560071082178 EPICERIE Sec chat +3560071082178 EPICERIE Sec chat +3560071082338 EPICERIE Miels +3560071082338 EPICERIE Miels +3560071082345 EPICERIE Miels +3560071082345 EPICERIE Miels +3560070809653 PRODUITS FRAIS Fromages blanc aromatises / fruits +3560071085926 PRODUITS FRAIS Crevettes +3560071085926 PRODUITS FRAIS Crevettes +3560071093716 PRODUITS FRAIS Fromages de chevre +3560071093716 PRODUITS FRAIS Fromages de chevre +3560071094898 PRODUITS FRAIS Lardons +3560071094898 PRODUITS FRAIS Lardons +3560071094973 PRODUITS FRAIS Lardons +3560071094973 PRODUITS FRAIS Lardons +3560071095345 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560071095345 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560071095352 PRODUITS FRAIS Cocktail/garniture/salad f mer surgelés +3560071095352 PRODUITS FRAIS Cocktail/garniture/salad f mer surgelés +3560071095352 PRODUITS FRAIS Cocktail/garniture/salad f mer surgelés +3560071095352 PRODUITS FRAIS Cocktail/garniture/salad f mer surgelés +3560071095352 PRODUITS FRAIS Cocktail/garniture/salad f mer surgelés +3560071095352 PRODUITS FRAIS Cocktail/garniture/salad f mer surgelés +3560071095352 PRODUITS FRAIS Cocktail/garniture/salad f mer surgelés +3560071095352 PRODUITS FRAIS Cocktail/garniture/salad f mer surgelés +3560071098278 PRODUITS FRAIS Oeufs +3560070812172 PRODUITS FRAIS ,Quiches,, tartes,, tourtes surgelées, +3560071098278 PRODUITS FRAIS Oeufs +3560071098285 PRODUITS FRAIS Oeufs +3560071098285 PRODUITS FRAIS Oeufs +3560071098292 PRODUITS FRAIS Oeufs +3560071098292 PRODUITS FRAIS Oeufs +3560070817627 EPICERIE ,Coulis,, nappages, +3560070817658 EPICERIE ,Coulis,, nappages, +3560070817719 EPICERIE ,Coulis,, nappages, +3560070819096 EPICERIE Autres légumes +3560070819362 EPICERIE Conserves de Haricots verts cueillis et rangés main +3560070820580 LIQUIDES Jus de pomme bio +3560070820597 LIQUIDES Jus de pomme bio +3560070820597 LIQUIDES Jus de pomme bio +3560071134488 EPICERIE Conserves de Flageolets +3560071134488 EPICERIE Conserves de Flageolets +3560071151034 PRODUITS FRAIS Pates à tarte fraiches +3560071151034 PRODUITS FRAIS Pates à tarte fraiches +3560070821174 PRODUITS FRAIS Glaces Pots et coupelles +3560070821204 EPICERIE Conserves - Autres plats cuisines +3560070821211 EPICERIE Conserves - Autres plats cuisines +3560070821228 EPICERIE Conserves - Autres plats cuisines +3560070821266 EPICERIE Chocolat tablette - noirs +3560071161460 PRODUITS FRAIS Pates à tarte fraiches +3560071161460 PRODUITS FRAIS Pates à tarte fraiches +3560071161460 PRODUITS FRAIS Pates à tarte fraiches +3560071161460 PRODUITS FRAIS Pates à tarte fraiches +3560071161477 PRODUITS FRAIS Pates à tarte fraiches +3560071161477 PRODUITS FRAIS Pates à tarte fraiches +3560071161477 PRODUITS FRAIS Pates à tarte fraiches +3560071161477 PRODUITS FRAIS Pates à tarte fraiches +3560071161484 PRODUITS FRAIS Pates à tarte fraiches +3560071161484 PRODUITS FRAIS Pates à tarte fraiches +3560071161491 PRODUITS FRAIS Pates à tarte fraiches +3560071161491 PRODUITS FRAIS Pates à tarte fraiches +3560071164003 PRODUITS FRAIS Libre service - Poulets +3560071164003 PRODUITS FRAIS Libre service - Poulets +3560070821938 EPICERIE Autres céréales +3560071164003 PRODUITS FRAIS Libre service - Poulets +3560071164003 PRODUITS FRAIS Libre service - Poulets +3560071164003 PRODUITS FRAIS Libre service - Poulets +3560071164065 PRODUITS FRAIS Libre service - Poulets +3560071164065 PRODUITS FRAIS Libre service - Poulets +3560071164065 PRODUITS FRAIS Libre service - Poulets +3560071164065 PRODUITS FRAIS Libre service - Poulets +3560071164065 PRODUITS FRAIS Libre service - Poulets +3560071164690 PRODUITS FRAIS Pains de mie élaboré +3560071164690 PRODUITS FRAIS Pains de mie élaboré +3560070822829 EPICERIE Chocolat tablette - noirs +3560070822829 EPICERIE Chocolat tablette - noirs +3560071174682 LIQUIDES Purs Jus de Fruits - Multifruits +3560070822997 EPICERIE Snacks: Produits souffles et extrudes +3560071174682 LIQUIDES Purs Jus de Fruits - Multifruits +3560071174699 LIQUIDES Autres boissons non-gazeifiees Aux fruits +3560071174699 LIQUIDES Autres boissons non-gazeifiees Aux fruits +3560071174705 LIQUIDES Autres boissons non-gazeifiees Aux fruits +3560071174705 LIQUIDES Autres boissons non-gazeifiees Aux fruits +3560071174712 LIQUIDES Autres boissons non-gazeifiees Aux fruits +3560071174712 LIQUIDES Autres boissons non-gazeifiees Aux fruits +3560070823260 LIQUIDES Jus d'autres fruits bio +3560070823260 LIQUIDES Jus d'autres fruits bio +3560070823277 LIQUIDES Jus d'autres fruits bio +3560071174996 EPICERIE Pâtes alimentaires sèches +3560071174996 EPICERIE Pâtes alimentaires sèches +3560071175023 EPICERIE Pâtes alimentaires sèches +3560071175023 EPICERIE Pâtes alimentaires sèches +3560071176419 PRODUITS FRAIS Légumes verts surgelés +3560071176419 PRODUITS FRAIS Légumes verts surgelés +3560071177638 PRODUITS FRAIS Préparations à tartiner et rillettes +3560071177638 PRODUITS FRAIS Préparations à tartiner et rillettes +3560071189051 PRODUITS FRAIS Poissons surgelés natures filets +3560071189051 PRODUITS FRAIS Poissons surgelés natures filets +3560070823802 EPICERIE Mueslis +3560070824137 EPICERIE Semoules de ble / Couscous +3560070824137 EPICERIE Semoules de ble / Couscous +3560070824458 LIQUIDES Autres fruits gazéifiées +3560070824748 EPICERIE Confitures de fruits rouges +3560070824755 EPICERIE Confitures de fruits jaunes +3560071220860 EPICERIE Conserves de Haricots rouges +3560071220860 EPICERIE Conserves de Haricots rouges +3560071220921 EPICERIE Conserves de Lentilles +3560071220921 EPICERIE Conserves de Lentilles +3560071220952 EPICERIE Conserves de Lentilles +3560071220952 EPICERIE Conserves de Lentilles +3560070825271 LIQUIDES Nectars de Pomme +3560070825271 LIQUIDES Nectars de Pomme +3560070825295 PRODUITS FRAIS Poissons surgelés natures filets +3560070825394 EPICERIE Potages deshydrates +3560070825813 LIQUIDES Nectars Multifruits +3560070827923 EPICERIE Confitures d autres fruits +3560070829019 LIQUIDES Créme (liqueur) +3560070829323 LIQUIDES Purs Jus de Fruits - Pomme +3560070829323 LIQUIDES Purs Jus de Fruits - Pomme +5400101171244 EPICERIE Conserves de Tomates concassées +5400101171244 EPICERIE Conserves de Tomates concassées +5400101173224 EPICERIE Conserves de Petits pois +5400101173224 EPICERIE Conserves de Petits pois +5400101173224 EPICERIE Conserves de Petits pois +5400101173224 EPICERIE Conserves de Petits pois +5400101173613 EPICERIE Salsifis +5400101173613 EPICERIE Salsifis +5400101173675 EPICERIE Conserves de Petits pois carottes +5400101173675 EPICERIE Conserves de Petits pois carottes +5400101184442 EPICERIE Conserves de Petits pois +5400101184442 EPICERIE Conserves de Petits pois +3560070832934 PRODUITS FRAIS Libre service - Poulets +3560070833191 EPICERIE Confiserie et chocolats noel +3560070833313 EPICERIE Confiserie et chocolats noel +3560070835898 EPICERIE Confiserie et chocolats noel +3560070836277 EPICERIE Confiserie de chocolat - Autres produits +8012666010707 PRODUITS FRAIS Calamar/encornet/poulpe/seches surgelés +8012666010707 PRODUITS FRAIS Calamar/encornet/poulpe/seches surgelés +3560070846696 PRODUITS FRAIS Corps gras a tartiner +8012666012701 PRODUITS FRAIS Frites surgelées +8012666012701 PRODUITS FRAIS Frites surgelées +3560070847297 PRODUITS FRAIS Plat cuis./prépar.pate légume +8012666019144 EPICERIE Conserves Asperges +8012666019144 EPICERIE Conserves Asperges +8012666026876 PRODUITS FRAIS Autres fruits de mer/preparés surgelés +8012666026876 PRODUITS FRAIS Autres fruits de mer/preparés surgelés +8012666026876 PRODUITS FRAIS Autres fruits de mer/preparés surgelés +3560070852086 EPICERIE Thés parfumés +3560070852147 EPICERIE Thés parfumés +8431876006438 EPICERIE Cafés solubles +8431876006438 EPICERIE Cafés solubles +3560070854103 PRODUITS FRAIS Volailles Découpes / Préparations +8431876008159 EPICERIE Conserves Poivrons +8431876008159 EPICERIE Conserves Poivrons +3560070856480 PRODUITS FRAIS Frites surgelées +3560070856510 PRODUITS FRAIS Préparation pommes de terres +3560070856596 EPICERIE ,Chocolat patissier,,couverture, +3560070856985 EPICERIE Autres Aliments infantiles hors lait +3560070857012 EPICERIE Autres Aliments infantiles hors lait +3560070857074 EPICERIE Autres Aliments infantiles hors lait +8431876012354 EPICERIE Conserves Artichauts +8431876012354 EPICERIE Conserves Artichauts +8431876012422 EPICERIE Conserves de Haricots verts +8431876012422 EPICERIE Conserves de Haricots verts +8431876012422 EPICERIE Conserves de Haricots verts +8431876012422 EPICERIE Conserves de Haricots verts +3560070859429 EPICERIE Conserves de Petits pois +3560070859429 EPICERIE Conserves de Petits pois +8431876012422 EPICERIE Conserves de Haricots verts +8431876012422 EPICERIE Conserves de Haricots verts +8431876047356 LIQUIDES Jus de fruits frais et légumes - Pur jus +8431876047356 LIQUIDES Jus de fruits frais et légumes - Pur jus +8431876059366 EPICERIE Conserves Coeur de palmier +8431876059366 EPICERIE Conserves Coeur de palmier +8431876059649 LIQUIDES Jus de fruits frais et légumes - Pur jus +3560070869763 EPICERIE Thés natures +8431876059649 LIQUIDES Jus de fruits frais et légumes - Pur jus +8431876059656 LIQUIDES Jus de fruits frais et légumes - Pur jus +8431876059656 LIQUIDES Jus de fruits frais et légumes - Pur jus +3560070872343 PFT Aide patisserie +3560070872374 PFT Aide patisserie +3560070872435 PRODUITS FRAIS Pates fourrees +3560070872961 PRODUITS FRAIS Salades +3560070874033 EPICERIE Confiserie et chocolats paques +3560070874064 EPICERIE Confiserie et chocolats paques +3560070874095 EPICERIE Confiserie et chocolats paques +3560070874156 EPICERIE Confiserie et chocolats paques +3560070878901 LIQUIDES Vodkas +8431876109634 LIQUIDES Limonades gazéifiées +8431876109634 LIQUIDES Limonades gazéifiées +3560070880805 EPICERIE Bonbons gélifiés +3560070883509 PRODUITS FRAIS Autres pâtes molles +3560070884445 PRODUITS FRAIS Emmentals rapes +3560070884759 PRODUITS FRAIS Desserts - Mousses +3245390230379 LIQUIDES Mousseux d'appellation +3245390238856 LIQUIDES Mousseux d'appellation +3245411155346 PRODUITS FRAIS Légumes cuisines/ Purées / Gratins +3245411167394 EPICERIE Snacks: Produits souffles et extrudes +3245411171193 PRODUITS FRAIS Légumes cuisines/ Purées / Gratins +3245411171230 PRODUITS FRAIS Légumes cuisines/ Purées / Gratins +3245411205621 PRODUITS FRAIS Fromages blanc nature +3245411344450 EPICERIE Cafés solubles +3245411352332 EPICERIE Miels +3245411377816 LIQUIDES Eaux plates aromatisées +3245411386702 PRODUITS FRAIS Beurres Sans sel +3245411386757 PRODUITS FRAIS Beurres Sales +3245411400712 PRODUITS FRAIS Pates fourrees +3245411400729 PRODUITS FRAIS Pates fourrees +3245411430740 EPICERIE Cafés moulus +3245411440114 PRODUITS FRAIS Plats cuisinés surgelés - specialites +3245411441920 LIQUIDES Limonades gazéifiées +3245411442132 PRODUITS FRAIS Légumes cuisines/ Purées / Gratins +3245411442224 PRODUITS FRAIS Légumes cuisines/ Purées / Gratins +3245411442262 PRODUITS FRAIS Légumes cuisines/ Purées / Gratins +3245411458546 EPICERIE Sauces chaudes à base de tomate et tomate frito +3245411480684 EPICERIE Snacks: Produits souffles et extrudes +3245411570576 PRODUITS FRAIS Préparation pommes de terres +3560070887514 PRODUITS FRAIS Raclette +3245411640903 PRODUITS FRAIS Liégeois +3245411640972 PRODUITS FRAIS Liégeois +3245411667979 LIQUIDES Purs Jus de Fruits - Orange +3245411670863 EPICERIE ,Chocolat tablette - blanc,,confiserie blanche, +3245411692834 PRODUITS FRAIS Autres pâtes molles +3245411716622 EPICERIE Conserves - Autres plats cuisines +3245411767006 LIQUIDES Sirops concentrés à base de fruits +3245411815059 EPICERIE Pâtés +3245411815080 EPICERIE Pâtés +3245411815110 EPICERIE Pâtés +3245411815141 PRODUITS FRAIS Entrées +3245411816278 PRODUITS FRAIS Glaces Cones et cornets +3245411849931 EPICERIE Conserves de Thon +3245411849948 EPICERIE Conserves de Thon +3245411863081 LIQUIDES Sirops concentrés - Autres sirops +3245411880170 LIQUIDES Eaux gazeuses aromatisées +3245411884314 LIQUIDES Eaux gazeuses aromatisées +3245411889234 LIQUIDES Eaux plates aromatisées +3245411889241 LIQUIDES Eaux plates aromatisées +3560070888795 PRODUITS FRAIS Fromages blanc aromatises / fruits +3560070888825 PRODUITS FRAIS Fromages blanc aromatises / fruits +3560070888856 PRODUITS FRAIS Fromages blanc aromatises / fruits +3560070888887 PRODUITS FRAIS Fromages blanc aromatises / fruits +3245411901509 LIQUIDES Limonades gazéifiées +3560070889600 LIQUIDES Purs Jus de Fruits - Autres +3560070889600 LIQUIDES Purs Jus de Fruits - Multifruits +3245411901530 LIQUIDES Limonades gazéifiées +3245411901547 LIQUIDES Tonics et Bitter gazéifiées +3245411901578 LIQUIDES Tonics et Bitter gazéifiées +3560070890224 PRODUITS FRAIS Autres pâtes molles +3245411954277 PRODUITS FRAIS Pizzas +3245411955588 PRODUITS FRAIS Pizzas +3245411955618 PRODUITS FRAIS Pizzas +3245412038020 EPICERIE Biscuits sucrés Au chocolat +3245412059124 EPICERIE Cafés moulus +3245412064562 PRODUITS FRAIS Plats cuisinés surgelés - a base de viande +3245412074073 PRODUITS FRAIS Volailles Découpes / Préparations +3245412149085 PRODUITS FRAIS Pizzas +3245412149146 PRODUITS FRAIS Pizzas +3245412149269 PRODUITS FRAIS Pizzas +3245412160059 PRODUITS FRAIS Gateaux glacés à partager +3245412161971 PRODUITS FRAIS Charc.volaille et autre viande +3245412191817 EPICERIE Conserves Plats cuisines base de pates +3245412211348 PRODUITS FRAIS Patisseries et tartes surgelées +3245412217203 PRODUITS FRAIS Yaourts a boire +3245412217517 PRODUITS FRAIS Yaourts a boire +3245412256639 EPICERIE Snacks: Produits souffles et extrudes +3245412303890 PRODUITS FRAIS Salades +3245412305115 EPICERIE Chocolat tablette - fourres +3245412305122 EPICERIE Chocolat tablette - fourres +3245412343810 PRODUITS FRAIS Patisseries industrielles - Madeleines +3245412343988 PRODUITS FRAIS Patisseries industrielles - Madeleines +3245412354724 LIQUIDES Eaux plates aromatisées +3245412379994 EPICERIE Conserves - Autres plats cuisines +3245412404474 PRODUITS FRAIS Dessert patissier +3245412404856 PRODUITS FRAIS Autres produits snacking glacés +3245412414466 PRODUITS FRAIS Plats cuisinés surgelés - a base de viande +3245412416620 EPICERIE ,Gateaux roules,, fourres, +3245412417924 EPICERIE Chocolat tablette - au lait +3245412418020 EPICERIE ,Chocolat tablette - amande,,noisette,,riz, +3245412418136 EPICERIE ,Chocolat patissier,,couverture, +3245412430961 PRODUITS FRAIS Jambons crus +3245412432651 PRODUITS FRAIS Bacon +3245412435263 PRODUITS FRAIS Dessert patissier +3245412438523 LIQUIDES Autres boissons non-gazeifiees Au thé +3245412459139 PRODUITS FRAIS Pates fourrees +3245412476105 PRODUITS FRAIS Pates fourrees +3245412476525 PRODUITS FRAIS Pates fourrees +3245412477430 PRODUITS FRAIS Saumon fumés +3245412477447 PRODUITS FRAIS Saumon fumés +3245412479533 EPICERIE Pâtés +3245412511561 PRODUITS FRAIS Yaourts natures +3245412520549 PRODUITS FRAIS Surimi +3245412542657 EPICERIE Conserves de Sardines +3245412567223 PRODUITS FRAIS Pains de mie élaboré +3245412584800 LIQUIDES Sirops concentrés à base de plantes +3245412584848 LIQUIDES Sirops concentrés à base de plantes +3245412589980 EPICERIE Biscottes +3245412621963 EPICERIE Conserves de Haricots rouges +3245412654497 EPICERIE Cafés en dosettes +3245412654527 EPICERIE Cafés en dosettes +3245412654558 EPICERIE Cafés en dosettes +3245412654589 EPICERIE Cafés en dosettes +3245412694486 PRODUITS FRAIS Pains industriels - Spécialités étrangères +3560070895373 PRODUITS FRAIS Salades +3245412702815 PRODUITS FRAIS Dessert patissier +3245412707254 LIQUIDES Limonades gazéifiées +3245412707261 LIQUIDES Limonades gazéifiées +3245412709371 EPICERIE Conserves de Poires +3245412709661 EPICERIE Conserves de Poires +3245412718687 EPICERIE Potages liquides +3245412718694 EPICERIE Potages liquides +3245412729829 PRODUITS FRAIS Saumon fumés +3245412730252 LIQUIDES Autres fruits gazéifiées +3245412730283 PRODUITS FRAIS Plats cuisinés surgelés - a base de viande +3245412730535 PRODUITS FRAIS Desserts - Mousses +3245412730566 PRODUITS FRAIS Desserts - Mousses +3245412730993 PRODUITS FRAIS Compotes pommes + fruits +3560070899289 EPICERIE ,Gateaux roules,, fourres, +3245412733673 PRODUITS FRAIS Préparation pommes de terres +3245412738142 EPICERIE Desserts a preparer +3245412749438 EPICERIE Produits feuilletes et sables +3245412751561 PRODUITS FRAIS Entrées exotiques +3245412762826 LIQUIDES Cidres +3245412767975 PRODUITS FRAIS Patisseries salees surgelées +3245412776878 PRODUITS FRAIS Plats cuisinés surgelés - a base de viande +3245412776939 PRODUITS FRAIS Plats cuisinés surgelés - a base de pates +3245412777356 PRODUITS FRAIS Plats cuisinés surgelés - a base de pates +3245412778353 PRODUITS FRAIS Plats cuisinés surgelés - poisson/fruit m +3245412826535 EPICERIE Biscuits sucrés Secs +3560070900770 PRODUITS FRAIS Autres fromages fondus +3560070901418 EPICERIE ,Aromes,, colorants,, decors, +3560070901418 EPICERIE Desserts a preparer +3560070901449 EPICERIE ,Aromes,, colorants,, decors, +3245412890987 EPICERIE Compotes pots / coupelles +3245412891168 EPICERIE Compotes pots / coupelles +3245412891175 EPICERIE Compotes pots / coupelles +3245412897993 PRODUITS FRAIS Yaourts aux fruits +3245412898457 PRODUITS FRAIS Salades +3245412901454 EPICERIE Noix de cajou +3245412901485 EPICERIE Cacahuetes +3245412915253 PRODUITS FRAIS ,Patés,, terrines, +3245412918988 PRODUITS FRAIS Yaourts sante et biologique à base de soja +3245412925344 PRODUITS FRAIS Fromages blanc nature +3245412934407 PRODUITS FRAIS Blinis et croutons +3245412934452 PRODUITS FRAIS Préparations à tartiner et rillettes +3245412934841 EPICERIE Huiles de spécialité +3560070903498 PRODUITS FRAIS Fromages blanc aromatises / fruits +3245412937545 EPICERIE Snacks: Produits souffles et extrudes +3245412950872 PRODUITS FRAIS Pains précuits +3245412955389 PRODUITS FRAIS Pains précuits +3245412956355 PRODUITS FRAIS Préparations à tartiner et rillettes +3245412956515 PRODUITS FRAIS Préparations à tartiner et rillettes +3245412961113 PRODUITS FRAIS Poissons non fumés +3245412966156 EPICERIE Autres produits apéritifs +3245412969683 PRODUITS FRAIS ,Quiches,, tartes,, tourtes surgelées, +3560070906369 PRODUITS FRAIS Fromages blanc aromatises / fruits +3245412975462 EPICERIE Cafés en dosettes +3245412991349 PRODUITS FRAIS Autre Charcuterie à cuire +3245412993909 EPICERIE Conserves Autres fruits +3245412997846 PRODUITS FRAIS Autres pains industriels +3245412997853 PRODUITS FRAIS Autres pains industriels +3245413058881 EPICERIE Biscuits sucrés Au chocolat +3245413136527 EPICERIE Semoules de ble / Couscous +3245413153647 PRODUITS FRAIS Autres poissons fumés +3245413192257 EPICERIE Cafés en dosettes +3245413200198 EPICERIE Biscuits sucrés Au chocolat +3245413243324 EPICERIE Autres farines +3245413243355 EPICERIE Autres farines +3245413419996 EPICERIE Levures +3245413439512 PRODUITS FRAIS Yaourts sante et biologique aux fruits +3245413444790 PRODUITS FRAIS Autres saucisses +3245413476296 PRODUITS FRAIS Patisseries salees surgelées +3245413487063 PRODUITS FRAIS Autres produits surgelés +3245413487919 EPICERIE Compotes pots / coupelles +3245413488244 PRODUITS FRAIS ,Patés,, terrines, +3245413489876 PRODUITS FRAIS ,Patés,, terrines, +3245413505682 EPICERIE Sauces chaudes - pâtes - riz +3245413506627 PRODUITS FRAIS ,Patés,, terrines, +3245413531605 EPICERIE Produits diététiques Barres de substitution +3245413531681 EPICERIE Produits diététiques Barres de substitution +3245413562722 PRODUITS FRAIS Foie gras +3245413563040 EPICERIE Laits en poudre +3245413588036 PRODUITS FRAIS ,Quiches,, tartes,, tourtes surgelées, +3245413588241 PRODUITS FRAIS Plat cuis./préparé avec viande +3245413693365 PRODUITS FRAIS Yaourts sante et biologique à base de soja +3560070909520 PRODUITS FRAIS Assiette apéritif tranche +3560070910366 EPICERIE Huiles Olive +3560070910366 EPICERIE Huiles Olive +3560070910366 EPICERIE Huiles Olive +3245413730169 EPICERIE ,Aides culinaires,, boillons solides et court bouillon, +3245413780270 PRODUITS FRAIS Préparations à tartiner et rillettes +3245413808196 EPICERIE Sauces chaudes - pâtes - riz +3245413812254 PRODUITS FRAIS Liégeois +3245413812261 PRODUITS FRAIS Liégeois +3245413812292 PRODUITS FRAIS Liégeois +3245413812322 PRODUITS FRAIS Liégeois +3245413814449 PRODUITS FRAIS Yaourts aux fruits +3245413824837 PRODUITS FRAIS Pain de mie standard +3245413824899 PRODUITS FRAIS Pizzas +3245413832719 PRODUITS FRAIS Plat cuis./préparé avec viande +3245413834089 PRODUITS FRAIS Plat cuis./préparé avec viande +3245413839602 EPICERIE Sauces chaudes - viandes - poissons +3245413852540 LIQUIDES Jus de fruits frais et légumes - Pur jus +3245413852717 PRODUITS FRAIS Panettone/brioche/prd tranche +3245413857026 PRODUITS FRAIS Rillettes +3245413857064 PRODUITS FRAIS Pains précuits +3245413865151 PRODUITS FRAIS Salades +3245413870018 PRODUITS FRAIS Patisseries et tartes surgelées +3245413870056 PRODUITS FRAIS Patisseries et tartes surgelées +3245413913128 EPICERIE Moutardes +3245413924384 PRODUITS FRAIS Salades +3245413949660 PRODUITS FRAIS Plats cuisinés surgelés - a base de viande +3560070915231 EPICERIE Confiserie et chocolats noel +3560070915446 EPICERIE Confiserie et chocolats noel +3560070915507 EPICERIE Confiserie et chocolats noel +3245413955470 EPICERIE Conserves - Autres plats cuisines +3245413965547 EPICERIE Conserves Plats cuisines base de pates +3245413984418 PRODUITS FRAIS Plats cuisinés surgelés - a base de viande +3245414007413 PRODUITS FRAIS Plats cuisinés surgelés - a base de pates +3245414072657 PRODUITS FRAIS Plats cuisinés surgelés - poisson/fruit m +3245414076440 PRODUITS FRAIS Crêpes et galettes salées surgelées +3560070917051 PRODUITS FRAIS Crèmes dessert +3245414079113 PRODUITS FRAIS Saumon fumés +3245414079175 PRODUITS FRAIS Saumon fumés +3560070917631 EPICERIE Conserves de Thon +3560070917631 EPICERIE Conserves de Thon +3560070917662 EPICERIE Conserves de Thon +3560070917662 EPICERIE Conserves de Thon +3245414094642 PRODUITS FRAIS Mélanges de legumes/garniture surgelés +3560070918416 LIQUIDES Cognacs +3245414094741 PRODUITS FRAIS Légumes cuisines/ Purées / Gratins +3245414096455 EPICERIE Biscuits sucrés Secs +3245414098756 PRODUITS FRAIS Fromages blanc nature +3245414113190 PRODUITS FRAIS Salades +3245414113404 PRODUITS FRAIS Salades +3245414113442 PRODUITS FRAIS Salades +3245414113459 PRODUITS FRAIS Salades +3245414117259 PRODUITS FRAIS Compotes pommes + fruits +3245414117457 PRODUITS FRAIS Compotes pommes + fruits +3245414143081 EPICERIE Cafés moulus +3245414144705 PRODUITS FRAIS Crêpes et galettes salées surgelées +3560070920235 EPICERIE Confiserie de chocolat +3245414146440 EPICERIE Biscuits sucrés Aux fruits +3245414164086 EPICERIE Conserves Plats cuisines base de viande +3245414164093 EPICERIE Conserves Plats cuisines base de viande +3245414164123 EPICERIE Conserves Plats cuisines base de viande +3560070924073 EPICERIE Riz étuvés +3245414172081 EPICERIE Cafés moulus +3245414174221 PRODUITS FRAIS Patisseries industrielles - Madeleines +3245414174238 PRODUITS FRAIS Patisseries industrielles - Madeleines +3245414189188 PRODUITS FRAIS Foie gras +3245414228740 LIQUIDES Eaux plates Bouteille plastique +3245414228764 LIQUIDES Eaux plates Bouteille plastique +3245414228900 LIQUIDES Eaux plates Bouteille plastique +3245414228948 LIQUIDES Eaux plates Bouteille plastique +3245414229297 PRODUITS FRAIS Autre Charcuterie à cuire +3245414241701 LIQUIDES Rhums blancs +3245414249950 EPICERIE Cafés en dosettes +3245414250772 PRODUITS FRAIS Panettone/brioche/prd tranche +3245414376625 EPICERIE Sauces chaudes - pâtes - riz +3245414393899 EPICERIE Cafés en dosettes +3245414394155 EPICERIE Cafés en dosettes +3245414456341 PRODUITS FRAIS ,Brioche,, buns,, specialite individuelle, +3245414469426 LIQUIDES Eaux plates Bouteille plastique +3560070927807 EPICERIE Produits diététiques Autres salés +3560070927807 EPICERIE Produits diététiques Autres salés +3245414469433 LIQUIDES Eaux plates Bouteille plastique +3245414480322 EPICERIE Autres condiments +3245414604803 EPICERIE Cafés en grains +3245414605183 EPICERIE Cafés en grains +3245414620087 EPICERIE Compotes boîtes et bocales +3245414620131 EPICERIE Compotes boîtes et bocales +3245414620148 EPICERIE Compotes boîtes et bocales +3245414658769 PRODUITS FRAIS Dessert patissier +3245414663497 PRODUITS FRAIS Autres saucisses +3245414664869 PRODUITS FRAIS Autres produits surgelés +3270190005230 LIQUIDES Tonics et Bitter gazéifiées +3270190005261 LIQUIDES Autres fruits gazéifiées +3270190005834 EPICERIE Cafés moulus +3560070929238 EPICERIE Produits diététiques Autres sucrés +3270190006947 LIQUIDES Sirops concentrés autres fruits +3270190006985 LIQUIDES Sirops concentrés - Conc. d agrumes +3270190006992 LIQUIDES Sirops concentrés à base de plantes +3270190007005 LIQUIDES Sirops concentrés à base de fruits +3270190007418 EPICERIE Petits pains type suédois +3270190007425 EPICERIE Petits pains type suédois +3270190007906 EPICERIE Cafés moulus +3270190007920 EPICERIE Cafés moulus +3270190007937 EPICERIE Cafés moulus +3270190007951 EPICERIE Cafés moulus +3270190010685 PRODUITS FRAIS Poissons surgelés et preparations panee +3270190020059 PRODUITS FRAIS Laits longue conservation natu +3270190020080 PRODUITS FRAIS Corps gras de cuisine +3270190020417 PRODUITS FRAIS Préparation pommes de terres +3560070931019 PRODUITS FRAIS Fromages blanc aromatises / fruits +3270190020554 PRODUITS FRAIS Corps gras a tartiner +3270190020646 PRODUITS FRAIS Mélanges de legumes/garniture surgelés +3270190020653 PRODUITS FRAIS Mélanges de legumes/garniture surgelés +3270190020677 PRODUITS FRAIS Rillettes +3270190020684 PRODUITS FRAIS Rillettes +3270190020929 PRODUITS FRAIS Yaourts natures +3560070931415 EPICERIE Bonbons gélifiés +3270190020981 PRODUITS FRAIS Fromages blanc nature +3270190021049 PRODUITS FRAIS Préparation pommes de terres +3270190021056 PRODUITS FRAIS Laits longue conservation natu +3560070932429 EPICERIE Biscuits sucrés Secs +3270190021070 PRODUITS FRAIS Pain de mie standard +3270190021100 PRODUITS FRAIS Crêpes et galettes salées surgelées +3270190021162 PRODUITS FRAIS Laits longue conservation natu +3270190022626 PRODUITS FRAIS Bacs Crèmes Glacées +3270190022855 PRODUITS FRAIS Corps gras de cuisine +3270190023135 PRODUITS FRAIS Crèmes dessert +3270190023142 PRODUITS FRAIS Crèmes dessert +3560070934881 PRODUITS FRAIS Jambons crus +3270190023302 PRODUITS FRAIS Yaourts aux fruits +3560070936106 EPICERIE Biscuits sucrés Au chocolat +3560070936137 EPICERIE Biscuits sucrés Au chocolat +3270190023401 PRODUITS FRAIS Bacs Crèmes Glacées +3560070936649 PRODUITS FRAIS Jambons crus +3560070936847 PRODUITS FRAIS Yaourts sante et biologique aromatisé +3560070937059 EPICERIE Mayonnaise +3270190023524 PRODUITS FRAIS Fromages blanc allegés +3270190023548 PRODUITS FRAIS Fromages blanc nature +3270190023562 PRODUITS FRAIS Poissons surgelés et preparations panee +3270190023814 PRODUITS FRAIS Yaourts natures +3270190023821 PRODUITS FRAIS Yaourts natures +3270190024484 PRODUITS FRAIS Crêpes et galettes salées surgelées +3270190025153 PRODUITS FRAIS Charcuterie tranchée autres +3270190025276 PRODUITS FRAIS Saumon fumés +3270190025535 PRODUITS FRAIS Crèmes fouettées aerosols +3270190025542 PRODUITS FRAIS Crèmes fouettées aerosols +3270190025641 PRODUITS FRAIS Préparations à tartiner et rillettes +3270190025658 PRODUITS FRAIS Préparations à tartiner et rillettes +3270190025962 LIQUIDES Jus de fruits frais et légumes - Pur jus +3270190026082 PRODUITS FRAIS Autres pâtes molles +3560070939114 PRODUITS FRAIS Autres pâtes molles +3560070939114 PRODUITS FRAIS Autres pâtes molles +3560070939244 EPICERIE Produits diététiques Autres salés +3560070939275 EPICERIE Produits diététiques Autres salés +3270190026471 PRODUITS FRAIS Fromages blanc aromatises / fruits +3560070939404 EPICERIE Autres Aliments infantiles hors lait +3560070939435 EPICERIE Autres Aliments infantiles hors lait +3270190026679 PRODUITS FRAIS Mélanges de legumes/garniture surgelés +3270190026709 PRODUITS FRAIS Plats cuisinés surgelés - a base de pates +3270190026716 PRODUITS FRAIS Plats cuisinés surgelés - a base de volaile +3270190026761 PRODUITS FRAIS Préparations à tartiner et rillettes +3270190026815 PRODUITS FRAIS Yaourts aromatises +3270190027447 PRODUITS FRAIS Crèmes longue conservation +3270190028505 PRODUITS FRAIS Autres produits traiteur frais +3560070941346 EPICERIE Huiles Olive +3560070941346 EPICERIE Huiles Olive +3560070941346 EPICERIE Huiles Olive +3270190112266 EPICERIE Biscuits sucrés Au chocolat +3270190113508 LIQUIDES Eaux plates Bouteille plastique +3270190114123 LIQUIDES Eaux plates Bouteille plastique +3270190115045 EPICERIE Cafés moulus +3270190115113 EPICERIE Conserves de Tomates concassées +3270190116912 LIQUIDES Eaux plates Bouteille plastique +3560070941933 EPICERIE Barres chocolatees +3270190116929 LIQUIDES Eaux plates Bouteille plastique +3270190117964 EPICERIE Cafés moulus +3270190117971 EPICERIE Cafés moulus +3270190118145 EPICERIE Cacahuetes +3270190118749 EPICERIE Snacks: Produits souffles et extrudes +3560070942718 EPICERIE Cacahuetes +3270190118756 EPICERIE Snacks: Produits souffles et extrudes +3560070943678 PRODUITS FRAIS Yaourts sante et biologique aux fruits +3270190119067 EPICERIE Noix de cajou +3270190119500 EPICERIE Cafés moulus +3270190119517 EPICERIE Cafés moulus +3270190121503 EPICERIE Miels +3560070944255 PRODUITS FRAIS Autres saucisses +3270190121909 EPICERIE Moutardes +3270190122852 EPICERIE Biscuits sucrés Secs +3270190122975 EPICERIE Autres céréales +3560070945252 PRODUITS FRAIS Charc.volaille et autre viande +3270190124528 EPICERIE Bonbons gélifiés +3270190124924 EPICERIE Moutardes +3270190125860 EPICERIE Biscuits sucrés Au chocolat +3270190125990 EPICERIE Biscuits sucrés Au chocolat +3270190128632 EPICERIE Cafés moulus +3270190129134 EPICERIE Bonbons gélifiés +3270190130697 EPICERIE Infusions classiques +3270190130703 EPICERIE Infusions classiques +3270190138396 EPICERIE Biscuits sucrés Au chocolat +3270190149316 LIQUIDES Autres boissons non-gazeifiees Aux fruits +3270190150596 EPICERIE Thés parfumés +3270190152972 EPICERIE Autres produits apéritifs +3270190153085 EPICERIE Infusions classiques +3270190156833 EPICERIE Autres chocolats tablettes +3270190164296 EPICERIE Conserves Plats cuisines base de viande +3270190164302 EPICERIE Conserves Plats cuisines base de viande +3270190171041 LIQUIDES Eaux plates Bouteille plastique +3270190171058 LIQUIDES Eaux plates Bouteille plastique +3270190171430 EPICERIE Infusions classiques +3270190171706 EPICERIE Compotes pots / coupelles +3560070948284 PRODUITS FRAIS Saucisses de strasbourg +3270190175216 EPICERIE Cacahuetes +3270190177555 EPICERIE Sauces chaudes - viandes - poissons +3270190177579 EPICERIE Sauces chaudes - viandes - poissons +3270190177715 EPICERIE Conserves de Sardines +3270190177722 EPICERIE Conserves de Sardines +3270190178057 EPICERIE Autre pdt confiserie de sucre +3270190178071 EPICERIE Cafés en grains +3270190178088 LIQUIDES Eaux plates Bouteille plastique +3270190178095 LIQUIDES Eaux plates Bouteille plastique +3270190178101 LIQUIDES Eaux plates Bouteille plastique +3270190178118 LIQUIDES Eaux plates Bouteille plastique +3270190178279 EPICERIE Pochon humide chat +3270190178286 EPICERIE Pochon humide chat +3270190178293 EPICERIE Pochon humide chat +3270190178538 EPICERIE Conserves Asperges +3560070949533 PRODUITS FRAIS Saumon fumés +3270190178866 EPICERIE Biscuits sucrés Fourres +3270190180890 EPICERIE ,Chocolat tablette - blanc,,confiserie blanche, +3270190181460 EPICERIE Boissons chocolatées instantanées +3270190181477 EPICERIE Boissons chocolatées instantanées +3270190185239 EPICERIE Conserves de Thon +3270190185611 EPICERIE Conserves de mais +3270190185772 EPICERIE Conserves de Thon +3560070950881 EPICERIE Conserves de Poires +3560070951000 EPICERIE Confiserie et chocolats paques +3560070951031 EPICERIE Confiserie et chocolats paques +3560070951062 EPICERIE Confiserie et chocolats paques +3560070951987 PRODUITS FRAIS Yaourts a boire +3560070952014 PRODUITS FRAIS Yaourts a boire +3560070952045 PRODUITS FRAIS Yaourts a boire +3270190191629 LIQUIDES Eaux plates Bouteille plastique +3270190194415 EPICERIE Pochon humide chat +3270190194569 EPICERIE Pochon humide chat +3270190194576 EPICERIE Pochon humide chat +3270190197867 EPICERIE Biscottes +3560070953028 PRODUITS FRAIS Sandwichs +3560070953080 PRODUITS FRAIS Sandwichs +3560070953110 PRODUITS FRAIS Sandwichs +3560070953141 PRODUITS FRAIS Sandwichs +3270190199960 PRODUITS FRAIS Jambons crus +3270190203353 PRODUITS FRAIS Jambons crus +3270190203407 PRODUITS FRAIS Charc.volaille et autre viande +3270190203421 PRODUITS FRAIS ,Patés,, terrines, +3560070954421 PRODUITS FRAIS Fromage hollandais +3560070954452 PRODUITS FRAIS Fromage hollandais +3270190203438 PRODUITS FRAIS ,Patés,, terrines, +3270190203445 PRODUITS FRAIS ,Patés,, terrines, +3270190203629 PRODUITS FRAIS Charc.volaille et autre viande +3270190203636 PRODUITS FRAIS Charc.volaille et autre viande +3270190204961 PRODUITS FRAIS Entrées +3270190207474 PRODUITS FRAIS Salades +3270190207481 PRODUITS FRAIS Salades +3270190207504 PRODUITS FRAIS Salades +3270190207511 PRODUITS FRAIS Salades +3270190207535 PRODUITS FRAIS Salades +3270190207542 PRODUITS FRAIS Salades +3560070956159 PRODUITS FRAIS ,Patés,, terrines, +3270190207573 PRODUITS FRAIS Corps gras de cuisine +3270190207740 PRODUITS FRAIS Roquefort +3270190207757 PRODUITS FRAIS Gateaux glacés à partager +3270190207832 PRODUITS FRAIS Glaces Pots et coupelles +3270190207887 PRODUITS FRAIS Patisseries industrielles - Madeleines +3270190207924 PRODUITS FRAIS Panettone/brioche/prd tranche +3270190208020 PRODUITS FRAIS Poissons surgelés et preparations panee +3270190208235 PRODUITS FRAIS Libre service - Produits carnes prepares +3270190208624 PRODUITS FRAIS Saucissons cuits +3270190208631 PRODUITS FRAIS Saucissons cuits +3270190208693 PRODUITS FRAIS Saucissons cuits +3270190208990 PRODUITS FRAIS Corps gras a tartiner +3270190210542 PRODUITS FRAIS Fromages blanc allegés +3270190212980 PRODUITS FRAIS Salades +3270190213062 PRODUITS FRAIS Champignons surgelés +3270190213321 PRODUITS FRAIS Plats cuisinés surgelés - a base de viande +3270190216032 PRODUITS FRAIS ,Quiches,, tartes,, tourtes surgelées, +3270190216780 PRODUITS FRAIS Liégeois +3270190216797 PRODUITS FRAIS Liégeois +3270190216810 PRODUITS FRAIS Autres desserts +3270190216827 PRODUITS FRAIS Autres desserts +3270190217633 PRODUITS FRAIS Glaces Cones et cornets +3270190217640 PRODUITS FRAIS Glaces Cones et cornets +3270190217671 PRODUITS FRAIS Glaces Cones et cornets +3560070959686 PRODUITS FRAIS Pates à tarte fraiches +3560070959686 PRODUITS FRAIS Pates à tarte fraiches +3560070959686 PRODUITS FRAIS Pates à tarte fraiches +3560070959686 PRODUITS FRAIS Pates à tarte fraiches +3560070959716 PRODUITS FRAIS Pates à tarte fraiches +3560070959716 PRODUITS FRAIS Pates à tarte fraiches +3560070959716 PRODUITS FRAIS Pates à tarte fraiches +3270190218241 PRODUITS FRAIS Plat cuis./prépar.avec poisson +3270190218647 PRODUITS FRAIS Charc.volaille et autre viande +3270190250418 PRODUITS FRAIS Produits exotiques +3560070961887 PRODUITS FRAIS Spec.sucree dont crepe gauffre +3270190253112 PRODUITS FRAIS Plat cuis./prépar.pate légume +3270190256076 PRODUITS FRAIS Plat cuis./prépar.pate légume +3270190265238 PRODUITS FRAIS Libre service - Produits carnes prepares +3270190265436 PRODUITS FRAIS Libre service - Produits carnes prepares +3560070962334 EPICERIE Miels +3560070962365 EPICERIE Miels +3560070962396 EPICERIE Miels +3560070962426 EPICERIE Miels +3560070962457 EPICERIE Miels +3270190696674 EPICERIE Minerale +3560070962723 PRODUITS FRAIS Traiteur sucré +3560070963775 EPICERIE Produits diététiques Autres sucrés +3270190696711 EPICERIE Désodorisants +3560070964529 PRODUITS FRAIS Autres découpes de porc +3270190696735 EPICERIE Désodorisants +3390507803462 EPICERIE Agglomerante +3560070015016 PRODUITS FRAIS Frites surgelées +3560070015757 EPICERIE Boite individuelle humide chat +3560070015801 EPICERIE Boite individuelle humide chat +3560070015832 EPICERIE Boite individuelle humide chat +3560070015856 EPICERIE Boite individuelle humide chat +3560070015863 EPICERIE Boite individuelle humide chat +3560070015870 EPICERIE Boite individuelle humide chat +3560070015900 EPICERIE Boite individuelle humide chat +3560070016389 EPICERIE Boite individuelle humide chat +3560070016419 EPICERIE Boite individuelle humide chat +3560070016433 EPICERIE Barquette humide chat +3560070016464 EPICERIE Barquette humide chat +3560070966639 EPICERIE Compotes gourdes +3560070966639 EPICERIE Compotes gourdes +3560070966684 EPICERIE Compotes gourdes +3560070966738 EPICERIE Compotes gourdes +3560070966738 EPICERIE Compotes gourdes +3560070966783 EPICERIE Compotes gourdes +3560070966882 EPICERIE Compotes gourdes +3560070966936 EPICERIE Compotes gourdes +3560070966936 EPICERIE Compotes gourdes +3560070967261 EPICERIE Compotes gourdes +3560070017171 EPICERIE Conserves d'Ananas +3560070017461 EPICERIE Conserves de Thon +3560070967636 EPICERIE Produits diététiques A base de soja +3560070967667 EPICERIE Produits diététiques Autres sucrés +3560070018338 EPICERIE Cafés solubles +3560070018369 EPICERIE Mueslis +3560070018611 LIQUIDES Autres boissons non-gazeifiees Au thé +3560070018741 EPICERIE Ketchup +3560070026142 LIQUIDES Autres boissons non-gazeifiees Au thé +3560070026418 PRODUITS FRAIS Préparation pommes de terres +3560070028054 PRODUITS FRAIS Préparation pommes de terres +3560070043699 EPICERIE Conserves d'Ananas +3560070047499 EPICERIE Conserves de mais +3560070048335 PRODUITS FRAIS Glaces Cones et cornets +3560070048427 PRODUITS FRAIS Glaces Cones et cornets +3560070048755 EPICERIE Biscuits sucrés Secs +3560070049110 EPICERIE ,Chocolat patissier,,couverture, +3560070054763 PRODUITS FRAIS Fromage fondu type tranchette +3560070971343 EPICERIE Compotes gourdes +3560070971374 EPICERIE Compotes gourdes +3560070971404 EPICERIE Compotes gourdes +3560070054824 PRODUITS FRAIS Fromage fondu type tranchette +3560070054978 EPICERIE Pochon humide chat +3560070971633 PRODUITS FRAIS Yaourts sante et biologique aux fruits +3560070971756 PRODUITS FRAIS Yaourts sante et biologique à base de soja +3560070971787 PRODUITS FRAIS Yaourts sante et biologique à base de soja +3560070971817 PRODUITS FRAIS Yaourts sante et biologique à base de soja +3560070100248 LIQUIDES Autres boissons non-gazeifiees Aux fruits +3560070103010 EPICERIE Friandise chien +3560070103041 EPICERIE Friandise chien +3560070103294 LIQUIDES Limonades gazéifiées +3560070105908 EPICERIE Olives farcies +3560070108442 PRODUITS FRAIS Fromage hollandais +3560070108589 EPICERIE Biscuits sucrés Secs +3560070109920 PRODUITS FRAIS Fromages frais aromatises +3560070110759 EPICERIE ,Gateaux roules,, fourres, +3560070111251 EPICERIE ,Gateaux roules,, fourres, +3560070111817 PRODUITS FRAIS Poissons surgelés et preparations panee +3560070112975 EPICERIE ,Chocolat patissier,,couverture, +3560070113392 PRODUITS FRAIS Fromage hollandais +3560070113453 PRODUITS FRAIS Fromage hollandais +3560070113637 EPICERIE Barquette humide chat +3560070113743 EPICERIE Barquette humide chat +3560070115211 EPICERIE Conserves Coeur de palmier +3560070975457 PFT Crudite Composee +3560070117659 EPICERIE Boite individuelle humide chat +3560070117987 PRODUITS FRAIS Crèmes fouettées aerosols +3560070119790 EPICERIE Barquette humide chat +3560070119820 EPICERIE Barquette humide chat +3560070976140 EPICERIE Pâtés +3560070120451 PRODUITS FRAIS Préparation pommes de terres +3560070121182 EPICERIE Miels +3560070123421 EPICERIE Boite individuelle humide chat +3560070123452 EPICERIE Boite individuelle humide chat +3560070123520 EPICERIE Boite individuelle humide chat +3560070123858 PRODUITS FRAIS Frites surgelées +3560070124879 PRODUITS FRAIS Pizzas surgelées - Cuite sur pierre +3560070125678 EPICERIE Boite individuelle humide chat +3560070125869 EPICERIE Friandise chien +3560070976867 PRODUITS FRAIS Patisseries industrielles individuelles +3560070130047 PRODUITS FRAIS Nuggets +3560070131846 EPICERIE Corn flakes +3560070132645 EPICERIE Autres céréales +3560070979493 EPICERIE Compotes gourdes +3560070981427 EPICERIE Confiserie et chocolats noel +3560070981519 EPICERIE Confiserie et chocolats noel +3560070981793 EPICERIE Conserves de Maquereaux +3560070139910 PRODUITS FRAIS Légumes verts surgelés +3560070140060 PRODUITS FRAIS Mélanges de legumes/garniture surgelés +3560070140152 PRODUITS FRAIS Autres legumes surgelés +3560070140244 PRODUITS FRAIS Légumes verts surgelés +3560070140398 PRODUITS FRAIS Légumes cuisines/ Purées / Gratins +3560070983186 EPICERIE Biscuits sucrés Secs +3560070983216 EPICERIE Biscuits sucrés Secs +3560070142224 EPICERIE Cacahuetes +3560070983308 EPICERIE Biscuits sucrés Aux fruits +3560070143085 PRODUITS FRAIS Frites surgelées +3560070149155 PRODUITS FRAIS Légumes verts surgelés +3560070149278 PRODUITS FRAIS Fromages frais - Féta +3560070151691 EPICERIE Autres céréales +3560070984350 EPICERIE Biscuits sucrés Au chocolat +3560070152681 LIQUIDES Bières Panaches +3560070985159 EPICERIE Confiserie de chocolat +3560070152704 LIQUIDES Bières Panaches +3560070152889 PRODUITS FRAIS Bacs Crèmes Glacées +3560070988051 EPICERIE Barres chocolatees +3560070156740 PRODUITS FRAIS Légumes verts surgelés +3560070156771 PRODUITS FRAIS Légumes verts surgelés +3560070158300 PRODUITS FRAIS Légumes verts surgelés +3560070159260 EPICERIE Riz prêt à l'emploi +3560070161706 EPICERIE Conserves de Thon +3560070166046 EPICERIE Riz prêt à l'emploi +3560070166343 PRODUITS FRAIS Fromage fondu type tranchette +3560070167593 PRODUITS FRAIS Autres Poissons surgelés +3560070173921 PRODUITS FRAIS Crèmes longue conservation +3560070991464 PRODUITS FRAIS Libre service - Autres volailles +3560070993116 EPICERIE Mayonnaise +3560070993178 EPICERIE Sauces froides +3560070993239 EPICERIE Sauces froides +3560070178032 EPICERIE Epices et herbes +3560070178131 EPICERIE Epices et herbes +3560070995875 PRODUITS FRAIS Autres Plats cuisinés surgelés +3560070996414 LIQUIDES Autres boissons non-gazeifiees Aux fruits +3560070996445 LIQUIDES Autres boissons non-gazeifiees Aux fruits +3560070997572 PRODUITS FRAIS Salades +3560070997664 PRODUITS FRAIS Salades +3560070181933 EPICERIE Conserves de Haricots blancs sauce tomate +3560070182152 PRODUITS FRAIS Légumes cuisines/ Purées / Gratins +3560070998609 PRODUITS FRAIS Autres produits traiteur frais +3560070998630 PRODUITS FRAIS Autres produits traiteur frais +3560070998692 PRODUITS FRAIS Autres produits traiteur frais +3560070998753 PRODUITS FRAIS Autres produits traiteur frais +3560070998784 PRODUITS FRAIS Autres produits traiteur frais +3560070183623 PRODUITS FRAIS Baies et fruits entiers surgelés +3560070183654 PRODUITS FRAIS Baies et fruits entiers surgelés +3560070185559 PRODUITS FRAIS Légumes verts surgelés +3560071000035 EPICERIE Conserves de Thon +3560071000035 EPICERIE Conserves de Thon +3560070187331 PRODUITS FRAIS Fromages frais - Féta +3560070202522 PRODUITS FRAIS Pizzas surgelées - Cuite sur pierre +3560070203895 EPICERIE Conserves Asperges +3560070204342 EPICERIE Conserves Autres fruits +3560070207794 PRODUITS FRAIS Glaces Cones et cornets +3560071000219 EPICERIE Thés parfumés +3560071000226 EPICERIE Thés parfumés +3560071000233 EPICERIE Thés parfumés +3560071000295 LIQUIDES Sirops concentrés à base de plantes +3560071000301 LIQUIDES Sirops concentrés à base de fruits +3560070215980 EPICERIE Sec chat +3560070218295 EPICERIE Potages liquides +3560070219421 PRODUITS FRAIS Emmentals blocs +3560070220670 EPICERIE Miels +3560070220700 EPICERIE Miels +3560070221912 EPICERIE Biscuits sucrés Secs +3560070223145 EPICERIE Pistaches +3560070224371 EPICERIE Friandise chien +3560070226061 LIQUIDES Bières Panaches +3560070227556 EPICERIE Biscuits sucrés Au chocolat +3560070230525 EPICERIE Infusions classiques +3560071001056 EPICERIE Miels +3560070230556 EPICERIE Thés parfumés +3560070230778 EPICERIE Thés natures +3560070232963 EPICERIE Infusions classiques +3560070234479 EPICERIE Ketchup +3560070240258 EPICERIE Crackers +3560070242610 EPICERIE Thés natures +3560070242757 PRODUITS FRAIS Mélanges de legumes/garniture surgelés +3560070246151 PRODUITS FRAIS Corps gras a tartiner +3560070247530 PRODUITS FRAIS Fromage hollandais +3560070251827 PRODUITS FRAIS Corps gras de cuisine +3560070252268 EPICERIE Autres céréales +3560070254040 LIQUIDES Autres fruits gazéifiées +3560070254699 EPICERIE Crackers +3560070257393 PRODUITS FRAIS Fromages frais aromatises +3560071001445 EPICERIE Cafés en dosettes +3560071001452 EPICERIE Cafés en dosettes +3560071001469 EPICERIE Cafés en dosettes +3560071001476 EPICERIE Cafés en dosettes +3560071001483 EPICERIE Cafés en dosettes +3560071001490 EPICERIE Cafés en dosettes +3560070257461 EPICERIE Conserves de Tomates - Concentré +3560070258819 PRODUITS FRAIS Bacs Crèmes Glacées +3560070258963 PRODUITS FRAIS Glaces Cones et cornets +3560070259564 PRODUITS FRAIS Autres préparations de fruits surgelés +3560070260614 LIQUIDES Autres fruits gazéifiées +3560070260799 EPICERIE Friandise chien +3560070261369 PRODUITS FRAIS Bacs Crèmes Glacées +3560070262229 LIQUIDES Autres boissons non-gazeifiees Aux fruits +3560070262250 EPICERIE Conserves de Sardines +3560070262595 PRODUITS FRAIS Préparation pommes de terres +3560070263103 EPICERIE Mayonnaise +3560070264124 EPICERIE Betterave +3560070266685 PRODUITS FRAIS Fromages frais aromatises +3560070267927 EPICERIE Snacks: Produits souffles et extrudes +3560070268030 EPICERIE Sauces chaudes à base de tomate et tomate frito +3560070269280 LIQUIDES Bières Panaches +3560070269297 LIQUIDES Bières Panaches +3560070269921 PRODUITS FRAIS Crèmes longue conservation +3560070269952 PRODUITS FRAIS Crèmes longue conservation +3560070272099 EPICERIE Conserves de poissons tartinables +3560070272129 EPICERIE Conserves de poissons tartinables +3560070274024 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560070274208 PRODUITS FRAIS Calamar/encornet/poulpe/seches surgelés +3560070274239 PRODUITS FRAIS Calamar/encornet/poulpe/seches surgelés +3560070274352 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560070275236 LIQUIDES Purs Jus de Fruits - Autres +3560070276110 PRODUITS FRAIS Frites surgelées +3560070277315 EPICERIE Cafés solubles +3560070279227 EPICERIE Miels +3560070279524 EPICERIE Potages liquides +3560070279678 EPICERIE Autres légumes +3560070280902 EPICERIE Infusions classiques +3560070284351 PRODUITS FRAIS Fromage fondu type vqr +3560070285532 EPICERIE Conserves de Haricots verts cueillis et rangés main +3560071003104 PRODUITS FRAIS Desserts - Mousses +3560071003111 PRODUITS FRAIS Dessert patissier +3560070302291 EPICERIE Conserves de Haricots verts +3560070308460 EPICERIE Epinards +3560070308606 EPICERIE Conserves Coeur de palmier +3560070309542 EPICERIE Sauces chaudes à base de tomate et tomate frito +3560071003272 PRODUITS FRAIS Saucissons cuits +3560071003289 PRODUITS FRAIS Saucissons cuits +3560071003296 PRODUITS FRAIS Saucissons cuits +3560071003302 PRODUITS FRAIS Saucissons cuits +3560070310890 EPICERIE Pommes de terre +3560070310920 EPICERIE Betterave +3560070317790 PRODUITS FRAIS Préparation pommes de terres +3560070319961 EPICERIE Cafés solubles +3560070320868 EPICERIE Confiserie de chocolat +3560070320899 EPICERIE Confiserie de chocolat +3560071003456 PRODUITS FRAIS Autres produits surgelés +3560070321032 PRODUITS FRAIS Légumes cuisines/ Purées / Gratins +3560070321216 PRODUITS FRAIS Herbes et assaisonnements surgelés +3560070322015 EPICERIE Conserves de Sardines +3560070322749 PRODUITS FRAIS Champignons surgelés +3560070322879 EPICERIE Conserves de Petits pois +3560070323661 PRODUITS FRAIS Pates pressées non cuites +3560070325580 EPICERIE Pâtes alimentaires prêtes à l'emploi +3560071003883 PRODUITS FRAIS Autres fromages frais +3560070325979 EPICERIE Conserves de Thon +3560070327805 PRODUITS FRAIS Mélanges de legumes/garniture surgelés +3560070328031 EPICERIE Conserves de Tomates pelées +3560070328062 EPICERIE Potages liquides +3560070329410 EPICERIE Conserves de Pois chiches +3560070329472 EPICERIE Conserves de Lentilles +3560070331642 EPICERIE Autres mélanges de légumes +3560070331673 EPICERIE Autres mélanges de légumes +3560070331703 EPICERIE Autres mélanges de légumes +3560070335541 PRODUITS FRAIS Bacs Crèmes Glacées +3560070335879 PRODUITS FRAIS Glaces Cones et cornets +3560070335930 PRODUITS FRAIS Glaces Cones et cornets +3560070339280 EPICERIE Autres céréales +3560070339495 EPICERIE Bonbons gélifiés +3560070344086 EPICERIE Cacahuetes +3560071004408 PRODUITS FRAIS Poissons surgelés et preparations panee +3560070345489 LIQUIDES Autres boissons non-gazeifiees Aux fruits +3560070345519 LIQUIDES Autres boissons non-gazeifiees Aux fruits +3560070345724 LIQUIDES Boissons colas - Colas +3560070347308 EPICERIE Conserves d'Ananas +3560070350704 PRODUITS FRAIS Plats cuisinés surgelés - specialites +3560070350940 PRODUITS FRAIS Patisseries industrielles individuelles +3560070351039 PRODUITS FRAIS Herbes et assaisonnements surgelés +3560070351060 PRODUITS FRAIS Herbes et assaisonnements surgelés +3560071004675 PRODUITS FRAIS Yaourts a boire +3560070351091 PRODUITS FRAIS Herbes et assaisonnements surgelés +3560070353378 PRODUITS FRAIS Entrées exotiques +3560070355075 PRODUITS FRAIS Liégeois +3560070355570 PRODUITS FRAIS Fromages frais aromatises +3560070355600 PRODUITS FRAIS Fromages frais aromatises +3560070355662 PRODUITS FRAIS Autres fruits de mer/preparés surgelés +3560070355693 PRODUITS FRAIS Autres produits surgelés +3560070356942 PRODUITS FRAIS Légumes verts surgelés +3560070356973 PRODUITS FRAIS Autres legumes surgelés +3560070360642 EPICERIE Corn flakes +3560071005214 EPICERIE Chocolat tablette - noirs +3560070361021 PRODUITS FRAIS Calamar/encornet/poulpe/seches surgelés +3560070361427 EPICERIE Bonbons gélifiés +3560071005559 PRODUITS FRAIS Foie gras +3560070363711 LIQUIDES Eaux plates Bouteille plastique +3560071005580 LIQUIDES Autres boissons non-gazeifiees Aux fruits +3560071005597 LIQUIDES Autres boissons non-gazeifiees Aux fruits +3560070363728 LIQUIDES Eaux plates Bouteille plastique +3560070364169 PRODUITS FRAIS Panettone/brioche/prd tranche +3560070364534 PRODUITS FRAIS Bœuf haché / Préparation / Découpe +3560070365807 PRODUITS FRAIS Autres produits traiteur frais +3560070365838 PRODUITS FRAIS Autres produits traiteur frais +3560070367221 PRODUITS FRAIS Pates à tarte fraiches +3560070368143 EPICERIE Moutardes +3560070369812 PRODUITS FRAIS Préparation pommes de terres +3560071006051 EPICERIE Pates à tartiner chocolat +3560071006068 EPICERIE Pates à tartiner chocolat +3560070370375 PRODUITS FRAIS Patisseries industrielles - Madeleines +3560070370566 LIQUIDES Jus de fruits frais et légumes - Pur jus +3560070370719 PRODUITS FRAIS Emincés alumettes de viande +3560070371600 PRODUITS FRAIS Pizzas surgelées - Standard +3560070374199 PRODUITS FRAIS Fromage fondu type vqr +3560070374304 PRODUITS FRAIS Frites surgelées +3560070374335 PRODUITS FRAIS Frites surgelées +3560070375226 PRODUITS FRAIS Surimi surgelés +3560070375257 PRODUITS FRAIS Surimi surgelés +3560070375486 EPICERIE Macédoine de légumes +3560071006457 EPICERIE Cafés en dosettes +3560071006464 PRODUITS FRAIS Autres produits traiteur frais +3560071006471 PRODUITS FRAIS Autres produits traiteur frais +3560071006495 PRODUITS FRAIS Autres produits traiteur frais +3560071006501 PRODUITS FRAIS Autres produits traiteur frais +3560070379026 PRODUITS FRAIS Légumes cuisines/ Purées / Gratins +3560070380138 EPICERIE Conserves Coeur de palmier +3560070380190 PRODUITS FRAIS Autres produits traiteur frais +3560070380220 PRODUITS FRAIS Autres produits traiteur frais +3560070380978 PRODUITS FRAIS Patisseries salees surgelées +3560070382224 EPICERIE Autres céréales +3560070383542 PRODUITS FRAIS Panettone/brioche/prd tranche +3560070384754 PRODUITS FRAIS Plats cuisinés surgelés - a base de pates +3560070385843 EPICERIE Mueslis +3560070386659 PRODUITS FRAIS Autres desserts de fruits +3560070387748 EPICERIE Pochon humide chat +3560070391226 PRODUITS FRAIS Pizzas surgelées - Standard +3560070393251 PRODUITS FRAIS ,Jus,, pulpes et coulis de fruit surgelés, +3560070401543 PRODUITS FRAIS Préparation pommes de terres +3560070403011 PRODUITS FRAIS Patisseries industrielles individuelles +3560070403165 PRODUITS FRAIS Pains industriels - Spécialités étrangères +3560070404117 PRODUITS FRAIS Plats cuisinés surgelés - poisson/fruit m +3560071007225 PRODUITS FRAIS Autres saucisses +3560070405022 EPICERIE Autre pdt confiserie de sucre +3560070408214 EPICERIE Conserves Artichauts +3560071007270 EPICERIE Autres céréales +3560071007287 EPICERIE Autres céréales +3560070415571 EPICERIE Cafés en dosettes +3560070415724 EPICERIE Thés parfumés +3560070415847 EPICERIE Cafés en dosettes +3560070416462 PRODUITS FRAIS Libre service - Produits carnes prepares +3560070416653 PRODUITS FRAIS Libre service - Autres volailles +3560070416899 PRODUITS FRAIS Goûter enfant +3560070417506 PRODUITS FRAIS Légumes cuisines/ Purées / Gratins +3560071007515 LIQUIDES Sirops concentrés à base de plantes +3560071007553 LIQUIDES Sirops concentrés à base de fruits +3560071007638 LIQUIDES Sirops concentrés - Autres sirops +3560071007645 LIQUIDES Sirops concentrés - Autres sirops +3560071007669 LIQUIDES Sirops concentrés - Autres sirops +3560071007676 LIQUIDES Sirops concentrés à base de fruits +3560071007737 LIQUIDES Sirops concentrés à base de fruits +3560071007768 LIQUIDES Sirops concentrés - Autres sirops +3560070417537 PRODUITS FRAIS Légumes verts surgelés +3560070417797 EPICERIE ,Chocolat tablette - blanc,,confiserie blanche, +3560070418145 PRODUITS FRAIS Fromage hollandais +3560070419395 EPICERIE Conserves de Sardines +3560070421626 EPICERIE Biscuits sucrés Secs +3560070422630 PRODUITS FRAIS Légumes verts surgelés +3560071007928 PRODUITS FRAIS Yaourts sante et biologique à base de soja +3560071007935 PRODUITS FRAIS Yaourts sante et biologique à base de soja +3560071007942 PRODUITS FRAIS Yaourts sante et biologique à base de soja +3560070423163 PRODUITS FRAIS Autres cremes +3560070423583 PRODUITS FRAIS Salades +3560070423613 PRODUITS FRAIS Salades +3560070423644 PRODUITS FRAIS Salades +3560070423675 PRODUITS FRAIS Salades +3560070427949 PRODUITS FRAIS Bœuf haché / Préparation / Découpe +3560070428885 EPICERIE Chocolat tablette - fourres +3560070431519 PRODUITS FRAIS Crèmes longue conservation +3560071008277 PRODUITS FRAIS Saumon fumés +3560070433063 PRODUITS FRAIS Pains de mie élaboré +3560070434107 EPICERIE Conserves de Haricots verts +3560070434169 EPICERIE Autres mélanges de légumes +3560070434893 EPICERIE Produits feuilletes et sables +3560070437405 PRODUITS FRAIS Laits longue conservation natu +3560070437436 PRODUITS FRAIS Laits longue conservation aromatisé +3560070439140 EPICERIE Conserves de Haricots rouges +3560070439430 PRODUITS FRAIS Poissons surgelés et preparations panee +3560070440634 PRODUITS FRAIS ,Brioche,, buns,, specialite individuelle, +3560071008451 PRODUITS FRAIS Glaces Cones et cornets +3560070442805 EPICERIE Autre pdt confiserie de sucre +3560070443475 PRODUITS FRAIS Yaourts aux fruits +3560070445523 EPICERIE Choux de Bruxelles +3560070445820 PRODUITS FRAIS Plats cuisinés surgelés - specialites +3560070446384 PRODUITS FRAIS Salades +3560070448135 PRODUITS FRAIS Yaourts aux fruits +3560070449675 PRODUITS FRAIS Pains de mie élaboré +3560070450190 EPICERIE Conserves Asperges +3560070450220 EPICERIE Conserves Asperges +3560070453306 LIQUIDES Purs Jus de Fruits - Raisin +3560070454044 PRODUITS FRAIS Salades +3560071008758 EPICERIE Conserves - Autres plats cuisines +3560070454747 PRODUITS FRAIS Pates à tarte fraiches +3560070457335 PRODUITS FRAIS Salades +3560070457403 PRODUITS FRAIS Crèmes longue conservation +3560070459070 PRODUITS FRAIS Fromages frais aromatises +3560070459100 PRODUITS FRAIS Fromages frais aromatises +3560071008901 PRODUITS FRAIS Autres fromages frais +3560071008949 LIQUIDES Autres boissons non-gazeifiees Aux fruits +3560070464166 PRODUITS FRAIS Poissons surgelés natures filets +3560070464258 EPICERIE Potages liquides +3560070464289 EPICERIE Potages liquides +3560070464319 EPICERIE Potages liquides +3560070464340 EPICERIE Potages liquides +3560070464739 EPICERIE Potages liquides +3560070465491 EPICERIE Moutardes +3560070468751 EPICERIE Pâtes alimentaires sèches +3560070468782 EPICERIE Pâtes alimentaires sèches +3560070468812 EPICERIE Pâtes alimentaires sèches +3560070468843 EPICERIE Pâtes alimentaires sèches +3560070468874 EPICERIE Pâtes alimentaires sèches +3560070468904 EPICERIE Pâtes alimentaires sèches +3560070468935 EPICERIE Pâtes alimentaires sèches +3560070468966 EPICERIE Pâtes alimentaires sèches +3560070468997 EPICERIE Pâtes alimentaires sèches +3560070469024 EPICERIE Pâtes alimentaires sèches +3560070469055 EPICERIE Pâtes alimentaires sèches +3560070475681 PRODUITS FRAIS Laits frais pasteurises +3560070475711 PRODUITS FRAIS Laits frais pasteurises +3560070477197 EPICERIE Biscuits sucrés Secs +3560070478637 LIQUIDES Purs Jus de Fruits - Orange +3560070479245 PRODUITS FRAIS Libre service - Autres volailles +3560070479580 EPICERIE Cafés en dosettes +3560070479641 EPICERIE Cafés en dosettes +3560070479702 EPICERIE Cafés en dosettes +3560070482498 PRODUITS FRAIS Autres saucisses +3560070482696 EPICERIE Pâtés +3560070482726 EPICERIE Pâtés +3560070483990 PRODUITS FRAIS Libre service - Poulets +3560070484027 PRODUITS FRAIS Libre service - Poulets +3560070487288 PRODUITS FRAIS ,Jus,, pulpes et coulis de fruit surgelés, +3560070487363 EPICERIE ,Gateaux roules,, fourres, +3560071009847 PRODUITS FRAIS Charcuterie tranchée autres +3560071009861 PRODUITS FRAIS Charcuterie tranchée autres +3560070488643 PRODUITS FRAIS Patisseries salees surgelées +3560070489114 PRODUITS FRAIS Plat cuis./préparé avec viande +3560070489237 PRODUITS FRAIS Plat cuis./préparé avec viande +3560070489442 EPICERIE Pâtes alimentaires sèches +3560070490769 EPICERIE Potages liquides +3560070490929 EPICERIE Autres biscuits sucrés +3560070492435 PRODUITS FRAIS Herbes et assaisonnements surgelés +3560070492978 PRODUITS FRAIS Autres patisseries et gateaux industriels +3560070494224 EPICERIE Cafés en dosettes +3560070494255 EPICERIE Cafés en dosettes +3560070494316 EPICERIE Pâtes alimentaires sèches Spécialités +3560070494378 EPICERIE Pâtes alimentaires sèches Spécialités +3560071010119 PRODUITS FRAIS Autres saucisses +3560070495337 EPICERIE Friandise chat +3560070495573 EPICERIE Barquette humide chat +3560070495603 EPICERIE Barquette humide chat +3560070495726 EPICERIE Cornichons +3560070496600 PRODUITS FRAIS Pates à tarte fraiches +3560070497072 EPICERIE Cafés en dosettes +3560070498055 EPICERIE Compotes pots / coupelles +3560070500796 PRODUITS FRAIS Légumes verts surgelés +3560070502677 PRODUITS FRAIS Mélanges de legumes/garniture surgelés +3560070502929 EPICERIE Conserves Artichauts +3560070505753 PRODUITS FRAIS Foie gras +3560071010287 EPICERIE Cafés en dosettes +3560071010294 EPICERIE Cafés en dosettes +3560070506040 PRODUITS FRAIS Autre Charcuterie à cuire +3560070506071 EPICERIE Conserves Coeur de palmier +3560070507573 PRODUITS FRAIS Plat cuis./prépar.pate légume +3560070508495 EPICERIE Biscuits sucrés Au chocolat +3560070508556 EPICERIE Friandise chat +3560070510436 EPICERIE ,Patisseries indiv,, madeleines, +3560070511891 PRODUITS FRAIS Raclette +3560071010409 EPICERIE Conserves de Sardines +3560070511921 EPICERIE Confiserie de chocolat +3560070513383 EPICERIE Conserves Asperges +3560070514632 PRODUITS FRAIS Fromage fondu type vqr +3560070517763 PRODUITS FRAIS Calamar/encornet/poulpe/seches surgelés +3560070521715 EPICERIE Autre pdt confiserie de sucre +3560071010485 PRODUITS FRAIS Yaourts sante et biologique aux fruits +3560071010492 PRODUITS FRAIS Yaourts sante et biologique aux fruits +3560070523696 PRODUITS FRAIS Préparation pommes de terres +3560070529957 EPICERIE Chocolat tablette - fourres +3560070530021 EPICERIE Sauces chaudes - pâtes - riz +3560070530748 EPICERIE Autre pdt confiserie de sucre +3560070533336 EPICERIE Autres mélanges de légumes +3560070535071 PRODUITS FRAIS Yaourts aux fruits +3560070535101 PRODUITS FRAIS Yaourts aux fruits +3560070535194 EPICERIE Sauces chaudes - pâtes - riz +3560070535552 LIQUIDES Autres boissons non-gazeifiees Aux fruits +3560070535941 LIQUIDES Autres boissons non-gazeifiees Au thé +3560070539239 EPICERIE Macédoine de légumes +3560070541065 PRODUITS FRAIS Dessert patissier +3560070541423 PRODUITS FRAIS Crèmes dessert +3560070541607 PRODUITS FRAIS Fromages de brebis +3560070543182 PRODUITS FRAIS ,Crèmes aux œufs,, petits pot crème, +3560070543632 PRODUITS FRAIS Saucisses de strasbourg +3560070543663 PRODUITS FRAIS Saucisses de strasbourg +3560070543762 PRODUITS FRAIS Panés +3560070543816 PRODUITS FRAIS Saucisses de strasbourg +3560070544684 EPICERIE Autres mélanges de légumes +3560071010850 PRODUITS FRAIS ,Crèmes aux œufs,, petits pot crème, +3560070545056 PRODUITS FRAIS Surimi +3560071010904 LIQUIDES Jus de légumes +3560071010911 LIQUIDES Jus de légumes +3560071010928 LIQUIDES Jus de légumes +3560071010973 PRODUITS FRAIS Riz et semoule +3560070545117 PRODUITS FRAIS ,Quiches,, tartes,, tourtes surgelées, +3560070545230 PRODUITS FRAIS Patisseries salees surgelées +3560070546411 LIQUIDES Sirops concentrés à base de plantes +3560070546442 LIQUIDES Sirops concentrés à base de fruits +3560070548620 PRODUITS FRAIS Libre service - Autres volailles +3560070549498 EPICERIE Boissons chocolatées instantanées +3560070549528 EPICERIE Boissons chocolatées instantanées +3560070551934 PRODUITS FRAIS Produits exotiques +3560070553808 EPICERIE Autres mélanges de légumes +3560070555673 PRODUITS FRAIS Lardons +3560070555901 PRODUITS FRAIS Pizzas +3560070555932 EPICERIE Chocolat tablette - noirs +3560071011369 PRODUITS FRAIS ,Crèmes aux œufs,, petits pot crème, +3560071011383 PRODUITS FRAIS Charc.volaille et autre viande +3560070556465 PRODUITS FRAIS Spec.sucree dont crepe gauffre +3560070556939 PRODUITS FRAIS Saumon fumés +3560070556991 PRODUITS FRAIS Saumon fumés +3560070557165 PRODUITS FRAIS Pizzas surgelées - Cuite sur pierre +3560070558575 EPICERIE Conserves de viandes +3560070558636 EPICERIE Conserves Plats cuisines base de viande +3560070558995 EPICERIE ,Chocolat patissier,,couverture, +3560070559084 LIQUIDES Limonades gazéifiées +3560070562626 PRODUITS FRAIS Patisseries industrielles - Madeleines +3560070562688 EPICERIE Pochon humide chat +3560070562701 EPICERIE Pochon humide chat +3560070562718 EPICERIE Pochon humide chat +3560070562725 EPICERIE Barquette humide chat +3560070562732 EPICERIE Barquette humide chat +3560070562763 EPICERIE Pochon humide chat +3560070563166 EPICERIE Miels +3560070564743 LIQUIDES Eaux plates Bouteille plastique +3560070564750 LIQUIDES Eaux plates Bouteille plastique +3560070566143 PRODUITS FRAIS Surimi +3560070566402 LIQUIDES Autres fruits gazéifiées +3560070567621 PRODUITS FRAIS Glaces Cones et cornets +3560070568222 PRODUITS FRAIS Autres produits snacking glacés +3560070568253 PRODUITS FRAIS Autres produits snacking glacés +3560070571666 PRODUITS FRAIS Autres fromages frais +3560070572441 EPICERIE Conserves Poivrons +3560070572892 PRODUITS FRAIS Fromages blanc allegés +3560070572922 PRODUITS FRAIS Crèmes fraiches epaisses +3560070573011 EPICERIE Petits pains type suédois +3560070574469 EPICERIE Sec chat +3560071011895 PRODUITS FRAIS Yaourts a boire +3560071011901 PRODUITS FRAIS Yaourts a boire +3560070577323 EPICERIE Moutardes +3560070577439 LIQUIDES Autres fruits gazéifiées +3560070577491 LIQUIDES Autres fruits gazéifiées +3560070577521 LIQUIDES Autres fruits gazéifiées +3560070577774 PRODUITS FRAIS Glaces Batonnets +3560070579778 PRODUITS FRAIS Charc.volaille et autre viande +3560070580439 LIQUIDES Eaux gazeuses aromatisées +3560071012175 PRODUITS FRAIS Sandwichs +3560071012182 PRODUITS FRAIS Sandwichs +3560071012199 PRODUITS FRAIS Sandwichs +3560071012212 PRODUITS FRAIS Sandwichs +3560071012229 PRODUITS FRAIS Sandwichs +3560071012236 PRODUITS FRAIS Sandwichs +3560070580460 LIQUIDES Eaux gazeuses aromatisées +3560070581849 EPICERIE Mueslis +3560070581870 EPICERIE Mueslis +3560070582709 EPICERIE Autres céréales +3560070582761 EPICERIE Autres céréales +3560070582853 EPICERIE Autres céréales +3560070582914 EPICERIE Autres céréales +3560070583157 EPICERIE Biscuits sucrés Au chocolat +3560071012434 PRODUITS FRAIS Fromages blanc nature +3560070584543 PRODUITS FRAIS Autres préparations de fruits surgelés +3560071012458 PRODUITS FRAIS Sandwichs +3560070585588 PRODUITS FRAIS Plat cuis./préparé avec viande +3560070587483 PRODUITS FRAIS ,Brioche,, buns,, specialite individuelle, +3560070588428 PRODUITS FRAIS Légumes verts surgelés +3560070588459 PRODUITS FRAIS Mélanges de legumes/garniture surgelés +3560070588480 PRODUITS FRAIS Herbes et assaisonnements surgelés +3560070589654 PRODUITS FRAIS Charc.volaille et autre viande +3560070590179 EPICERIE Pistaches +3560070590209 EPICERIE Pistaches +3560070590230 EPICERIE Autres graines salees +3560070590988 PRODUITS FRAIS Légumes cuisines/ Purées / Gratins +3560070591015 PRODUITS FRAIS Légumes cuisines/ Purées / Gratins +3560070591565 PRODUITS FRAIS Fromages de chevre +3560070592203 PRODUITS FRAIS Herbes et assaisonnements surgelés +3560071012731 EPICERIE Pâtes alimentaires sèches +3560070592975 LIQUIDES Eaux plates aromatisées +3560071012779 PRODUITS FRAIS Poissons surgelés et preparations panee +3560070593309 PRODUITS FRAIS Panettone/brioche/prd tranche +3560070593330 PRODUITS FRAIS Pizzas +3560070593514 PRODUITS FRAIS Pains de mie élaboré +3560070593545 PRODUITS FRAIS Pains de mie élaboré +3560070594559 EPICERIE Biscuits sucrés Aux fruits +3560070594580 PRODUITS FRAIS Yaourts aux céréales +3560070594610 PRODUITS FRAIS Yaourts aux céréales +3560070594641 PRODUITS FRAIS Yaourts aux fruits +3560070595525 EPICERIE Desserts a preparer +3560070596317 LIQUIDES Autres fruits gazéifiées +3560070598021 PRODUITS FRAIS Panés +3560070600090 PRODUITS FRAIS Nuggets +3560070600151 PRODUITS FRAIS Beurres Sans sel +3560070600434 EPICERIE Conserves d'Ananas +3560070601189 PRODUITS FRAIS Salades +3560070601998 PRODUITS FRAIS Saumon fumés +3560070602407 PRODUITS FRAIS Pizzas surgelées - Cuite sur pierre +3560070602438 PRODUITS FRAIS Autres produits surgelés +3560070603046 EPICERIE Céleri +3560070603824 PRODUITS FRAIS Foie gras +3560070604432 PRODUITS FRAIS Poissons surgelés et preparations panee +3560070605767 PRODUITS FRAIS Foie gras +3560070605798 PRODUITS FRAIS Foie gras +3560070605828 PRODUITS FRAIS Foie gras +3560070605903 EPICERIE Autre pdt confiserie de sucre +3560070607068 EPICERIE Potages liquides +3560070609154 PRODUITS FRAIS Foie gras +3560070609253 EPICERIE Potages liquides +3560070609345 LIQUIDES Purs Jus de Fruits - Orange +3560070609888 PRODUITS FRAIS Quenelles +3560070610389 PRODUITS FRAIS Autres saucisses +3560070610563 PRODUITS FRAIS Plat cuis./préparé avec viande +3560070612130 EPICERIE Vinaigrette +3560070612161 EPICERIE Vinaigrette +3560070613342 EPICERIE Conserves Artichauts +3560070614080 PRODUITS FRAIS Plat cuis./préparé avec viande +3560070614110 EPICERIE Autres céréales +3560070614202 EPICERIE Autres céréales +3560070615056 EPICERIE Mueslis +3560070621712 PRODUITS FRAIS Charc.volaille et autre viande +3560070621774 EPICERIE Riz Spécialités +3560070636310 PRODUITS FRAIS Patisseries et tartes surgelées +3560070636471 PRODUITS FRAIS Entrées exotiques +3560070648856 EPICERIE Autres mélanges de légumes +3560070649204 EPICERIE Biscuits sucrés Aux fruits +3560070649235 EPICERIE Biscuits sucrés Aux fruits +3560070649327 EPICERIE Biscuits sucrés Fourres +3560070649655 PRODUITS FRAIS Libre service - Autres volailles +3560071013493 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560071013493 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560071013493 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560071013493 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560071013493 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560071013493 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560071013493 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560070649686 PRODUITS FRAIS Libre service - Autres volailles +3560070649778 EPICERIE ,Patisseries indiv,, madeleines, +3560070650859 PRODUITS FRAIS Calamar/encornet/poulpe/seches surgelés +3560070655595 PRODUITS FRAIS Plats cuisinés surgelés - a base de pates +3560070655625 PRODUITS FRAIS Plats cuisinés surgelés - a base de volaile +3560070657483 EPICERIE ,Aides culinaires,, boillons solides et court bouillon, +3560070657698 EPICERIE Conserves de Petits pois +3560071013660 PRODUITS FRAIS Flans +3560070657728 EPICERIE Conserves de Petits pois carottes +3560070659487 EPICERIE Thés parfumés +3560070659517 EPICERIE Thés parfumés +3560070660575 EPICERIE ,Chocolat patissier,,couverture, +3560070661077 EPICERIE Sauces chaudes - viandes - poissons +3560070668236 PRODUITS FRAIS Poissons surgelés et preparations panee +3560070669684 EPICERIE Conserves de Petits pois +3560070669813 EPICERIE Sauces chaudes à base de tomate et tomate frito +3560070669844 EPICERIE Sauces chaudes - pâtes - riz +3560070669875 EPICERIE Sauces chaudes - pâtes - riz +3560070669905 EPICERIE Sauces chaudes - pâtes - riz +3560070671212 EPICERIE Sauces chaudes - pâtes - riz +3560071013936 EPICERIE Petits pots infantiles +3560071013943 EPICERIE Autres Aliments infantiles hors lait +3560071013967 EPICERIE Autres Aliments infantiles hors lait +3560071013981 EPICERIE Plats infantiles +3560071013998 EPICERIE Plats infantiles +3560071014094 EPICERIE Produits diététiques Autres sucrés +3560070673193 PRODUITS FRAIS Plats cuisinés surgelés - specialites +3560070677498 EPICERIE Choux de Bruxelles +3560070677795 EPICERIE Sauces chaudes - pâtes - riz +3560070677825 EPICERIE Sauces chaudes - viandes - poissons +3560070679904 PRODUITS FRAIS Pizzas surgelées - Standard +3560070680016 EPICERIE Sauces chaudes - pâtes - riz +3560070680559 EPICERIE Conserves Asperges +3560070681136 PRODUITS FRAIS Entrées exotiques +3560070681167 PRODUITS FRAIS Entrées exotiques +3560070681198 PRODUITS FRAIS Entrées exotiques +3560070681228 PRODUITS FRAIS Entrées exotiques +3560070681259 PRODUITS FRAIS Entrées exotiques +3560071014384 PRODUITS FRAIS Crèmes dessert +3560070681662 PRODUITS FRAIS Glaces Batonnets +3560070683550 EPICERIE Autres céréales +3560070683581 EPICERIE Autres céréales +3560070683895 EPICERIE Conserves de Tomates concassées +3560070683987 PRODUITS FRAIS Glaces Cones et cornets +3560070686940 EPICERIE Autres graines salees +3560070686971 EPICERIE Autres graines salees +3560070687114 PRODUITS FRAIS Frites surgelées +3560070687145 PRODUITS FRAIS Frites surgelées +3560070687589 EPICERIE Cacahuetes +3560070687619 EPICERIE Cacahuetes +3560070688968 EPICERIE Conserves Poivrons +3560070689569 EPICERIE Conserves Poivrons +3560071014667 PRODUITS FRAIS Desserts - Mousses +3560070689620 PRODUITS FRAIS Calamar/encornet/poulpe/seches surgelés +3560070689651 PRODUITS FRAIS Calamar/encornet/poulpe/seches surgelés +3560070689682 PRODUITS FRAIS Autres fruits de mer/preparés surgelés +3560070689927 EPICERIE Noix de cajou +3560070690916 EPICERIE Salsifis +3560070690947 EPICERIE Salsifis +3560070692453 LIQUIDES Limonades gazéifiées +3560070692712 LIQUIDES Boissons colas - Colas +3560070692729 LIQUIDES Boissons colas - Colas +3560070692842 PRODUITS FRAIS Autres saucisses +3560070693337 PRODUITS FRAIS Autres Plats cuisinés surgelés +3560070694983 PRODUITS FRAIS Pizzas surgelées - Standard +3560070697410 PRODUITS FRAIS Frites surgelées +3560070697748 PRODUITS FRAIS Assortiment tranche +3560070698202 PRODUITS FRAIS Liégeois +3560070698295 PRODUITS FRAIS Desserts - Mousses +3560070698981 EPICERIE Huiles Olive +3560070699223 PRODUITS FRAIS Frites surgelées +3560070699254 PRODUITS FRAIS Frites surgelées +3560070699346 PRODUITS FRAIS Préparation pommes de terres +3560070699377 PRODUITS FRAIS Frites surgelées +3560070699438 PRODUITS FRAIS Préparation pommes de terres +3560070699469 PRODUITS FRAIS Frites surgelées +3560070700110 PRODUITS FRAIS Charc.volaille et autre viande +3560070704118 PRODUITS FRAIS Charc.volaille et autre viande +3560070704255 EPICERIE Salsifis +3560070704286 EPICERIE Salsifis +3560070704316 EPICERIE Autres mélanges de légumes +3560070704965 EPICERIE Cafés solubles +3560070705740 EPICERIE Pommes de terre +3560070708000 PRODUITS FRAIS Pates fourrees +3560070708031 PRODUITS FRAIS Autres jambons +3560070710232 PRODUITS FRAIS Autres legumes surgelés +3560070710294 PRODUITS FRAIS Légumes verts surgelés +3560070710379 PRODUITS FRAIS Préparation pommes de terres +3560070710652 LIQUIDES Bières Spécialité +3560070710836 PRODUITS FRAIS Fromages blanc allegés +3560070711277 EPICERIE Sucres +3560070712519 EPICERIE Biscuits sucrés Secs +3560070713110 EPICERIE Cafés en dosettes +3560070713271 EPICERIE Sauces chaudes - pâtes - riz +3560070713677 EPICERIE Fruits secs +3560070714056 EPICERIE Cafés moulus +3560070714087 EPICERIE Cafés moulus +3560070714568 PRODUITS FRAIS Bœuf haché / Préparation / Découpe +3560070715480 EPICERIE Crackers +3560070715862 EPICERIE Conserves de Haricots blancs +3560070717514 PRODUITS FRAIS Jambons crus +3560070717934 PRODUITS FRAIS Pates à tarte fraiches +3560070718214 EPICERIE Pochon humide chat +3560070718245 EPICERIE Pochon humide chat +3560070718399 EPICERIE Lait chat +3560070718634 EPICERIE Snacks: Produits souffles et extrudes +3560070718665 EPICERIE Snacks: Produits souffles et extrudes +3560070718696 EPICERIE Snacks: Produits souffles et extrudes +3560070718962 EPICERIE Crackers +3560070719051 EPICERIE Produits feuilletes et sables +3560070719112 EPICERIE Crackers +3560070719235 PRODUITS FRAIS Autres jambons +3560070719266 PRODUITS FRAIS Autres jambons +3560070719297 PRODUITS FRAIS Autres jambons +3560070719327 PRODUITS FRAIS Autres jambons +3560070719358 PRODUITS FRAIS Jambons cuits +3560071015671 PRODUITS FRAIS Traiteur sucré +3560070719617 LIQUIDES Bières Panaches +3560071015770 EPICERIE Autres Aliments infantiles hors lait +3560071015794 EPICERIE Autres Aliments infantiles hors lait +3560071015800 EPICERIE Autres Aliments infantiles hors lait +3560071015817 EPICERIE Autres Aliments infantiles hors lait +3560071015824 EPICERIE Autres Aliments infantiles hors lait +3560071015831 EPICERIE Autres Aliments infantiles hors lait +3560071015848 EPICERIE Autres Aliments infantiles hors lait +3560071015855 EPICERIE Autres Aliments infantiles hors lait +3560070719839 PRODUITS FRAIS Fromage hollandais +3560071015893 PRODUITS FRAIS Dessert patissier +3560070719860 PRODUITS FRAIS Fromage fondu type tranchette +3560070719891 PRODUITS FRAIS Fromages frais aromatises +3560070721276 LIQUIDES Sirops concentrés à base de fruits +3560070721672 EPICERIE Betterave +3560070722082 PRODUITS FRAIS Plat cuis./préparé avec viande +3560070722112 PRODUITS FRAIS Plat cuis./préparé avec viande +3560070722303 EPICERIE Friandise chien +3560070722495 PRODUITS FRAIS Salades +3560070722914 PRODUITS FRAIS ,Brioche,, buns,, specialite individuelle, +3560070723171 PRODUITS FRAIS Légumes cuisines/ Purées / Gratins +3560070724765 EPICERIE Conserves Asperges +3560070726059 PRODUITS FRAIS Fromages de chevre +3560070726226 PRODUITS FRAIS Patisseries salees surgelées +3560070726257 EPICERIE Friandise chien +3560070726486 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560070726547 PRODUITS FRAIS Panettone/brioche/prd tranche +3560070727988 EPICERIE Friandise chien +3560070728015 EPICERIE Friandise chien +3560071016517 PRODUITS FRAIS Desserts - Mousses +3560070728046 EPICERIE Friandise chien +3560070728077 EPICERIE Friandise chat +3560070728138 EPICERIE Friandise chien +3560070728299 EPICERIE Pates à tartiner chocolat +3560070728732 PRODUITS FRAIS ,Patés,, terrines, +3560070729654 LIQUIDES Punch +3560070729975 PRODUITS FRAIS Panettone/brioche/prd tranche +3560070730193 PRODUITS FRAIS Dessert patissier +3560071016715 PRODUITS FRAIS Charc.volaille et autre viande +3560070732944 PRODUITS FRAIS Yaourts sante et biologique à base de soja +3560070733002 PRODUITS FRAIS Yaourts aux fruits +3560070733460 EPICERIE Conserves de Tomates concassées +3560070734788 EPICERIE Thés natures +3560070735143 PRODUITS FRAIS Autres desserts glacés +3560070735204 LIQUIDES Autres boissons non-gazéifiées +3560070735648 EPICERIE Conserves Artichauts +3560070735679 EPICERIE Conserves Artichauts +3560070735709 EPICERIE Conserves Artichauts +3560070737017 EPICERIE Petits pains type suédois +3560070737048 EPICERIE Petits pains type suédois +3560070737710 EPICERIE Autres céréales +3560070737987 PRODUITS FRAIS Autres produits surgelés +3560070738014 PRODUITS FRAIS Préparation pommes de terres +3560070739738 PRODUITS FRAIS Plat cuis./préparé avec viande +3560070740529 EPICERIE Cacahuetes +3560070741168 PRODUITS FRAIS Fromages blanc nature +3560070743308 EPICERIE Potages liquides +3560070747085 EPICERIE Produits diététiques Barres de substitution +3560070747115 EPICERIE Produits diététiques Barres de substitution +3560070747245 PRODUITS FRAIS Beurres Sans sel +3560070748273 LIQUIDES Autres boissons non-gazeifiees Aux fruits +3560070748334 LIQUIDES Purs Jus de Fruits - Autres +3560070748365 LIQUIDES Purs Jus de Fruits - Orange +3560070748396 LIQUIDES Purs Jus de Fruits - Autres +3560070748426 LIQUIDES Purs Jus de Fruits - Autres +3560070748488 EPICERIE Thés parfumés +3560070748570 PRODUITS FRAIS Feuilletés/croissants/pains chocolat +3560070748785 PRODUITS FRAIS Pains de mie élaboré +3560070749256 LIQUIDES Jus de mélange de fruits à base de conc. +3560070749300 LIQUIDES Jus de mélange de fruits à base de conc. +3560070749331 LIQUIDES Jus de mélange de fruits à base de conc. +3560070749362 LIQUIDES Jus de mélange de fruits à base de conc. +3560070750443 LIQUIDES Jus de pomme à base de concentré +3560070751020 EPICERIE Biscuits sucrés Secs +3560070751266 EPICERIE Infusions classiques +3560070751570 PRODUITS FRAIS Charc.volaille et autre viande +3560070751600 PRODUITS FRAIS Charc.volaille et autre viande +3560070752188 EPICERIE Conserves de Haricots verts +3560070752485 EPICERIE Sauces chaudes - pâtes - riz +3560070753833 PRODUITS FRAIS Raclette +3560070753925 PRODUITS FRAIS Raclette +3560070754762 EPICERIE Conserves de Petits pois +3560071017927 PRODUITS FRAIS Sandwichs +3560070754793 EPICERIE Potages deshydrates +3560070754854 EPICERIE Snacks: Produits souffles et extrudes +3560070755257 PRODUITS FRAIS CoCompotes d autres fruits +3560070755288 PRODUITS FRAIS Autres desserts de fruits +3560070755318 PRODUITS FRAIS Autres desserts de fruits +3560070755349 PRODUITS FRAIS Saumon fumés +3560070755370 EPICERIE Cafés en dosettes +3560070756506 PRODUITS FRAIS Libre service - Produits carnes prepares +3560070756629 PRODUITS FRAIS Libre service - Produits carnes prepares +3560071018214 PRODUITS FRAIS Beurres Sans sel +3560071018221 PRODUITS FRAIS Beurres Sales +3560070758005 PRODUITS FRAIS Plat cuis./prépar.pate légume +3560070758036 PRODUITS FRAIS Fromages blanc allegés +3560070758111 PRODUITS FRAIS Chorizo +3560070758203 PRODUITS FRAIS Libre service - Produits carnes prepares +3560070758210 PRODUITS FRAIS Libre service - Produits carnes prepares +3560070758586 PRODUITS FRAIS Plat cuis./préparé avec viande +3560070759323 EPICERIE Biscuits sucrés Au chocolat +3560070759354 EPICERIE Biscuits sucrés Au chocolat +3560070759538 EPICERIE Friandise chat +3560070760480 PRODUITS FRAIS Libre service - Poulets +3560070761210 EPICERIE Epices et herbes +3560070761272 EPICERIE Epices et herbes +3560070761364 EPICERIE Epices et herbes +3560070763573 PRODUITS FRAIS Plat cuis./prépar.pate légume +3560070764785 LIQUIDES Autres boissons non-gazeifiees Aux fruits +3560070766079 EPICERIE Autres biscuits sucrés +3560070766512 LIQUIDES Autres boissons non-gazeifiees Aux fruits +3560070766727 EPICERIE ,Chocolat patissier,,couverture, +3560070767236 PRODUITS FRAIS Mélanges de legumes/garniture surgelés +3560070767267 PRODUITS FRAIS Mélanges de legumes/garniture surgelés +3560070767694 EPICERIE Carottes +3560070770014 EPICERIE Compotes pots / coupelles +3560070772520 EPICERIE Conserves Plats cuisines base de pates +3560070774111 PRODUITS FRAIS Bacs Crèmes Glacées +3560070774395 PRODUITS FRAIS Glaces Batonnets +3560070774456 PRODUITS FRAIS Glaces Batonnets +3560070776597 EPICERIE Potages liquides +3560070776689 EPICERIE Potages liquides +3560070777433 LIQUIDES Boissons colas - Colas +3560070777440 LIQUIDES Boissons colas - Colas +3560070777792 PRODUITS FRAIS Flans +3560070778065 PRODUITS FRAIS Fromages blanc nature +3560070778379 PRODUITS FRAIS Calamar/encornet/poulpe/seches surgelés +3560070778720 EPICERIE Cacahuetes +3560070779659 EPICERIE Epinards +3560070781560 EPICERIE Desserts a preparer +3560070781591 EPICERIE Desserts a preparer +3560070782017 PRODUITS FRAIS Entrées exotiques +3560070782048 PRODUITS FRAIS Plat cuis./préparé avec viande +3560070783892 EPICERIE Conserves Poivrons +3560070784691 PRODUITS FRAIS Panés +3560070786947 PRODUITS FRAIS Jambons cuits +3560070786978 PRODUITS FRAIS Jambons cuits +3560070787005 PRODUITS FRAIS Jambons cuits +3560070787258 EPICERIE Cafés en dosettes +3560070787975 EPICERIE Cafés en dosettes +3560070788002 EPICERIE Cafés en dosettes +3560070788255 PRODUITS FRAIS Pains hamburgers et hot-dogs +3560070788699 PRODUITS FRAIS Panés +3560070788880 EPICERIE Edulcorants Comprimés +3560070789078 PRODUITS FRAIS Fromage fondu type vqr +3560070789689 EPICERIE Potages liquides +3560070789719 EPICERIE Potages liquides +3560070789801 EPICERIE Potages liquides +3560070790593 PRODUITS FRAIS Goûter enfant +3560070790678 PRODUITS FRAIS Autres pâtes molles +3560070791002 PRODUITS FRAIS Frites surgelées +3560070792818 EPICERIE Thés parfumés +3560070793747 EPICERIE Cafés en dosettes +3560070793778 EPICERIE Cafés en dosettes +3560070793808 EPICERIE Cafés en dosettes +3560070793839 EPICERIE Cafés en dosettes +3560070793860 EPICERIE Cafés en dosettes +3560070793891 EPICERIE Cafés en dosettes +3560070794027 PRODUITS FRAIS Patisseries et tartes surgelées +3560070794232 EPICERIE Bonbons durs aux plantes +3560070794652 LIQUIDES Nectars d'orange +3560070794683 LIQUIDES Nectars Multifruits +3560070794713 LIQUIDES Nectars de Pomme +3560070794775 LIQUIDES Autres boissons non-gazeifiees Aux fruits +3560070794836 LIQUIDES Boissons colas - Colas +3560070797394 PRODUITS FRAIS Plat cuis./préparé avec viande +3560070797462 LIQUIDES Purs Jus de Fruits - Raisin +3560070798414 PRODUITS FRAIS Panettone/brioche/prd tranche +3560070798681 EPICERIE Snacks: Produits souffles et extrudes +3560070799039 PRODUITS FRAIS Glaces Batonnets +3560070799213 PRODUITS FRAIS Fromage fondu type vqr +3560070799244 PRODUITS FRAIS Fromage fondu type vqr +3560070799275 PRODUITS FRAIS Fromage fondu type tranchette +3560070799336 PRODUITS FRAIS Fromage hollandais +3560070799398 PRODUITS FRAIS Fromage hollandais +3560070799428 PRODUITS FRAIS Fromage hollandais +3560070799459 PRODUITS FRAIS Fromage hollandais +3560070799480 PRODUITS FRAIS Fromage hollandais +3560070801138 EPICERIE Conserves de Thon +3560070801404 PRODUITS FRAIS Bacs Crèmes Glacées +3560070801435 PRODUITS FRAIS Bacs Crèmes Glacées +3560070801923 EPICERIE Pates à tartiner chocolat +3560070802210 PRODUITS FRAIS Yaourts aux fruits alleges +3560070802241 PRODUITS FRAIS Yaourts aux fruits alleges +3560070802456 LIQUIDES Autres fruits gazéifiées +3560070803064 EPICERIE Laits concentrés +3560071021306 PRODUITS FRAIS Raclette +3560070805259 PRODUITS FRAIS Autres produits traiteur frais +3560070805310 EPICERIE Lait chat +3560070806188 EPICERIE Pochon humide chat +3560070806218 EPICERIE Pochon humide chat +3560071027865 EPICERIE ,Chocolat patissier,,couverture, +3560071027865 EPICERIE ,Chocolat patissier,,couverture, +3560070806270 EPICERIE Pochon humide chat +3560070806669 PRODUITS FRAIS Frites surgelées +3560070806829 EPICERIE Desserts a preparer +3560071028824 PRODUITS FRAIS Traiteur sucré +3560071028855 PRODUITS FRAIS Traiteur sucré +3560071028916 PRODUITS FRAIS Traiteur sucré +3560071028947 PRODUITS FRAIS Traiteur sucré +3560070806850 EPICERIE Desserts a preparer +3560070807628 EPICERIE Compotes pots / coupelles +3560070807963 PRODUITS FRAIS Yaourts a boire +3560070807994 PRODUITS FRAIS Yaourts a boire +3560071030292 PRODUITS FRAIS Autres fromages frais +3560070808021 PRODUITS FRAIS Yaourts a boire +3560071033217 PRODUITS FRAIS Saucissons cuits +3560070808731 EPICERIE Conserves de Thon +3560070808762 EPICERIE Conserves de Thon +3560070809264 EPICERIE Conserves de Thon +3560070809684 PRODUITS FRAIS Fromages blanc nature +3560070809714 EPICERIE Compotes pots / coupelles +3560070810598 EPICERIE Ketchup +3560070811373 EPICERIE Sauces chaudes à base de tomate et tomate frito +3560070812950 PRODUITS FRAIS Panés +3560070813797 EPICERIE Friandise chien +3560070813827 EPICERIE Friandise chien +3560070814213 PRODUITS FRAIS Yaourts natures +3560070814275 PRODUITS FRAIS Yaourts natures +3560070814541 PRODUITS FRAIS Crèmes longue conservation +3560070814572 PRODUITS FRAIS Crèmes longue conservation +3560070814602 PRODUITS FRAIS Crèmes longue conservation +3560070814855 PRODUITS FRAIS Pains hamburgers et hot-dogs +3560070816415 PRODUITS FRAIS Dessert patissier +3560070816507 PRODUITS FRAIS Pains précuits +3560071038366 EPICERIE Confiserie et chocolats paques +3560071038397 EPICERIE Confiserie et chocolats paques +3560070816583 PRODUITS FRAIS Pains hamburgers et hot-dogs +3560070816613 PRODUITS FRAIS Pains hamburgers et hot-dogs +3560070816965 PRODUITS FRAIS Jambons crus +3560071041847 PRODUITS FRAIS Pates à tarte fraiches +3560071041878 PRODUITS FRAIS Pates à tarte fraiches +3560071041908 PRODUITS FRAIS Pates à tarte fraiches +3560070817467 LIQUIDES Eaux plates Bouteille plastique +3560070817474 LIQUIDES Eaux plates Bouteille plastique +3560070817504 LIQUIDES Eaux plates Bouteille plastique +3560070817511 LIQUIDES Eaux plates Bouteille plastique +3560071046354 PRODUITS FRAIS Bœuf haché / Préparation / Découpe +3560070817542 LIQUIDES Eaux plates Bouteille plastique +3560071046897 EPICERIE Produits diététiques Autres salés +3560071047450 PRODUITS FRAIS Crèmes fraiches epaisses +3560070817559 LIQUIDES Eaux plates Bouteille plastique +3560070817573 LIQUIDES Eaux plates Bouteille plastique +3560071048280 EPICERIE Biscuits sucrés Au chocolat +3560070817580 LIQUIDES Eaux plates Bouteille plastique +3560070817788 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560071048785 PRODUITS FRAIS Bries +3560070818013 PRODUITS FRAIS Autres pâtes molles +3560071048907 PRODUITS FRAIS Autres pâtes molles +3560070818075 PRODUITS FRAIS Autres pâtes molles +3560070818334 PRODUITS FRAIS Autre Charcuterie à cuire +3560070818389 PRODUITS FRAIS Autre Charcuterie à cuire +3560070818914 EPICERIE Cappuccino +3560070819065 PRODUITS FRAIS Crêpes et galettes salées surgelées +3560070819515 PRODUITS FRAIS Crèmes fraiches epaisses +3560070820115 EPICERIE Barres céréalières +3560070820221 EPICERIE Barres céréalières +3560070820238 EPICERIE Barres céréalières +3560070820245 EPICERIE Barres céréalières +3560070820306 PRODUITS FRAIS Nuggets +3560070820313 PRODUITS FRAIS Pizzas surgelées - Standard +3560070820771 PRODUITS FRAIS Glaces Batonnets +3560070820849 PRODUITS FRAIS Glaces Batonnets +3560070820856 PRODUITS FRAIS Glaces Cones et cornets +3560070820948 PRODUITS FRAIS Glaces Batonnets +3560070820962 PRODUITS FRAIS Glaces Cones et cornets +3560070820986 PRODUITS FRAIS Bacs Crèmes Glacées +3560070821051 EPICERIE Bonbons gélifiés +3560071055578 PRODUITS FRAIS Salades +3560071056995 EPICERIE Biscuits sucrés - Assortiments +3560070821082 EPICERIE Bonbons gélifiés +3560070821099 EPICERIE Bonbons gélifiés +3560070821143 PRODUITS FRAIS Glaces Batonnets +3560070821280 EPICERIE ,Chocolat patissier,,couverture, +3560070821310 EPICERIE Pâtes alimentaires sèches +3560070821327 EPICERIE Pâtes alimentaires sèches +3560070821464 EPICERIE Boite individuelle humide chat +3560070821471 EPICERIE Bte multi variétés humide chat +3560070821495 EPICERIE Friandise chat +3560070821525 EPICERIE Friandise chien +3560070821532 EPICERIE Sec chat +3560070821549 EPICERIE Sec chat +3560070821556 EPICERIE Sec chat +3560070821563 EPICERIE Sec chat +3560070821600 EPICERIE Agglomerante +3560070821648 EPICERIE Friandise chien +3560071064563 EPICERIE Confiserie et chocolats noel +3560071064624 EPICERIE Confiserie et chocolats paques +3560071064686 EPICERIE Confiserie et chocolats noel +3560071064747 EPICERIE Confiserie et chocolats noel +3560070821655 EPICERIE Friandise chien +3560070821662 EPICERIE Friandise chien +3560070821808 EPICERIE Bonbons gélifiés +3560070821815 EPICERIE Bonbons gélifiés +3560070821822 EPICERIE Bonbons gélifiés +3560070821846 EPICERIE Bonbons gélifiés +3560070821884 LIQUIDES Autres boissons non-gazeifiees Au thé +3560070821907 EPICERIE Pochon humide chat +3560070821914 EPICERIE Pochon humide chat +3560070821969 EPICERIE Friandise chat +3560070821990 EPICERIE Mueslis +3560071073541 PRODUITS FRAIS Autres produits preparés +3560071073602 PRODUITS FRAIS Autres produits preparés +3560070822140 PRODUITS FRAIS Autres produits snacking glacés +3560070822157 PRODUITS FRAIS Autres produits snacking glacés +3560070822171 EPICERIE Riz Spécialités +3560070822584 PRODUITS FRAIS Bacs Crèmes Glacées +3560070822836 EPICERIE Semoules de ble / Couscous +3560070823406 EPICERIE Caramels et spécialités +3560070823413 EPICERIE Bonbons gélifiés +3560070823420 EPICERIE Bonbons gélifiés +3560070823437 EPICERIE Bonbons gélifiés +3560070823475 EPICERIE Bonbons gélifiés +3560070823680 EPICERIE Potages liquides +3560070823741 PRODUITS FRAIS Pizzas surgelées - Standard +3560070823765 PRODUITS FRAIS Calamar/encornet/poulpe/seches surgelés +3560070823796 EPICERIE Potages liquides +3560070823970 EPICERIE Blé / Quinoa / Autres céréales +3560070823987 EPICERIE Semoules de ble / Couscous +3560070824465 EPICERIE Cafés en dosettes +3560070824472 EPICERIE Cafés en dosettes +3560070824489 EPICERIE Cafés en dosettes +3560070824496 EPICERIE Cafés en dosettes +3560071076931 EPICERIE Epices et herbes +3560070824502 EPICERIE Cafés en dosettes +3560070824519 EPICERIE Cafés en dosettes +3560070824526 EPICERIE Cafés en dosettes +3560070824533 EPICERIE Cafés en dosettes +3560070824618 EPICERIE Pâtes alimentaires aux œufs +3560070824625 EPICERIE Pâtes alimentaires aux œufs +3560070824632 EPICERIE Pâtes alimentaires aux œufs +3560070824649 EPICERIE Pâtes alimentaires aux œufs +3560070824656 LIQUIDES Limonades gazéifiées +3560070824694 LIQUIDES Boissons colas - Colas +3560070824700 LIQUIDES Boissons colas - Colas +3560070824847 LIQUIDES Autres fruits gazéifiées +3560070824953 EPICERIE Infusions parfumées +3560070825172 LIQUIDES Autres fruits gazéifiées +3560070825219 EPICERIE Biscottes +3560070825349 EPICERIE Cafés en grains +3560070825448 PRODUITS FRAIS Poissons surgelés natures filets +3560070825455 EPICERIE Riz prêt à l'emploi +3560070825462 EPICERIE Riz prêt à l'emploi +3560070825479 EPICERIE Riz prêt à l'emploi +3560070825486 EPICERIE Pâtes alimentaires sèches Spécialités +3560070825493 EPICERIE Pâtes alimentaires sèches Spécialités +3560070825509 EPICERIE Pâtes alimentaires sèches Spécialités +3560070826032 EPICERIE Cafés en dosettes +3560071080327 PRODUITS FRAIS Laits frais pasteurises +3560070826063 EPICERIE Cafés en dosettes +3560070826087 EPICERIE Cappuccino +3560070826292 EPICERIE Riz étuvés +3560070826414 EPICERIE Friandise chien +3560070826469 EPICERIE Potages liquides +3560070826476 EPICERIE Potages liquides +3560070827305 PRODUITS FRAIS Glaces Batonnets +3560070827435 EPICERIE Agglomerante +3560070827978 LIQUIDES Autres boissons non-gazéifiées +3560070827985 LIQUIDES Autres boissons non-gazéifiées +3560070827992 LIQUIDES Autres boissons non-gazéifiées +3560070828029 LIQUIDES Autres boissons non-gazéifiées +3560070828036 LIQUIDES Autres boissons non-gazéifiées +3560070828050 LIQUIDES Autres boissons non-gazéifiées +3560070828227 LIQUIDES Autres boissons non-gazeifiees Au thé +3560070828234 LIQUIDES Autres boissons non-gazeifiees Aux fruits +3560070828241 PRODUITS FRAIS Glaces Batonnets +3560070828425 EPICERIE Sec chat +3560070828722 EPICERIE Bonbons gélifiés +3560070828784 PRODUITS FRAIS Glaces Batonnets +3560070828791 PRODUITS FRAIS Glaces Cones et cornets +3560070829156 EPICERIE Friandise chien +3560070829583 EPICERIE Barres céréalières +3560070829682 EPICERIE Barquette humide chat +3560070829903 LIQUIDES Tonics et Bitter gazéifiées +3560070830411 EPICERIE Thés parfumés +3560070830749 EPICERIE Ketchup +3560070831029 PRODUITS FRAIS Nuggets +3560070833443 PRODUITS FRAIS Crèmes dessert +3560070833504 EPICERIE Friandise chien +3560070835300 PRODUITS FRAIS Dessert patissier +3560070835805 PRODUITS FRAIS Corps gras de cuisine +3560070836246 PRODUITS FRAIS ,Crèmes aux œufs,, petits pot crème, +3560070845491 PRODUITS FRAIS Préparation pommes de terres +3560070846603 PRODUITS FRAIS Corps gras de cuisine +3560070846634 PRODUITS FRAIS Corps gras de cuisine +3560070846665 PRODUITS FRAIS Corps gras a tartiner +3560070846924 PRODUITS FRAIS Fromages frais aromatises +3560070846955 PRODUITS FRAIS Fromages frais aromatises +3560070847037 PRODUITS FRAIS Libre service - Produits carnes prepares +3560071081188 EPICERIE Biscuits sucrés Secs +3560070847068 PRODUITS FRAIS Libre service - Produits carnes prepares +3560070847501 PRODUITS FRAIS Autres produits surgelés +3560070850235 EPICERIE Desserts a preparer +3560070850792 EPICERIE Biscuits sucrés Secs +3560070850907 PRODUITS FRAIS Salades +3560070851003 PRODUITS FRAIS Poissons surgelés nature tranche/morceau +3560070851683 PRODUITS FRAIS Autres pâtes molles +3560070852116 EPICERIE Thés parfumés +3560070852499 PRODUITS FRAIS Libre service - Produits carnes prepares +3560071081348 EPICERIE Pâtes alimentaires sèches +3560071081355 EPICERIE Pâtes alimentaires sèches +3560071081362 EPICERIE Pâtes alimentaires sèches +3560071081386 LIQUIDES Sirops concentrés à base de plantes +3560071081393 LIQUIDES Sirops concentrés à base de fruits +3560071081409 LIQUIDES Sirops concentrés à base de fruits +3560070854776 PRODUITS FRAIS Poissons surgelés et preparations panee +3560070855896 PRODUITS FRAIS Autres yaourts +3560071081508 PRODUITS FRAIS Salades +3560071081515 PRODUITS FRAIS Salades +3560071081522 PRODUITS FRAIS Salades +3560071081539 PRODUITS FRAIS Salades +3560071081546 PRODUITS FRAIS Salades +3560071081553 PRODUITS FRAIS Salades +3560071081560 PRODUITS FRAIS Traiteur sucré +3560071081621 PRODUITS FRAIS Entrées +3560071081638 PRODUITS FRAIS Entrées +3560071081690 PRODUITS FRAIS Plat cuis./préparé avec viande +3560071081706 PRODUITS FRAIS Plat cuis./préparé avec viande +3560071081713 PRODUITS FRAIS Plat cuis./préparé avec viande +3560070856077 PRODUITS FRAIS Poissons surgelés et preparations panee +3560070857494 PRODUITS FRAIS Raclette +3560070858309 PRODUITS FRAIS Pates natures +3560070858361 LIQUIDES Jus de fruits frais et légumes - Pur jus +3560071081898 PRODUITS FRAIS Jambons crus +3560070859344 PRODUITS FRAIS Fromages frais aromatises +3560070859993 PRODUITS FRAIS Gnocchis +3560070860197 PRODUITS FRAIS Laits frais pasteurises +3560071081997 PRODUITS FRAIS Fromages de brebis +3560071082000 PRODUITS FRAIS Emmentals blocs +3560071082024 PRODUITS FRAIS Emmentals blocs +3560071082048 PRODUITS FRAIS Autres pates pressees +3560071082055 PRODUITS FRAIS Emmentals rapes +3560071082062 PRODUITS FRAIS Fromages de chevre +3560071082130 PRODUITS FRAIS Baies et fruits entiers surgelés +3560070860678 EPICERIE Chocolat tablette - noirs +3560070862047 PRODUITS FRAIS Autre Charcuterie à cuire +3560071082161 PRODUITS FRAIS Autres préparations de fruits surgelés +3560070867967 EPICERIE Confiserie et chocolats paques +3560070869428 PRODUITS FRAIS Pates pressées non cuites +3560071082185 PRODUITS FRAIS Autres préparations de fruits surgelés +3560070871933 PRODUITS FRAIS Pates pressées non cuites +3560070872466 PRODUITS FRAIS Yaourts aux fruits +3560070872497 PRODUITS FRAIS Yaourts aux fruits +3560071082239 EPICERIE Barquette humide chat +3560071082246 EPICERIE Barquette humide chat +3560071082253 EPICERIE Barquette humide chien +3560070872619 PRODUITS FRAIS Charc.volaille et autre viande +3560070874125 EPICERIE Confiserie et chocolats paques +3560070874187 EPICERIE Confiserie et chocolats paques +3560070874637 EPICERIE Conserves Poivrons +3560070876501 PRODUITS FRAIS Blinis et croutons +3560070876532 PRODUITS FRAIS Blinis et croutons +3560070877546 PRODUITS FRAIS Pains de mie élaboré +3560070877577 PRODUITS FRAIS Pains de mie élaboré +3560070879113 LIQUIDES Jus de légumes +3560070879144 LIQUIDES Jus de légumes +3560070879762 PRODUITS FRAIS Autres pains industriels +3560070880232 PRODUITS FRAIS Autre Charcuterie à cuire +3560070880812 EPICERIE Bonbons gélifiés +3560070880881 LIQUIDES Nectars Multifruits +3560070880911 LIQUIDES Nectars - Autres fruits +3560070880942 LIQUIDES Nectars - Autres fruits +3560070880973 LIQUIDES Nectars d'orange +3560071082468 EPICERIE Thés natures +3560070881000 LIQUIDES Nectars d'ananas +3560071082598 EPICERIE Biscuits sucrés Au chocolat +3560071082604 EPICERIE Biscuits sucrés Au chocolat +3560070881062 LIQUIDES Nectars - Autres fruits +3560071082710 EPICERIE Pâtes alimentaires sèches +3560071082727 EPICERIE Pâtes alimentaires sèches +3560071082826 EPICERIE Pâtes alimentaires sèches +3560071082840 EPICERIE Pâtes alimentaires sèches +3560070883103 PRODUITS FRAIS Jambons cuits +3560070885169 PRODUITS FRAIS Dessert patissier +3560071083038 EPICERIE ,Gateaux roules,, fourres, +3560071083076 EPICERIE ,Gateaux roules,, fourres, +3560070886807 PRODUITS FRAIS Liégeois +3560070887583 PRODUITS FRAIS Autres produits surgelés +3560071083106 PRODUITS FRAIS Mélanges de legumes/garniture surgelés +3560071083113 PRODUITS FRAIS Autres legumes surgelés +3560071083120 PRODUITS FRAIS Mélanges de legumes/garniture surgelés +3560070888108 EPICERIE Thés parfumés +3560070888115 EPICERIE Infusions classiques +3560070888122 EPICERIE Infusions classiques +3560070888139 EPICERIE Thés parfumés +3560070888146 EPICERIE Infusions classiques +3560071083229 LIQUIDES Purs Jus de Fruits - Autres +3560071083236 EPICERIE Conserves Plats cuisines base de viande +3560070888153 EPICERIE Thés parfumés +3560070888696 PRODUITS FRAIS Fromages frais aromatises +3560071083304 EPICERIE Conserves Plats cuisines base de legumes +3560071083311 EPICERIE Conserves Plats cuisines base de legumes +3560071083328 EPICERIE Conserves Plats cuisines base de legumes +3560071083335 EPICERIE Conserves Plats cuisines base de legumes +3560071083342 EPICERIE Conserves Plats cuisines base de legumes +3560071083366 EPICERIE ,Chocolat tablette - blanc,,confiserie blanche, +3560070889303 PRODUITS FRAIS Mélanges de legumes/garniture surgelés +3560070889792 EPICERIE ,Fruits secs,, fruits confits, +3560070889853 EPICERIE ,Aromes,, colorants,, decors, +3560070889884 EPICERIE ,Fruits secs,, fruits confits, +3560070891689 PRODUITS FRAIS Fromages blanc nature +3560070891917 PRODUITS FRAIS Autres pâtes molles +3560070891948 PRODUITS FRAIS Autres pâtes molles +3560070892105 LIQUIDES Nectars de Poire +3560070892136 LIQUIDES Nectars - Autres fruits +3560071083588 LIQUIDES Jus de légumes +3560071083588 LIQUIDES Jus de légumes +3560070892167 LIQUIDES Nectars - Autres fruits +3560071083656 LIQUIDES Jus d'autres fruits bio +3560071083663 LIQUIDES Jus d'autres fruits bio +3560071083663 LIQUIDES Jus d'autres fruits bio +3560071083670 LIQUIDES Jus de légumes bio +3560071083670 LIQUIDES Jus de légumes bio +3560071083700 LIQUIDES Jus d'orange bio +3560071083724 EPICERIE Confitures d autres fruits +3560071083731 EPICERIE Confitures d autres fruits +3560071083748 EPICERIE Conserves Poivrons +3560071083755 EPICERIE Conserves Poivrons +3560070892198 LIQUIDES Nectars Multifruits +3560070892228 LIQUIDES Nectars de Pomme +3560070892259 LIQUIDES Nectars - Autres fruits +3560070892730 EPICERIE Friandise chien +3560070892761 EPICERIE Friandise chien +3560070892792 EPICERIE Friandise chien +3560070892822 EPICERIE Friandise chien +3560070892853 EPICERIE Friandise chien +3560070892884 EPICERIE Friandise chien +3560070894161 EPICERIE Cacahuetes +3560070894642 EPICERIE Biscuits sucrés Secs +3560071083939 PRODUITS FRAIS Autres produits traiteur frais +3560071083946 PRODUITS FRAIS Autres produits traiteur frais +3560071083953 PRODUITS FRAIS Autres produits traiteur frais +3560070897216 EPICERIE Conserves de Salades de thon et autres +3560070897247 EPICERIE Conserves de Salades de thon et autres +3560070897278 EPICERIE Conserves de Salades de thon et autres +3560071084011 EPICERIE Miels +3560071084028 EPICERIE Miels +3560071084035 EPICERIE Miels +3560070897339 EPICERIE Conserves de Salades de thon et autres +3560070897360 EPICERIE Conserves de Salades de thon et autres +3560071084066 EPICERIE Miels +3560071084110 EPICERIE Miels +3560070897391 EPICERIE Conserves de Salades de thon et autres +3560070897421 EPICERIE Conserves de Salades de thon et autres +3560070897698 EPICERIE Moutardes +3560071084158 EPICERIE Conserves de Thon +3560071084158 EPICERIE Conserves de Thon +3560071084165 EPICERIE Conserves de Thon +3560071084165 EPICERIE Conserves de Thon +3560071084196 EPICERIE Conserves de Thon +3560071084202 EPICERIE Conserves de Thon +3560071084219 EPICERIE Conserves de Thon +3560071084264 EPICERIE Conserves de Thon +3560070899524 EPICERIE Confiserie de chocolat +3560070899838 PRODUITS FRAIS Salades +3560070899869 PRODUITS FRAIS Fromages de brebis +3560070900046 EPICERIE Compotes boîtes et bocales +3560070900077 EPICERIE Compotes boîtes et bocales +3560070900565 PRODUITS FRAIS Beurres Sans sel +3560070900596 PRODUITS FRAIS Beurres Sales +3560070900657 PRODUITS FRAIS Beurres Sales +3560070900718 PRODUITS FRAIS Autres pâtes molles +3560070903085 PRODUITS FRAIS Crèmes dessert +3560070903467 PRODUITS FRAIS Fromages blanc nature +3560070905652 PRODUITS FRAIS Plat cuis./préparé avec viande +3560070905973 EPICERIE ,Amandes,, noisettes,, noix, +3560070906116 PRODUITS FRAIS Beurres Sans sel +3560070906147 PRODUITS FRAIS Beurres Sales +3560070906208 PRODUITS FRAIS Autres cremes +3560070906390 PRODUITS FRAIS Fromages blanc aromatises / fruits +3560070906772 PRODUITS FRAIS Fromages frais aromatises +3560070906802 PRODUITS FRAIS Fromages frais type nature +3560070906833 PRODUITS FRAIS Fromages frais aromatises +3560070906864 PRODUITS FRAIS Fromages frais aromatises +3560070906987 PRODUITS FRAIS Fromage fondu type tranchette +3560070907045 PRODUITS FRAIS Fromage fondu type tranchette +3560070907380 EPICERIE Conserves Poivrons +3560070907410 EPICERIE Conserves Asperges +3560070910540 PRODUITS FRAIS Raclette +3560070910571 PRODUITS FRAIS Raclette +3560070910601 PRODUITS FRAIS Raclette +3560071085124 EPICERIE Biscuits sucrés - Assortiments +3560071085162 PRODUITS FRAIS Yaourts a boire +3560071085179 PRODUITS FRAIS Yaourts a boire +3560071085186 PRODUITS FRAIS Yaourts a boire +3560070910694 PRODUITS FRAIS Raclette +3560070911967 EPICERIE Autres farines +3560070911998 EPICERIE Compotes pots / coupelles +3560070913572 PRODUITS FRAIS Fromages frais - Spécialité italienne +3560070913763 EPICERIE Sauces chaudes à base de tomate et tomate frito +3560070914401 PRODUITS FRAIS Yaourts natures +3560070914432 PRODUITS FRAIS Yaourts natures +3560070914517 EPICERIE ,Chocolat tablette - amande,,noisette,,riz, +3560070914562 EPICERIE ,Chocolat tablette - blanc,,confiserie blanche, +3560070914678 PRODUITS FRAIS Patisseries industrielles - Madeleines +3560070914739 PRODUITS FRAIS Autres patisseries et gateaux industriels +3560070915538 EPICERIE Confiserie et chocolats paques +3560070916085 PRODUITS FRAIS Panés +3560070916252 PRODUITS FRAIS Mélanges de legumes/garniture surgelés +3560070917020 PRODUITS FRAIS Flans +3560070919079 PRODUITS FRAIS Plat cuis./préparé avec viande +3560070919574 PRODUITS FRAIS Fromages de chevre +3560070919888 LIQUIDES Tonics et Bitter gazéifiées +3560070924837 PRODUITS FRAIS Autres produits de panification industrielles +3560070926176 EPICERIE Huiles mélangées +3560070926220 EPICERIE Huiles mélangées +3560070926787 EPICERIE Sec chat +3560071085490 PRODUITS FRAIS Plats cuisinés surgelés - specialites +3560070926909 EPICERIE Sec chat +3560071085568 EPICERIE Blé / Quinoa / Autres céréales +3560070927746 PRODUITS FRAIS Entrées exotiques +3560070927777 PRODUITS FRAIS Entrées exotiques +3560070927975 EPICERIE Vinaigrette +3560071085650 LIQUIDES Autres boissons non-gazeifiees Aux fruits +3560070928002 EPICERIE Vinaigrette +3560071085674 PRODUITS FRAIS Jambons crus +3560071085681 PRODUITS FRAIS Jambons crus +3560071085698 PRODUITS FRAIS Jambons crus +3560071085711 PRODUITS FRAIS Assortiment tranche +3560070928194 EPICERIE Infusions classiques +3560070928224 EPICERIE Infusions classiques +3560070928286 EPICERIE Thés parfumés +3560071085803 PRODUITS FRAIS Assortiment tranche +3560070928347 EPICERIE Infusions parfumées +3560070929177 PRODUITS FRAIS Charc.volaille et autre viande +3560070929290 EPICERIE Compotes gourdes +3560070929757 PRODUITS FRAIS Gateaux glacés à partager +3560070929788 PRODUITS FRAIS Bacs Sorbets +3560071085919 PRODUITS FRAIS Crevettes +3560071085919 PRODUITS FRAIS Crevettes +3560070929818 PRODUITS FRAIS Gateaux glacés à partager +3560070929979 PRODUITS FRAIS Crêpes et galettes salées surgelées +3560071085933 EPICERIE Produits diététiques Autres sucrés +3560070930265 PRODUITS FRAIS Calamar/encornet/poulpe/seches surgelés +3560070930296 PRODUITS FRAIS Autres patisseries et gateaux industriels +3560070931521 PRODUITS FRAIS Crèmes dessert +3560071086084 EPICERIE Pâtes alimentaires aux œufs +3560071086121 PRODUITS FRAIS Autres produits surgelés +3560070931835 PRODUITS FRAIS Comte +3560070932610 PRODUITS FRAIS Charc.volaille et autre viande +3560070932641 PRODUITS FRAIS Autres saucisses +3560070932955 EPICERIE Conserves Asperges +3560070932986 EPICERIE Conserves Asperges +3560070933044 PRODUITS FRAIS Frites surgelées +3560070933716 PRODUITS FRAIS ,Quiches,, tartes,, tourtes surgelées, +3560070935079 EPICERIE Potages deshydrates +3560071086268 PRODUITS FRAIS Surimi +3560070936588 PRODUITS FRAIS Autre Charcuterie à cuire +3560070938629 EPICERIE Cafés moulus +3560070940189 EPICERIE Moutardes +3560071086336 EPICERIE Sauces chaudes - pâtes - riz +3560071086343 EPICERIE Sauces chaudes - pâtes - riz +3560070940219 EPICERIE Moutardes +3560070940240 EPICERIE Conserves de mais +3560070941629 PRODUITS FRAIS Plat cuis./prépar.pate légume +3560070941810 EPICERIE Autre pdt confiserie de sucre +3560070941841 EPICERIE Autre pdt confiserie de sucre +3560071086428 PRODUITS FRAIS Champignons surgelés +3560071086459 PRODUITS FRAIS Champignons surgelés +3560071086480 PRODUITS FRAIS Champignons surgelés +3560071086510 PRODUITS FRAIS Champignons surgelés +3560070943890 PRODUITS FRAIS Patisseries et tartes surgelées +3560070943968 LIQUIDES Jus de fruits frais et légumes - Pur jus +3560070944026 LIQUIDES Jus de fruits frais et légumes - Pur jus +3560070944286 PRODUITS FRAIS Oeufs +3560070946013 PRODUITS FRAIS Mélanges de legumes/garniture surgelés +3560070946259 PRODUITS FRAIS Patisseries salees surgelées +3560071086855 LIQUIDES Whiskies écossais blend +3560071086923 EPICERIE Thés parfumés +3560071086954 EPICERIE Thés parfumés +3560071086985 EPICERIE Thés parfumés +3560071089610 LIQUIDES Bières Spécialité +3560070946280 PRODUITS FRAIS Patisseries salees surgelées +3560070946310 PRODUITS FRAIS Jambons cuits +3560071090821 EPICERIE Autres céréales +3560070946341 PRODUITS FRAIS Jambons cuits +3560071090951 LIQUIDES Jus d'autres fruits à base de concentré +3560071090951 LIQUIDES Jus d'autres fruits à base de concentré +3560071091002 PRODUITS FRAIS Entrées +3560071091156 PRODUITS FRAIS Foie gras +3560070948123 PRODUITS FRAIS Jambons cuits +3560071091170 PRODUITS FRAIS Patisseries industrielles individuelles +3560071091187 PRODUITS FRAIS Patisseries industrielles individuelles +3560071091200 PRODUITS FRAIS Patisseries industrielles individuelles +3560070948352 PRODUITS FRAIS Yaourts a boire +3560070948383 PRODUITS FRAIS Yaourts a boire +3560070948413 PRODUITS FRAIS Yaourts a boire +3560070948475 PRODUITS FRAIS Yaourts a boire +3560070948505 PRODUITS FRAIS Yaourts a boire +3560070948536 PRODUITS FRAIS Yaourts a boire +3560070948567 PRODUITS FRAIS Yaourts a boire +3560070948598 PRODUITS FRAIS Yaourts a boire +3560070948628 PRODUITS FRAIS Yaourts a boire +3560070948659 PRODUITS FRAIS Yaourts a boire +3560070948680 PRODUITS FRAIS Yaourts a boire +3560070948710 PRODUITS FRAIS Yaourts a boire +3560070948994 PRODUITS FRAIS Yaourts a boire +3560071091477 PRODUITS FRAIS Jambons crus +3560070949021 PRODUITS FRAIS Yaourts a boire +3560070949564 PRODUITS FRAIS Plat cuis./prépar.avec poisson +3560070949656 PRODUITS FRAIS Produits exotiques +3560070950089 PRODUITS FRAIS Fromages frais type nature +3560070950119 PRODUITS FRAIS Fromages frais type nature +3560070950317 EPICERIE Biscuits sucrés Au chocolat +3560070950348 EPICERIE Biscuits sucrés Au chocolat +3560071092221 PRODUITS FRAIS Yaourts sante et biologique à base de soja +3560071092238 PRODUITS FRAIS Yaourts sante et biologique à base de soja +3560070950379 EPICERIE Biscuits sucrés Au chocolat +3560070952991 EPICERIE Desserts a preparer +3560070953837 PRODUITS FRAIS Autres produits surgelés +3560070955107 PRODUITS FRAIS Autres jambons +3560071092351 EPICERIE Pâtes alimentaires aux œufs +3560071092368 EPICERIE Pâtes alimentaires aux œufs +3560071092399 EPICERIE Bonbons gélifiés +3560071092429 PRODUITS FRAIS Salades +3560071092436 PRODUITS FRAIS Salades +3560071092443 EPICERIE Légumes secs +3560071092573 EPICERIE Chocolat tablette - au lait +3560070955138 PRODUITS FRAIS Autres jambons +3560070955169 PRODUITS FRAIS Autres jambons +3560070955435 PRODUITS FRAIS Autre Charcuterie à cuire +3560070955558 EPICERIE Conserves de Thon +3560070956661 EPICERIE Autres graines salees +3560070957590 LIQUIDES Autres boissons non-gazeifiees Aux fruits +3560070957736 PRODUITS FRAIS Patisseries et tartes surgelées +3560070959242 PRODUITS FRAIS Légumes cuisines/ Purées / Gratins +3560070959273 PRODUITS FRAIS Dessert patissier +3560070959518 PRODUITS FRAIS Patisseries industrielles - Madeleines +3560070959549 PRODUITS FRAIS Salades +3560070959600 PRODUITS FRAIS Salades +3560070962150 PRODUITS FRAIS Pains hamburgers et hot-dogs +3560070962600 PRODUITS FRAIS Préparation pommes de terres +3560070965830 EPICERIE Conserves - Autres plats cuisines +3560070966004 PRODUITS FRAIS Autres desserts de fruits +3560070966387 EPICERIE Desserts a preparer +3560070967346 PRODUITS FRAIS Volailles Découpes / Préparations +3560071092917 LIQUIDES Champagnes Millésimes et cuvées spéciales +3560071092986 EPICERIE Biscuits sucrés Secs +3560071093099 EPICERIE Conserves de Champignons de Paris coupés +3560071093310 EPICERIE Cafés en dosettes +3560071093341 EPICERIE Cafés en dosettes +3560071093372 EPICERIE Cafés en dosettes +3560071093402 EPICERIE Cafés en dosettes +3560071093433 EPICERIE Cafés en dosettes +3560071093464 EPICERIE Cafés en dosettes +3560071093495 EPICERIE Cafés en dosettes +3560071093525 EPICERIE Conserves de Haricots verts +3560071093532 EPICERIE Conserves Asperges +3560070967414 PRODUITS FRAIS Fromage hollandais +3560070968749 EPICERIE Conserves Poivrons +3560070968770 EPICERIE Conserves Artichauts +3560071093648 EPICERIE Conserves Asperges +3560070968831 EPICERIE Conserves Poivrons +3560071093709 PRODUITS FRAIS Autres poissons fumés +3560070969678 EPICERIE Compotes pots / coupelles +3560070969739 EPICERIE Compotes pots / coupelles +3560070969791 EPICERIE Compotes pots / coupelles +3560071093808 LIQUIDES Nectars d'orange +3560071093853 EPICERIE Confitures d autres fruits +3560071093945 PRODUITS FRAIS Desserts - Mousses +3560070969883 EPICERIE Compotes gourdes +3560071094034 LIQUIDES Sirops concentrés à base de fruits +3560070969913 EPICERIE Compotes gourdes +3560070970704 EPICERIE Conserves de Peches +3560070970827 EPICERIE Desserts a preparer +3560071094126 PRODUITS FRAIS Crèmes dessert +3560071094157 PRODUITS FRAIS Crèmes dessert +3560070970889 EPICERIE Desserts a preparer +3560070971572 PRODUITS FRAIS Autres yaourts +3560070971602 PRODUITS FRAIS Yaourts aux fruits +3560070971848 PRODUITS FRAIS Yaourts sante et biologique à base de soja +3560070971909 PRODUITS FRAIS Autres yaourts +3560070972180 EPICERIE Conserves de Sardines +3560070975501 PRODUITS FRAIS Fromages frais aromatises +3560070975518 PRODUITS FRAIS Fromages frais aromatises +3560070975525 PRODUITS FRAIS Crèmes dessert +3560070975556 PRODUITS FRAIS Crèmes dessert +3560070976263 EPICERIE Conserves Plats cuisines base de viande +3560070976713 PRODUITS FRAIS Pains de mie élaboré +3560070977048 PRODUITS FRAIS Surimi +3560070981014 PRODUITS FRAIS Patisseries industrielles individuelles +3560070981281 PRODUITS FRAIS Fromage fondu type tranchette +3560071094904 EPICERIE ,Cakes aux fruits,, fourres, +3560070981540 EPICERIE Confiserie et chocolats noel +3560070981700 PRODUITS FRAIS Raclette +3560070981823 EPICERIE Conserves de Maquereaux +3560070981854 EPICERIE Conserves de Maquereaux +3560071094997 PRODUITS FRAIS Pates fourrees +3560070981885 EPICERIE Conserves de Maquereaux +3560070981915 EPICERIE Conserves de Maquereaux +3560070982165 PRODUITS FRAIS Raclette +3560071095277 EPICERIE Desserts a preparer +3560071095284 EPICERIE Desserts a preparer +3560071095291 EPICERIE Desserts a preparer +3560071095307 EPICERIE Produits diététiques Autres sucrés +3560071095338 PRODUITS FRAIS ,Langoustes,, homards,, crabes surgelés, +3560071095338 PRODUITS FRAIS ,Langoustes,, homards,, crabes surgelés, +3560070983278 EPICERIE Biscuits sucrés Aux fruits +3560070984046 EPICERIE Confiserie de chocolat +3560070984305 PRODUITS FRAIS Pains précuits +3560070989508 PRODUITS FRAIS Autres produits surgelés +3560070995110 PRODUITS FRAIS Autres patisseries et gateaux industriels +3560070995141 PRODUITS FRAIS Autres patisseries et gateaux industriels +3560070998258 EPICERIE Conserves Asperges +3560070998364 EPICERIE Conserves Asperges +3560071000042 EPICERIE Pochon humide chat +3560071000059 EPICERIE Pochon humide chat +3560071000417 EPICERIE Mueslis +3560071002299 EPICERIE Cafés solubles +3560071002343 EPICERIE Autres mélanges de légumes +3560071095734 EPICERIE ,Pains grilles,,toasts,,tartines, +3560071002756 PRODUITS FRAIS ,Patés,, terrines, +3560071003067 PRODUITS FRAIS Pates fourrees +3560071003128 PRODUITS FRAIS Desserts - Mousses +3560071095772 PRODUITS FRAIS Autres desserts glacés +3560071095789 PRODUITS FRAIS Autres desserts glacés +3560071003210 PRODUITS FRAIS Jambons crus +3560071003227 PRODUITS FRAIS Autre Charcuterie à cuire +3560071003401 PRODUITS FRAIS Noix st jacques/petoncle/coquilles surgelés +3560071003562 EPICERIE Blé / Quinoa / Autres céréales +3560071003616 PRODUITS FRAIS Plat cuis./préparé avec viande +3560071003661 PRODUITS FRAIS Pates à tarte fraiches +3560071003708 LIQUIDES Jus de mélange de fruits à base de conc. +3560071003715 LIQUIDES Jus de pomme à base de concentré +3560071003722 LIQUIDES Purs Jus de Fruits - Orange +3560071003876 PRODUITS FRAIS Dessert patissier +3560071003913 PRODUITS FRAIS Yaourts natures +3560071003920 PRODUITS FRAIS Autres yaourts +3560071003968 PRODUITS FRAIS Autres yaourts +3560071004156 PRODUITS FRAIS Yaourts a boire +3560071004286 LIQUIDES Bières Blondes +3560071004293 LIQUIDES Bières Blondes +3560071004309 LIQUIDES Bières Spéciales +3560071004316 LIQUIDES Bières Spéciales +3560071004323 LIQUIDES Bières Spéciales +3560071096403 PRODUITS FRAIS Légumes cuisines/ Purées / Gratins +3560071004514 PRODUITS FRAIS Fromages blanc allegés +3560071004545 EPICERIE Potages liquides +3560071004552 EPICERIE Potages liquides +3560071004576 EPICERIE Boite individuelle humide chat +3560071004774 PRODUITS FRAIS Poissons surgelés et preparations panee +3560071004972 LIQUIDES Bières Panaches +3560071005061 PRODUITS FRAIS Plat cuis./préparé avec viande +3560071005078 PRODUITS FRAIS Plat cuis./prépar.pate légume +3560071005184 EPICERIE Miels +3560071005252 EPICERIE Pates à tartiner chocolat +3560071005269 EPICERIE Mueslis +3560071005641 EPICERIE Pates à tartiner chocolat +3560071005672 EPICERIE Pates à tartiner chocolat +3560071005726 EPICERIE Mueslis +3560071005771 EPICERIE Bonbons gélifiés +3560071096977 PRODUITS FRAIS Traiteur sucré +3560071005917 PRODUITS FRAIS Plats cuisinés surgelés - a base de volaile +3560071006129 PRODUITS FRAIS Autres yaourts +3560071006303 LIQUIDES Jus de fruits frais et légumes - Pur jus +3560071006310 EPICERIE ,Chocolat patissier,,couverture, +3560071006389 PRODUITS FRAIS Pizzas surgelées - Feu de bois +3560071006396 LIQUIDES Bières Blondes +3560071006419 EPICERIE Autres graines salees +3560071006433 EPICERIE Mueslis +3560071006525 PRODUITS FRAIS Autres fromages fondus +3560071006563 EPICERIE Cafés solubles +3560071006587 EPICERIE Autres céréales +3560071006860 PRODUITS FRAIS ,Brioche,, buns,, specialite individuelle, +3560071006877 PRODUITS FRAIS ,Brioche,, buns,, specialite individuelle, +3560071007300 EPICERIE Autres produits apéritifs à tartiner +3560071007317 PRODUITS FRAIS Jambons crus +3560071007461 PRODUITS FRAIS Bacs Sorbets +3560071097523 PRODUITS FRAIS Autres produits surgelés +3560071007850 PRODUITS FRAIS Bacs Crèmes Glacées +3560071097585 EPICERIE Biscuits sucrés Aux fruits +3560071097615 EPICERIE Biscuits sucrés Aux fruits +3560071097875 PRODUITS FRAIS Pains hamburgers et hot-dogs +3560071008192 EPICERIE Conserves de Salades de thon et autres +3560071008208 EPICERIE Conserves de Salades de thon et autres +3560071008215 EPICERIE Conserves de Salades de thon et autres +3560071008307 PRODUITS FRAIS Fromage fondu type tranchette +3560071008376 EPICERIE Conserves Asperges +3560071008383 EPICERIE Conserves Asperges +3560071008390 EPICERIE Conserves Asperges +3560071008413 EPICERIE Conserves Asperges +3560071008420 EPICERIE Conserves Asperges +3560071008437 EPICERIE Conserves Asperges +3560071008529 LIQUIDES Autres boissons non-gazeifiees Aux fruits +3560071008536 LIQUIDES Autres boissons non-gazeifiees Aux fruits +3560071008574 EPICERIE Pistaches +3560071008604 PRODUITS FRAIS Fromages frais aromatises +3560071008611 PRODUITS FRAIS Fromages frais aromatises +3560071008628 PRODUITS FRAIS Fromages frais aromatises +3560071008710 EPICERIE Minerale +3560071008840 EPICERIE Friandise chien +3560071098407 PRODUITS FRAIS Plats cuisinés surgelés - a base de pates +3560071098414 PRODUITS FRAIS Plats cuisinés surgelés - a base de pates +3560071098421 PRODUITS FRAIS Pizzas surgelées - Standard +3560071098438 PRODUITS FRAIS Pizzas surgelées - Standard +3560071008864 PRODUITS FRAIS Crèmes dessert +3560071008871 PRODUITS FRAIS Crèmes dessert +3560071008888 PRODUITS FRAIS Crèmes dessert +3560071008970 LIQUIDES Autres boissons non-gazeifiees Aux fruits +3560071098629 PRODUITS FRAIS Crèmes dessert +3560071008987 LIQUIDES Autres fruits gazéifiées +3560071009014 LIQUIDES Limonades gazéifiées +3560071009038 LIQUIDES Boissons colas - Colas +3560071009120 LIQUIDES Autres boissons non-gazeifiees Aux fruits +3560071009298 EPICERIE Pochon humide chat +3560071009304 EPICERIE Pochon humide chat +3560071009380 PRODUITS FRAIS Charcuterie tranchée autres +3560071009496 PRODUITS FRAIS Saumon fumés +3560071009632 PRODUITS FRAIS CoCompotes d autres fruits +3560071009649 PRODUITS FRAIS CoCompotes d autres fruits +3560071009656 PRODUITS FRAIS CoCompotes d autres fruits +3560071009717 EPICERIE Pates à tartiner chocolat +3560071009724 EPICERIE Boite individuelle humide chat +3560071010034 PRODUITS FRAIS Patisseries industrielles - Madeleines +3560071010058 PRODUITS FRAIS Autres pains industriels +3560071010065 PRODUITS FRAIS Patisseries industrielles - Madeleines +3560071010171 EPICERIE Bte multi variétés humide chat +3560071010195 EPICERIE Conserves Asperges +3560071010355 EPICERIE Conserves Asperges +3560071099206 PRODUITS FRAIS Autres cremes +3560071010362 EPICERIE Conserves Asperges +3560071010546 PRODUITS FRAIS Frites surgelées +3560071099244 PRODUITS FRAIS Surimi +3560071099244 PRODUITS FRAIS Surimi +3560071099251 PRODUITS FRAIS Surimi +3560071099251 PRODUITS FRAIS Surimi +3560071010560 PRODUITS FRAIS Autres pates pressees +3560071010652 EPICERIE Potages liquides +3560071099404 EPICERIE Biscuits sucrés Secs +3560071010676 EPICERIE Confitures d autres fruits +3560071010980 EPICERIE Bonbons gélifiés +3560071099527 PRODUITS FRAIS Autres produits traiteur frais +3560071011000 PRODUITS FRAIS Spec.sucree dont crepe gauffre +3560071099671 EPICERIE Cafés moulus +3560071099701 EPICERIE Cafés moulus +3560071099732 EPICERIE Cafés moulus +3560071099763 EPICERIE Cafés moulus +3560071011062 EPICERIE Infusions parfumées +3560071011086 PRODUITS FRAIS Lardons +3560071100001 PRODUITS FRAIS Autres produits traiteur frais +3560071011109 PRODUITS FRAIS Jambons cuits +3560071011260 PRODUITS FRAIS Poissons surgelés et preparations panee +3560071011390 PRODUITS FRAIS Autre Charcuterie à cuire +3560071011451 EPICERIE Potages liquides +3560071011468 EPICERIE Barres céréalières +3560071011475 EPICERIE Barres céréalières +3560071103071 EPICERIE Conserves de mais +3560071011970 EPICERIE Cafés moulus +3560071011994 EPICERIE Cafés en dosettes +3560071012090 EPICERIE Cafés en dosettes +3560071012113 EPICERIE Cappuccino +3560071012120 EPICERIE Cappuccino +3560071012243 EPICERIE Biscuits sucrés Fourres +3560071109226 EPICERIE Confiserie et chocolats paques +3560071109400 EPICERIE Confiserie et chocolats paques +3560071012496 PRODUITS FRAIS Pizzas +3560071012564 EPICERIE Riz parfumés (Basmati & Thaï) +3560071012632 EPICERIE Melanges graines salees +3560071012717 PRODUITS FRAIS Gateaux glacés à partager +3560071012854 PRODUITS FRAIS Lardons +3560071012861 PRODUITS FRAIS Lardons +3560071013080 EPICERIE Mueslis +3560071013097 EPICERIE Mueslis +3560071013127 EPICERIE Autres céréales +3560071013141 EPICERIE Autres céréales +3560071013356 PRODUITS FRAIS Laits longue conservation natu +3560071013509 LIQUIDES Autres boissons non-gazeifiees Au thé +3560071013523 LIQUIDES Autres boissons non-gazéifiées +3560071013554 PRODUITS FRAIS Plats cuisinés surgelés - a base de viande +3560071013561 PRODUITS FRAIS Plats cuisinés surgelés - a base de volaile +3560071013707 EPICERIE Boissons chocolatées instantanées +3560071013837 PRODUITS FRAIS Charc.volaille et autre viande +3560071013875 PRODUITS FRAIS Saucisses de strasbourg +3560071014131 PRODUITS FRAIS Crèmes dessert +3560071014162 PRODUITS FRAIS ,Crèmes aux œufs,, petits pot crème, +3560071014339 EPICERIE Pâtes alimentaires sèches Spécialités +3560071014476 PRODUITS FRAIS Fromages de chevre +3560071014513 PRODUITS FRAIS Jambons cuits +3560071014520 PRODUITS FRAIS Jambons cuits +3560071114534 LIQUIDES Rhums blancs +3560071014537 PRODUITS FRAIS Jambons cuits +3560071014582 LIQUIDES Jus de fruits frais et légumes - Pur jus +3560071014599 LIQUIDES Jus de fruits frais et légumes - Pur jus +3560071014650 PRODUITS FRAIS Liégeois +3560071014728 EPICERIE Corn flakes +3560071014735 PRODUITS FRAIS Autres produits traiteur frais +3560071014964 PRODUITS FRAIS Charcuterie tranchée autres +3560071015077 PRODUITS FRAIS Plats cuisinés surgelés - a base de viande +3560071117085 EPICERIE Produits diététiques Autres sucrés +3560071117115 EPICERIE Produits diététiques Autres sucrés +3560071117146 EPICERIE Produits diététiques Autres salés +3560071117177 EPICERIE Produits diététiques Autres salés +3560071117207 EPICERIE Produits diététiques Autres salés +3560071117238 EPICERIE Produits diététiques Autres salés +3560071015145 PRODUITS FRAIS Autres produits surgelés +3560071015190 PRODUITS FRAIS Frites surgelées +3560071015329 EPICERIE Cappuccino +3560071119317 EPICERIE Huiles Olive +3560071015411 PRODUITS FRAIS Yaourts a boire +3560071015428 PRODUITS FRAIS Yaourts a boire +3560071015664 EPICERIE Ketchup +3560071015992 PRODUITS FRAIS Dessert patissier +3560071016029 EPICERIE Conserves Artichauts +3560071016142 PRODUITS FRAIS Patisseries salees surgelées +3560071016180 EPICERIE Biscuits sucrés Secs +3560071016432 PRODUITS FRAIS Fromages de chevre +3560071016852 PRODUITS FRAIS Autres produits surgelés +3560071016920 PRODUITS FRAIS Yaourts sante et biologique à base de soja +3560071017576 PRODUITS FRAIS Desserts - Mousses +3560071017668 PRODUITS FRAIS Crèmes dessert +3560071017835 PRODUITS FRAIS Saumon fumés +3560071018023 EPICERIE Pistaches +3560071018047 PRODUITS FRAIS Fromages de chevre +3560071018269 PRODUITS FRAIS Yaourts a boire +3560071018276 PRODUITS FRAIS Yaourts a boire +3560071125769 EPICERIE ,Capres,, pickles, +3560071125790 EPICERIE ,Capres,, pickles, +3560071125820 EPICERIE ,Capres,, pickles, +3560071125851 EPICERIE Cornichons +3560071125882 EPICERIE Cornichons +3560071018283 PRODUITS FRAIS Yaourts a boire +3560071018290 PRODUITS FRAIS Yaourts a boire +3560071018566 EPICERIE Barres céréalières +3560071018627 PRODUITS FRAIS Liégeois +3560071126469 EPICERIE Moutardes +3560071126865 EPICERIE Confiserie et chocolats noel +3560071018634 PRODUITS FRAIS Jambons cuits +3560071018702 PRODUITS FRAIS Glaces Batonnets +3560071018719 PRODUITS FRAIS Glaces Batonnets +3560071018740 PRODUITS FRAIS Glaces Batonnets +3560071018795 PRODUITS FRAIS Glaces Cones et cornets +3560071018900 PRODUITS FRAIS Autres saucisses +3560071018917 PRODUITS FRAIS Autres saucisses +3560071019143 PRODUITS FRAIS Yaourts a boire +3560071128777 EPICERIE Confiserie et chocolats noel +3560071019150 PRODUITS FRAIS Yaourts a boire +3560071019167 PRODUITS FRAIS Yaourts a boire +3560071128845 EPICERIE Confiserie et chocolats noel +3560071019174 PRODUITS FRAIS Yaourts a boire +3560071019181 PRODUITS FRAIS Yaourts a boire +3560071019198 PRODUITS FRAIS Yaourts a boire +3560071019266 LIQUIDES Jus d'ananas à base de concentré +3560071019334 EPICERIE Compotes pots / coupelles +3560071019686 PRODUITS FRAIS Autres legumes surgelés +3560071019723 PRODUITS FRAIS Légumes verts surgelés +3560071019747 PRODUITS FRAIS Mélanges de legumes/garniture surgelés +3560071019853 PRODUITS FRAIS Fromage fondu type tranchette +3560071130794 PRODUITS FRAIS Patisseries industrielles individuelles +3560071130824 EPICERIE Sauces chaudes à base de tomate et tomate frito +3560071130824 EPICERIE Sauces chaudes à base de tomate et tomate frito +3560071028312 PRODUITS FRAIS Patisseries industrielles individuelles +3560071028343 PRODUITS FRAIS Patisseries industrielles - Madeleines +3560071028374 PRODUITS FRAIS Crèmes fraiches epaisses +3560071029050 EPICERIE Conserves Asperges +3560071132903 EPICERIE Conserves de Petits pois +3560071132934 EPICERIE Conserves de Petits pois carottes +3560071033682 PRODUITS FRAIS Baies et fruits entiers surgelés +3560071133597 EPICERIE Conserves de Petits pois +3560071033712 PRODUITS FRAIS Baies et fruits entiers surgelés +3560071033774 PRODUITS FRAIS Cocktails de fruits surgelés +3560071134563 EPICERIE Conserves de mais +3560071033835 PRODUITS FRAIS Baies et fruits entiers surgelés +3560071034542 PRODUITS FRAIS Charcuterie tranchée autres +3560071037758 PRODUITS FRAIS Herbes et assaisonnements surgelés +3560071037789 PRODUITS FRAIS Champignons surgelés +3560071038137 EPICERIE Confiserie et chocolats paques +3560071137748 EPICERIE Conserves de Champignons - Autres +3560071137779 EPICERIE Conserves de Champignons - Autres +3560071137809 EPICERIE Conserves de Champignons - Autres +3560071045555 EPICERIE Conserves de Poires +3560071048112 EPICERIE Barres chocolatees +3560071048310 EPICERIE Biscuits sucrés Aux fruits +3560071048341 EPICERIE Biscuits sucrés Aux fruits +3560071138769 EPICERIE Confiserie et chocolats paques +3560071138790 EPICERIE Confiserie et chocolats paques +3560071138851 EPICERIE Confiserie et chocolats paques +3560071139315 EPICERIE Conserves de Petits pois +3560071139346 EPICERIE Conserves de Haricots verts +3560071048563 EPICERIE Biscuits sucrés Au chocolat +3560071049799 EPICERIE Biscuits sucrés Fourres +3560071050115 EPICERIE Conserves de Tomates - Concentré +3560071055158 PRODUITS FRAIS Salades +3560071057404 PRODUITS FRAIS Patisseries industrielles - Madeleines +3560071063412 EPICERIE ,Gateaux roules,, fourres, +3560071067021 PRODUITS FRAIS Patisseries salees surgelées +3560071150013 PRODUITS FRAIS Jambons crus +3560071150020 PRODUITS FRAIS Jambons crus +3560071067533 PRODUITS FRAIS Autres produits surgelés +3560071150242 EPICERIE Cafés en grains +3560071150273 EPICERIE Cafés en grains +3560071150303 EPICERIE Cafés en grains +3560071150334 EPICERIE Infusions classiques +3560071150419 PRODUITS FRAIS Beurres Sans sel +3560071150426 PRODUITS FRAIS Beurres Sales +3560071150433 EPICERIE Autres graines salees +3560071150464 EPICERIE Infusions parfumées +3560071150495 EPICERIE Infusions parfumées +3560071071264 EPICERIE Confiserie et chocolats noel +3560071150525 EPICERIE ,Amandes,, noisettes,, noix, +3560071150556 EPICERIE ,Amandes,, noisettes,, noix, +3560071150587 EPICERIE ,Amandes,, noisettes,, noix, +3560071150617 EPICERIE ,Amandes,, noisettes,, noix, +3560071150648 EPICERIE Autres graines salees +3560071150679 EPICERIE Mélanges graines et fruits +3560071150709 EPICERIE Mélanges graines et fruits +3560071150730 EPICERIE Mélanges graines et fruits +3560071150792 PRODUITS FRAIS Patisseries salees surgelées +3560071151010 PRODUITS FRAIS Dessert patissier +3560071151027 PRODUITS FRAIS Dessert patissier +3560071072797 PRODUITS FRAIS Autres legumes surgelés +3560071075439 PRODUITS FRAIS Autres patisseries et gateaux industriels +3560071075873 PRODUITS FRAIS Herbes et assaisonnements surgelés +3560071075903 PRODUITS FRAIS Herbes et assaisonnements surgelés +3560071075934 PRODUITS FRAIS Autres légumes surgelés et soupes - Soupes +3560071076191 PRODUITS FRAIS Autres produits traiteur frais +3560071076221 PRODUITS FRAIS Autres produits traiteur frais +3560071076252 PRODUITS FRAIS Autres produits traiteur frais +3560071151225 PRODUITS FRAIS Autres produits preparés +3560071080013 PRODUITS FRAIS Fromages frais - Spécialité italienne +3560071151300 PRODUITS FRAIS Crèmes sucrées +3560071151317 PRODUITS FRAIS Crèmes sucrées +3560071151324 PRODUITS FRAIS Corps gras de cuisine +3560071151393 PRODUITS FRAIS Autres produits preparés +3560071151409 PRODUITS FRAIS Autres produits preparés +3560071080068 EPICERIE Vegetale +3560071151423 EPICERIE Biscuits sucrés Cookies +3560071080082 EPICERIE Conserves de Haricots verts cueillis et rangés main +3560071080099 EPICERIE Conserves de Haricots verts cueillis et rangés main +3560071080105 EPICERIE Conserves de Haricots verts cueillis et rangés main +3560071080488 EPICERIE Autres graines salees +3560071080495 EPICERIE Autres graines salees +3560071080518 PRODUITS FRAIS Pates à tarte fraiches +3560071080563 EPICERIE Conserves de Fruits melanges +3560071080570 EPICERIE Conserves de Fruits melanges +3560071080587 EPICERIE Conserves de Fruits melanges +3560071080594 PRODUITS FRAIS Plats cuisinés surgelés - poisson/fruit m +3560071080600 PRODUITS FRAIS Autres preparations base poisson surgelés +3560071080969 PRODUITS FRAIS Autres saucisses +3560071081157 PRODUITS FRAIS Spec.sucree dont crepe gauffre +3560071081225 EPICERIE Infusions parfumées +3560071081232 EPICERIE Thés parfumés +3560071081249 EPICERIE Thés parfumés +3560071081256 EPICERIE Thés natures +3560071081263 EPICERIE Thés parfumés +3560071081270 EPICERIE Thés parfumés +3560071081287 EPICERIE Thés parfumés +3560071081317 PRODUITS FRAIS Légumes verts surgelés +3560071081751 EPICERIE Blé / Quinoa / Autres céréales +3560071081799 PRODUITS FRAIS Autres pains industriels +3560071081812 PRODUITS FRAIS Panettone/brioche/prd tranche +3560071081829 PRODUITS FRAIS Spec.sucree dont crepe gauffre +3560071152161 PRODUITS FRAIS Bœuf haché / Préparation / Découpe +3560071081911 PRODUITS FRAIS Fromages de chevre +3560071152215 EPICERIE Desserts a preparer +3560071081966 PRODUITS FRAIS Emmentals rapes +3560071081973 PRODUITS FRAIS Emmentals blocs +3560071082109 PRODUITS FRAIS Autres préparations de fruits surgelés +3560071152277 EPICERIE Epices et herbes +3560071152307 EPICERIE Epices et herbes +3560071152338 EPICERIE Epices et herbes +3560071152369 EPICERIE Epices et herbes +3560071082116 PRODUITS FRAIS Autres préparations de fruits surgelés +3560071082123 PRODUITS FRAIS Autres préparations de fruits surgelés +3560071082192 PRODUITS FRAIS ,Jus,, pulpes et coulis de fruit surgelés, +3560071082208 EPICERIE Bte multi variétés humide chat +3560071082215 EPICERIE Bte multi variétés humide chat +3560071082260 EPICERIE Dentaire +3560071082277 EPICERIE Dentaire +3560071082284 PRODUITS FRAIS Cocktails de fruits surgelés +3560071082291 PRODUITS FRAIS Cocktails de fruits surgelés +3560071082307 PRODUITS FRAIS Cocktails de fruits surgelés +3560071082314 PRODUITS FRAIS Cocktails de fruits surgelés +3560071082321 PRODUITS FRAIS Cocktails de fruits surgelés +3560071082352 EPICERIE Miels +3560071082369 EPICERIE Miels +3560071082376 PRODUITS FRAIS Pizzas surgelées - Standard +3560071082383 PRODUITS FRAIS Pizzas surgelées - Standard +3560071082390 PRODUITS FRAIS Pizzas surgelées - Standard +3560071082581 PRODUITS FRAIS Glaces Batonnets +3560071082611 EPICERIE Pochon humide chat +3560071082673 EPICERIE ,Gateaux roules,, fourres, +3560071082680 EPICERIE ,Gateaux roules,, fourres, +3560071082697 EPICERIE Pâtes alimentaires sèches +3560071082741 EPICERIE Potages liquides +3560071082758 EPICERIE Potages liquides +3560071082765 EPICERIE Biscuits sucrés Secs +3560071082819 EPICERIE Biscuits sucrés Au chocolat +3560071082833 EPICERIE Snacks: Produits souffles et extrudes +3560071082918 PRODUITS FRAIS Glaces Cones et cornets +3560071082925 PRODUITS FRAIS Glaces Cones et cornets +3560071153113 EPICERIE Desserts a preparer +3560071082970 EPICERIE Snacks: Produits souffles et extrudes +3560071083014 EPICERIE Biscuits sucrés Secs +3560071083021 EPICERIE Biscuits sucrés Secs +3560071153373 PRODUITS FRAIS Bacs Crèmes Glacées +3560071153403 PRODUITS FRAIS Bacs Crèmes Glacées +3560071083052 PRODUITS FRAIS ,Quiches,, tartes,, tourtes surgelées, +3560071083151 LIQUIDES Whiskies écossais pur malt +3560071083168 LIQUIDES Whiskies écossais pur malt +3560071083267 EPICERIE Conserves Plats cuisines base de viande +3560071083274 EPICERIE Conserves Plats cuisines base de viande +3560071083281 EPICERIE Conserves Plats cuisines base de viande +3560071083397 PRODUITS FRAIS Rillettes +3560071083427 PRODUITS FRAIS Lardons +3560071083434 PRODUITS FRAIS Lardons +3560071083441 PRODUITS FRAIS Lardons +3560071083458 PRODUITS FRAIS Autre Charcuterie à cuire +3560071083465 EPICERIE Biscuits sucrés Secs +3560071083472 EPICERIE Biscuits sucrés Secs +3560071083489 PRODUITS FRAIS Bacs Crèmes Glacées +3560071083526 EPICERIE Conserves de Sardines +3560071083533 EPICERIE Conserves de Sardines +3560071083540 EPICERIE Conserves de Thon +3560071083564 EPICERIE Biscuits sucrés Cookies +3560071083571 EPICERIE Biscuits sucrés Cookies +3560071083618 LIQUIDES Jus de mélange de fruits à base de conc. +3560071083786 PRODUITS FRAIS Pizzas +3560071083793 PRODUITS FRAIS Pizzas +3560071083809 PRODUITS FRAIS Pizzas +3560071083816 PRODUITS FRAIS Pizzas +3560071083854 PRODUITS FRAIS Bacs Crèmes Glacées +3560071083861 EPICERIE Shampoings +3560071083878 EPICERIE Pipettes +3560071083885 EPICERIE Collier +3560071083892 EPICERIE Pipettes +3560071083908 EPICERIE Gouttes +3560071083915 EPICERIE Colliers +3560071083922 PRODUITS FRAIS Bacs Crèmes Glacées +3560071083960 EPICERIE ,Patisseries indiv,, madeleines, +3560071083977 PRODUITS FRAIS Jambons crus +3560071083984 PRODUITS FRAIS Surimi +3560071083991 EPICERIE Noix de cajou +3560071084042 EPICERIE Cacahuetes +3560071084059 EPICERIE Cacahuetes +3560071084127 EPICERIE Agglomerante +3560071084134 EPICERIE Minerale +3560071084141 EPICERIE Minerale +3560071084486 LIQUIDES Sirops concentrés à base de fruits +3560071085117 PRODUITS FRAIS Pizzas surgelées - Cuite sur pierre +3560071085193 EPICERIE Blé / Quinoa / Autres céréales +3560071085216 EPICERIE Conserves de Sardines +3560071085254 EPICERIE Melanges graines salees +3560071085261 EPICERIE Melanges graines salees +3560071085278 EPICERIE Melanges graines salees +3560071085285 EPICERIE Melanges graines salees +3560071085292 EPICERIE Melanges graines salees +3560071156695 EPICERIE Cafés en grains +3560071085513 EPICERIE Potages liquides +3560071085605 PRODUITS FRAIS Yaourts natures +3560071085612 PRODUITS FRAIS Yaourts natures +3560071085629 PRODUITS FRAIS Yaourts aromatises +3560071085667 EPICERIE ,Chocolat patissier,,couverture, +3560071085735 PRODUITS FRAIS Assortiment tranche +3560071085759 PRODUITS FRAIS Autres produits traiteur frais +3560071085773 EPICERIE Thés parfumés +3560071085858 EPICERIE Conserves de Thon +3560071085865 EPICERIE Conserves de Thon +3560071085872 EPICERIE Conserves de Thon +3560071085889 EPICERIE Conserves de Thon +3560071085995 PRODUITS FRAIS Yaourts a boire +3560071086008 EPICERIE Pâtes alimentaires sèches +3560071086138 PRODUITS FRAIS Salades +3560071086145 PRODUITS FRAIS Salades +3560071157906 EPICERIE Conserves Asperges +3560071086152 PRODUITS FRAIS Salades +3560071086206 PRODUITS FRAIS Bœuf haché / Préparation / Découpe +3560071086244 EPICERIE Autres graines salees +3560071086305 EPICERIE Conserves d'Ananas +3560071086312 PRODUITS FRAIS Libre service - Produits carnes prepares +3560071086329 PRODUITS FRAIS Libre service - Produits carnes prepares +3560071158835 EPICERIE Boite humide chien +3560071086411 PRODUITS FRAIS Plats cuisinés surgelés - specialites +3560071086596 PRODUITS FRAIS Libre service - Produits carnes prepares +3560071090593 EPICERIE Conserves Asperges +3560071090715 EPICERIE Potages liquides +3560071090838 EPICERIE Biscuits sucrés Cookies +3560071091026 EPICERIE Autres céréales +3560071091163 PRODUITS FRAIS Spec.sucree dont crepe gauffre +3560071091224 LIQUIDES Jus de fruits frais et légumes - Pur jus +3560071091231 LIQUIDES Jus de fruits frais et légumes - Pur jus +3560071091255 LIQUIDES Jus de fruits frais et légumes - Pur jus +3560071160876 EPICERIE Vinaigres +3560071160883 EPICERIE Vinaigres +3560071092061 PRODUITS FRAIS Yaourts a boire +3560071092078 PRODUITS FRAIS Yaourts a boire +3560071092085 EPICERIE Biscuits sucrés Au chocolat +3560071092122 EPICERIE Thés parfumés +3560071092177 PRODUITS FRAIS Mélanges de legumes/garniture surgelés +3560071092245 PRODUITS FRAIS Yaourts a boire +3560071092252 EPICERIE Infusions classiques +3560071092283 EPICERIE Infusions classiques +3560071092320 EPICERIE Autres graines salees +3560071161668 EPICERIE Conserves de Haricots blancs +3560071092771 LIQUIDES Bières Spécialité +3560071092788 PRODUITS FRAIS Pizzas surgelées - Standard +3560071092795 PRODUITS FRAIS Pizzas surgelées - Standard +3560071092801 PRODUITS FRAIS Pizzas surgelées - Standard +3560071092818 PRODUITS FRAIS Pizzas surgelées - Standard +3560071093563 EPICERIE Conserves Asperges +3560071162788 PRODUITS FRAIS Jambons cuits +3560071093587 EPICERIE Conserves Asperges +3560071093617 EPICERIE Conserves Asperges +3560071093679 EPICERIE Autres mélanges de légumes +3560071093747 PRODUITS FRAIS Fromages de chevre +3560071094065 PRODUITS FRAIS Dessert patissier +3560071094096 PRODUITS FRAIS Surimi +3560071094188 EPICERIE Croquettes sec +3560071094218 EPICERIE Croquettes sec +3560071094300 EPICERIE Conserves de Petits pois carottes +3560071094324 EPICERIE Conserves de Petits pois +3560071094379 PRODUITS FRAIS Plats cuisinés surgelés - specialites +3560071094416 PRODUITS FRAIS Autres produits traiteur frais +3560071094454 EPICERIE Autres farines +3560071094492 EPICERIE Conserves de Thon +3560071094522 EPICERIE Conserves de Thon +3560071094553 EPICERIE Conserves de Thon +3560071094638 PRODUITS FRAIS Pains industriels - Spécialités étrangères +3560071094683 PRODUITS FRAIS Patisseries et tartes surgelées +3560071094935 EPICERIE Riz blanchis +3560071094942 EPICERIE Riz blanchis +3560071095215 EPICERIE Barres céréalières +3560071095246 EPICERIE Barres céréalières +3560071095420 PRODUITS FRAIS Autres produits surgelés +3560071095451 PRODUITS FRAIS Autres produits surgelés +3560071095574 EPICERIE ,Pains grilles,,toasts,,tartines, +3560071095598 EPICERIE Barres céréalières +3560071095628 EPICERIE Barres céréalières +3560071095659 EPICERIE Barres céréalières +3560071095741 PRODUITS FRAIS Foie gras +3560071095758 PRODUITS FRAIS Foie gras +3560071095765 PRODUITS FRAIS Autre Charcuterie à cuire +3560071095796 EPICERIE Conserves de Thon +3560071095826 EPICERIE Conserves de Thon +3560071095857 EPICERIE Conserves de Thon +3560071095888 EPICERIE Conserves de Thon +3560071095918 EPICERIE Conserves de Thon +3560071095949 EPICERIE Conserves de Thon +3560071095970 EPICERIE Conserves de Thon +3560071164355 EPICERIE Epices et herbes +3560071096007 EPICERIE Conserves de Thon +3560071096038 EPICERIE Conserves de Thon +3560071096069 EPICERIE Conserves de Thon +3560071096090 EPICERIE ,Cakes aux fruits,, fourres, +3560071096182 EPICERIE ,Cakes aux fruits,, fourres, +3560071164607 PRODUITS FRAIS Patisseries industrielles individuelles +3560071096212 EPICERIE ,Cakes aux fruits,, fourres, +3560071164638 PRODUITS FRAIS Patisseries industrielles individuelles +3560071096274 PRODUITS FRAIS Jambons cuits +3560071096281 PRODUITS FRAIS Jambons cuits +3560071096298 PRODUITS FRAIS Jambons cuits +3560071096304 PRODUITS FRAIS Jambons cuits +3560071096311 PRODUITS FRAIS Jambons cuits +3560071096458 PRODUITS FRAIS Champignons surgelés +3560071096489 PRODUITS FRAIS Entrées exotiques +3560071096625 EPICERIE Biscuits sucrés - Assortiments +3560071165857 PRODUITS FRAIS Salades +3560071165864 PRODUITS FRAIS Salades +3560071165871 PRODUITS FRAIS Salades +3560071165888 PRODUITS FRAIS Salades +3560071165895 PRODUITS FRAIS Salades +3560071165925 PRODUITS FRAIS Sandwichs +3560071165932 PRODUITS FRAIS Sandwichs +3560071165949 PRODUITS FRAIS Traiteur sucré +3560071168384 EPICERIE Conserves Plats cuisines base de viande +3560071168414 EPICERIE Sec chat +3560071168506 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560071168544 PRODUITS FRAIS Noix st jacques/petoncle/coquilles surgelés +3560071168582 EPICERIE Friandise chat +3560071168612 EPICERIE Friandise chien +3560071168674 EPICERIE Autres céréales +3560071168704 EPICERIE Autres céréales +3560071096946 EPICERIE Conserves d'Autres poissons +3560071169107 PRODUITS FRAIS Libre service - Poulets +3560071096984 EPICERIE ,Pains grilles,,toasts,,tartines, +3560071096991 EPICERIE ,Pains grilles,,toasts,,tartines, +3560071097028 EPICERIE ,Pains grilles,,toasts,,tartines, +3560071097066 EPICERIE Barres céréalières +3560071097097 EPICERIE Barres céréalières +3560071097127 EPICERIE Barres céréalières +3560071169411 PRODUITS FRAIS Bacs Crèmes Glacées +3560071097158 EPICERIE Barres céréalières +3560071097189 EPICERIE Barres céréalières +3560071097271 PRODUITS FRAIS Plats cuisinés surgelés - a base de viande +3560071097288 PRODUITS FRAIS Plats cuisinés surgelés - a base de pates +3560071097295 PRODUITS FRAIS Plats cuisinés surgelés - a base de pates +3560071097318 PRODUITS FRAIS Plats cuisinés surgelés - poisson/fruit m +3560071097325 PRODUITS FRAIS Plats cuisinés surgelés - a base de volaile +3560071097424 EPICERIE Biscuits sucrés Aux fruits +3560071097455 EPICERIE Autres biscuits sucrés +3560071097486 EPICERIE Biscuits sucrés Fourres +3560071097554 EPICERIE Biscuits sucrés Au chocolat +3560071169800 PRODUITS FRAIS Salades +3560071169817 PRODUITS FRAIS Salades +3560071097882 PRODUITS FRAIS Patisseries industrielles individuelles +3560071097899 PRODUITS FRAIS Patisseries industrielles individuelles +3560071097929 PRODUITS FRAIS Pains hamburgers et hot-dogs +3560071097936 PRODUITS FRAIS Pains hamburgers et hot-dogs +3560071097967 EPICERIE Autres produits patisserie +3560071098001 PRODUITS FRAIS Autres yaourts +3560071170288 EPICERIE Conserves - Autres légumes secs +3560071170318 EPICERIE Pâtés +3560071170349 LIQUIDES Sirops concentrés - Conc. d agrumes +3560071170387 LIQUIDES Liqueurs de fruits et plantes +3560071098018 PRODUITS FRAIS Autres yaourts +3560071098025 EPICERIE Pistaches +3560071098087 PRODUITS FRAIS Plats cuisinés surgelés - poisson/fruit m +3560071098094 PRODUITS FRAIS Plats cuisinés surgelés - a base de viande +3560071098100 PRODUITS FRAIS Plats cuisinés surgelés - a base de volaile +3560071098469 PRODUITS FRAIS Plats cuisinés surgelés - a base de viande +3560071098476 PRODUITS FRAIS Plats cuisinés surgelés - poisson/fruit m +3560071098490 PRODUITS FRAIS Plats cuisinés surgelés - specialites +3560071098513 PRODUITS FRAIS Plats cuisinés surgelés - poisson/fruit m +3560071098674 PRODUITS FRAIS Crèmes fraiches epaisses +3560071170981 PRODUITS FRAIS Patisseries industrielles individuelles +3560071171049 PRODUITS FRAIS Salades +3560071171179 EPICERIE Conserves de Fruits melanges +3560071171209 EPICERIE Conserves de Fruits melanges +3560071099138 PRODUITS FRAIS Légumes cuisines/ Purées / Gratins +3560071099169 PRODUITS FRAIS Pizzas surgelées - Standard +3560071171322 EPICERIE Thés parfumés +3560071099176 PRODUITS FRAIS Pizzas surgelées - Standard +3560071099183 PRODUITS FRAIS Pizzas surgelées - Standard +3560071099190 PRODUITS FRAIS Plats cuisinés surgelés - a base de pates +3560071099213 PRODUITS FRAIS Crèmes longue conservation +3560071099220 PRODUITS FRAIS Crèmes longue conservation +3560071099367 PRODUITS FRAIS Plats cuisinés surgelés - a base de pates +3560071099503 PRODUITS FRAIS Patisseries et tartes surgelées +3560071099510 PRODUITS FRAIS Gateaux glacés à partager +3560071099664 PRODUITS FRAIS Surimi +3560071171940 PRODUITS FRAIS Patisseries et tartes surgelées +3560071171971 EPICERIE Confiserie et chocolats noel +3560071099824 EPICERIE Biscuits sucrés Fourres +3560071099947 EPICERIE Conserves Artichauts +3560071101435 LIQUIDES Sangria +3560071110239 EPICERIE Conserves Artichauts +3560071111830 EPICERIE Sauces chaudes - pâtes - riz +3560071111861 EPICERIE Sauces chaudes - pâtes - riz +3560071112974 EPICERIE Pistaches +3560071115470 EPICERIE Autre pdt confiserie de sucre +3560071119393 EPICERIE Pommes de terre +3560071120078 PRODUITS FRAIS Pizzas +3560071172855 EPICERIE Conserves de Fruits melanges +3560071174361 EPICERIE Miels +3560071174385 EPICERIE Conserves Artichauts +3560071174415 EPICERIE Conserves Asperges +3560071174446 EPICERIE Conserves Poivrons +3560071174545 LIQUIDES Purs Jus de Fruits - Autres +3560071126346 EPICERIE Vinaigres +3560071126377 EPICERIE Vinaigres +3560071126407 EPICERIE Vinaigres +3560071126438 EPICERIE Vinaigres +3560071128456 EPICERIE Conserves de mais +3560071128487 EPICERIE Conserves de mais +3560071128517 EPICERIE Conserves de Haricots verts +3560071128647 EPICERIE Conserves de Petits pois +3560071128678 EPICERIE Conserves de Haricots verts +3560071128708 EPICERIE Conserves de Petits pois +3560071128807 EPICERIE Conserves de mais +3560071128814 EPICERIE Cornichons +3560071130466 PRODUITS FRAIS Spec.sucree dont crepe gauffre +3560071130534 PRODUITS FRAIS Panettone/brioche/prd tranche +3560071134754 EPICERIE Moutardes +3560071138318 EPICERIE Conserves de mais +3560071138608 EPICERIE Huiles de friture +3560071175214 PRODUITS FRAIS Autres desserts glacés +3560071175221 EPICERIE Conserves de Thon +3560071175252 EPICERIE Conserves de Thon +3560071138639 EPICERIE Huiles de friture +3560071175375 EPICERIE Conserves de Maquereaux +3560071175405 EPICERIE ,Fruits secs,, fruits confits, +3560071175412 EPICERIE ,Aromes,, colorants,, decors, +3560071139575 EPICERIE Bonbons gélifiés +3560071139872 EPICERIE Conserves de mais +3560071139919 EPICERIE Conserves de mais +3560071150402 PRODUITS FRAIS ,Quiches,, tartes,, tourtes surgelées, +3560071150501 PRODUITS FRAIS Autres cremes +3560071151041 PRODUITS FRAIS Patisseries salees surgelées +3560071151058 PRODUITS FRAIS ,Quiches,, tartes,, tourtes surgelées, +3560071151065 PRODUITS FRAIS Patisseries salees surgelées +3560071176082 PRODUITS FRAIS Autres produits surgelés +3560071176112 PRODUITS FRAIS Autres produits surgelés +3560071176143 PRODUITS FRAIS Autres produits surgelés +3560071151072 PRODUITS FRAIS Patisseries salees surgelées +3560071151089 PRODUITS FRAIS Patisseries salees surgelées +3560071151096 PRODUITS FRAIS ,Quiches,, tartes,, tourtes surgelées, +3560071151102 PRODUITS FRAIS Patisseries industrielles - gateaux a trancher +3560071151119 PRODUITS FRAIS Patisseries industrielles - gateaux a trancher +3560071151218 PRODUITS FRAIS Entrées exotiques +3560071176426 PRODUITS FRAIS Fromages blanc aromatises / fruits +3560071176433 PRODUITS FRAIS Fromages frais - Féta +3560071176457 LIQUIDES Autres boissons non-gazeifiees Aux fruits +3560071151232 LIQUIDES Cidres +3560071151416 PRODUITS FRAIS Panés +3560071151454 PRODUITS FRAIS Plats cuisinés surgelés - a base de pates +3560071151461 PRODUITS FRAIS Pizzas surgelées - Standard +3560071151478 PRODUITS FRAIS Pizzas surgelées - Standard +3560071176624 PRODUITS FRAIS Pates natures +3560071151539 EPICERIE Pâtes alimentaires aux œufs +3560071151546 EPICERIE Pâtes alimentaires aux œufs +3560071177089 PRODUITS FRAIS Autres pâtes molles +3560071151553 EPICERIE Pâtes alimentaires aux œufs +3560071151577 EPICERIE Pâtes alimentaires aux œufs +3560071151584 EPICERIE Pâtes alimentaires aux œufs +3560071151591 EPICERIE Pâtes alimentaires aux œufs +3560071151607 EPICERIE Pâtes alimentaires aux œufs +3560071177607 PRODUITS FRAIS Yaourts a boire +3560071177614 PRODUITS FRAIS Yaourts a boire +3560071151973 EPICERIE Huiles de friture +3560071152024 PRODUITS FRAIS Panés +3560071152031 PRODUITS FRAIS Panés +3560071152048 PRODUITS FRAIS Mixte de fromages +3560071152079 PRODUITS FRAIS Mixte de fromages +3560071152116 EPICERIE Bonbons gélifiés +3560071152208 PRODUITS FRAIS Pain de mie standard +3560071152246 PRODUITS FRAIS Crèmes fraiches epaisses +3560071152253 PRODUITS FRAIS Crèmes fraiches epaisses +3560071152260 LIQUIDES Autres fruits gazéifiées +3560071177850 PRODUITS FRAIS Pates natures +3560071177867 PRODUITS FRAIS Pates natures +3560071152390 PRODUITS FRAIS Autres desserts +3560071177935 PRODUITS FRAIS Plat cuis./prépar.pate légume +3560071178000 LIQUIDES Bières Blondes +3560071178307 EPICERIE Foin +3560071178314 PRODUITS FRAIS Autres pates pressees +3560071152468 EPICERIE Edulcorants Poudre +3560071179267 EPICERIE Biscuits sucrés Fourres +3560071179359 EPICERIE Biscuits sucrés Secs +3560071179601 EPICERIE Blé / Quinoa / Autres céréales +3560071179618 EPICERIE Blé / Quinoa / Autres céréales +3560071179625 EPICERIE Semoules de ble / Couscous +3560071179632 EPICERIE Blé / Quinoa / Autres céréales +3560071179649 EPICERIE Blé / Quinoa / Autres céréales +3560071179809 EPICERIE Infusions parfumées +3560071179861 PRODUITS FRAIS Autres fromages fondus +3560071180485 PRODUITS FRAIS Yaourts sante et biologique nature +3560071180492 PRODUITS FRAIS Yaourts aux fruits +3560071180508 PRODUITS FRAIS Yaourts aux fruits +3560071180515 EPICERIE Conserves Plats cuisines base de legumes +3560071180607 EPICERIE Conserves Plats cuisines base de pates +3560071180669 EPICERIE Pâtés +3560071180713 EPICERIE Miels +3560071180744 LIQUIDES Purs Jus de Fruits - Autres +3560071180751 LIQUIDES Purs Jus de Fruits - Autres +3560071180768 LIQUIDES Purs Jus de Fruits - Autres +3560071180775 EPICERIE Snacks: Produits souffles et extrudes +3560071180782 EPICERIE Snacks: Produits souffles et extrudes +3560071180799 EPICERIE Snacks: Produits souffles et extrudes +3560071180836 EPICERIE Snacks: Produits souffles et extrudes +3560071153069 PRODUITS FRAIS Plats cuisinés surgelés - specialites +3560071181079 LIQUIDES Jus de légumes bio +3560071181086 LIQUIDES Jus d'autres fruits bio +3560071181130 LIQUIDES Purs Jus de Fruits - Autres +3560071181130 LIQUIDES Purs Jus de Fruits - Autres +3560071181185 PRODUITS FRAIS Foie gras +3560071153144 PRODUITS FRAIS Fromages blanc nature +3560071153199 EPICERIE Conserves de Peches +3560071153243 PRODUITS FRAIS Plats cuisinés surgelés - a base de viande +3560071181345 EPICERIE Chocolat tablette - noirs +3560071181376 EPICERIE Chocolat tablette - noirs +3560071181437 PRODUITS FRAIS Crèmes fraiches epaisses +3560071181468 PRODUITS FRAIS Corps gras a tartiner +3560071181512 PRODUITS FRAIS Foie gras +3560071181529 PRODUITS FRAIS Foie gras +3560071181581 EPICERIE Mayonnaise +3560071181826 PRODUITS FRAIS Autres produits traiteur frais +3560071181857 PRODUITS FRAIS Autres produits traiteur frais +3560071182090 PRODUITS FRAIS Desserts - Mousses +3560071182106 PRODUITS FRAIS Liégeois +3560071182113 PRODUITS FRAIS Liégeois +3560071182120 PRODUITS FRAIS Desserts - Mousses +3560071153939 EPICERIE Bonbons gélifiés +3560071153960 PRODUITS FRAIS Pates à tarte fraiches +3560071153977 EPICERIE Barres chocolatees +3560071154004 EPICERIE Barres chocolatees +3560071154042 PRODUITS FRAIS Yaourts sante et biologique aux fruits +3560071154059 PRODUITS FRAIS Yaourts sante et biologique aux fruits +3560071154066 PRODUITS FRAIS Yaourts sante et biologique aux fruits +3560071182243 LIQUIDES Jus de fruits frais et légumes - Pur jus +3560071182267 LIQUIDES Jus de fruits frais et légumes - Pur jus +3560071154165 PRODUITS FRAIS Patisseries et tartes surgelées +3560071154288 PRODUITS FRAIS Poitrine de porc +3560071154295 PRODUITS FRAIS Poitrine de porc +3560071182465 LIQUIDES Jus d'orange bio +3560071182472 LIQUIDES Jus d'autres fruits bio +3560071182489 LIQUIDES Jus de raison bio +3560071182649 PRODUITS FRAIS Riz et semoule +3560071182656 PRODUITS FRAIS Riz et semoule +3560071182663 PRODUITS FRAIS Crèmes dessert +3560071154325 PRODUITS FRAIS Libre service - Produits carnes prepares +3560071154356 PRODUITS FRAIS Libre service - Produits carnes prepares +3560071183028 PRODUITS FRAIS Autres produits traiteur frais +3560071183059 PRODUITS FRAIS Autres produits traiteur frais +3560071183103 PRODUITS FRAIS Autres produits traiteur frais +3560071183141 PRODUITS FRAIS Autres produits traiteur frais +3560071183172 PRODUITS FRAIS Autres produits traiteur frais +3560071154714 EPICERIE Barres céréalières +3560071184124 EPICERIE Biscuits sucrés Secs +3560071184155 PRODUITS FRAIS Yaourts sante et biologique aromatisé +3560071184162 PRODUITS FRAIS Yaourts aromatises +3560071184179 PRODUITS FRAIS Yaourts aux fruits +3560071184186 EPICERIE Biscuits sucrés Secs +3560071184216 EPICERIE Biscuits sucrés Secs +3560071184360 EPICERIE Lapin +3560071154745 EPICERIE Barres céréalières +3560071154790 EPICERIE Snacks: Produits souffles et extrudes +3560071184483 LIQUIDES Purs Jus de Fruits - Autres +3560071154820 EPICERIE Mueslis +3560071154875 EPICERIE Mueslis +3560071154905 PRODUITS FRAIS Entrées exotiques +3560071185008 EPICERIE Autres produits patisserie +3560071185657 EPICERIE Chocolat tablette - noirs +3560071186289 PRODUITS FRAIS Spécialités festives (Bûches - Bûchettes...) +3560071186296 PRODUITS FRAIS Spécialités festives (Bûches - Bûchettes...) +3560071186302 PRODUITS FRAIS Spécialités festives (Bûches - Bûchettes...) +3560071186364 PRODUITS FRAIS Yaourts a boire +3560071186487 EPICERIE Biscuits sucrés Secs +3560071186685 PRODUITS FRAIS Pates fourrees +3560071187033 PRODUITS FRAIS Préparation pommes de terres +3560071187385 PRODUITS FRAIS Autres produits preparés +3560071187958 EPICERIE Biscuits sucrés Secs +3560071187989 EPICERIE Biscuits sucrés Secs +3560071188207 EPICERIE Sucres +3560071188399 PRODUITS FRAIS Légumes verts surgelés +3560071188405 PRODUITS FRAIS Spécialités festives (Bûches - Bûchettes...) +3560071188412 PRODUITS FRAIS Légumes cuisines/ Purées / Gratins +3560071189129 EPICERIE Biscuits sucrés Au chocolat +3560071189211 EPICERIE Biscuits sucrés Secs +3560071189327 LIQUIDES Jus de fruits frais et légumes - Pur jus +3560071189495 LIQUIDES Bières Blondes +3560071189532 LIQUIDES Bières Blondes +3560071189556 LIQUIDES Bières Blondes +3560071189648 LIQUIDES Bières Spécialité +3560071189730 LIQUIDES Bières Spéciales +3560071189761 LIQUIDES Bières Spéciales +3560071189808 LIQUIDES Bières Spéciales +3560071189815 LIQUIDES Bières Spéciales +3560071156763 LIQUIDES Autres boissons non-gazeifiees Aux fruits +3560071189983 PRODUITS FRAIS Préparation pommes de terres +3560071190149 LIQUIDES Jus de pomme bio +3560071156770 LIQUIDES Autres boissons non-gazeifiees Aux fruits +3560071156787 LIQUIDES Autres boissons non-gazeifiees Aux fruits +3560071156794 LIQUIDES Autres boissons non-gazeifiees Aux fruits +3560071156800 LIQUIDES Autres boissons non-gazeifiees Aux fruits +3560071190521 PRODUITS FRAIS Bœuf haché / Préparation / Découpe +3560071156817 LIQUIDES Autres boissons non-gazeifiees Aux fruits +3560071156824 LIQUIDES Autres boissons non-gazeifiees Aux fruits +3560071156831 LIQUIDES Autres boissons non-gazeifiees Aux fruits +3560071156848 LIQUIDES Autres boissons non-gazeifiees Aux fruits +3560071156855 LIQUIDES Autres boissons non-gazeifiees Aux fruits +3560071156862 LIQUIDES Autres boissons non-gazeifiees Aux fruits +3560071190903 PRODUITS FRAIS Saumon fumés +3560071190934 PRODUITS FRAIS Saumon fumés +3560071190965 EPICERIE Autres céréales +3560071156947 EPICERIE Biscuits sucrés Cookies +3560071156978 EPICERIE Biscuits sucrés Cookies +3560071191306 PRODUITS FRAIS Pizzas +3560071191573 EPICERIE Biscuits sucrés - Assortiments +3560071191641 EPICERIE Conserves de Maquereaux +3560071191726 PRODUITS FRAIS Plat cuis./prépar.pate légume +3560071191733 PRODUITS FRAIS Plat cuis./prépar.pate légume +3560071191740 PRODUITS FRAIS Plat cuis./prépar.pate légume +3560071191757 PRODUITS FRAIS Plat cuis./prépar.pate légume +3560071191931 LIQUIDES Bières Spécialité +3560071191962 PRODUITS FRAIS Autres produits preparés +3560071191979 EPICERIE Biscuits sucrés Au chocolat +3560071192105 EPICERIE Chocolat tablette - noirs +3560071157586 PRODUITS FRAIS Plats cuisinés surgelés - a base de pates +3560071157593 PRODUITS FRAIS Plats cuisinés surgelés - a base de pates +3560071192853 PRODUITS FRAIS Mélanges de legumes/garniture surgelés +3560071157722 PRODUITS FRAIS Surimi +3560071158583 LIQUIDES Autres boissons non-gazeifiees Au thé +3560071158590 LIQUIDES Autres boissons non-gazeifiees Au thé +3560071193195 EPICERIE Sels +3560071193423 EPICERIE Biscuits sucrés Secs +3560071193560 PRODUITS FRAIS Desserts - Mousses +3560071193676 PRODUITS FRAIS Pains de mie élaboré +3560071193768 PRODUITS FRAIS Jambons cuits +3560071193775 PRODUITS FRAIS Jambons cuits +3560071159443 EPICERIE Olives vertes +3560071159474 EPICERIE Olives farcies +3560071159504 EPICERIE Olives farcies +3560071159535 PRODUITS FRAIS Plats cuisinés surgelés - a base de pates +3560071160067 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560071195434 EPICERIE Noix de cajou +3560071161507 PRODUITS FRAIS Pates à tarte fraiches +3560071161514 PRODUITS FRAIS Pates à tarte fraiches +3560071195670 PRODUITS FRAIS Autre Charcuterie à cuire +3560071162399 LIQUIDES Nectars - Autres fruits +3560071162931 EPICERIE Olives farcies +3560071196233 EPICERIE Chocolat tablette - noirs +3560071163037 PRODUITS FRAIS Autres legumes surgelés +3560071163310 EPICERIE Vinaigrette +3560071163327 EPICERIE Vinaigrette +3560071163358 EPICERIE Bonbons durs aux fruits +3560071163655 LIQUIDES Autres boissons gazéifiées +3560071197094 PRODUITS FRAIS Bacs Sorbets +3560071164386 EPICERIE Bonbons gélifiés +3560071164393 EPICERIE Bonbons gélifiés +3560071164409 EPICERIE Bonbons fourres +3560071197704 PRODUITS FRAIS Bacs Sorbets +3560071164652 PRODUITS FRAIS Pizzas surgelées - Standard +3560071164669 EPICERIE Infusions classiques +3560071165604 EPICERIE Riz blanchis +3560071165611 EPICERIE Riz blanchis +3560071165628 EPICERIE Riz blanchis +3560071165635 EPICERIE Riz Spécialités +3560071165710 EPICERIE Riz Spécialités +3560071168445 PRODUITS FRAIS Plats cuisinés surgelés - a base de viande +3560071168520 PRODUITS FRAIS Pain de mie standard +3560071168537 PRODUITS FRAIS Pain de mie standard +3560071198763 EPICERIE Conserves de Flageolets +3560071168575 PRODUITS FRAIS Surimi +3560071168773 PRODUITS FRAIS Glaces Batonnets +3560071168780 PRODUITS FRAIS Glaces Batonnets +3560071168964 EPICERIE Blé / Quinoa / Autres céréales +3560071168971 EPICERIE Blé / Quinoa / Autres céréales +3560071169145 PRODUITS FRAIS Pizzas +3560071169190 PRODUITS FRAIS Pates fourrees +3560071169213 PRODUITS FRAIS Autres produits de panification +3560071169275 PRODUITS FRAIS Libre service - Poulets +3560071169381 PRODUITS FRAIS Bacs Crèmes Glacées +3560071169442 PRODUITS FRAIS Glaces Batonnets +3560071169473 PRODUITS FRAIS Glaces Batonnets +3560071169503 PRODUITS FRAIS Bacs Crèmes Glacées +3560071169534 PRODUITS FRAIS Bacs Crèmes Glacées +3560071169602 PRODUITS FRAIS Plat cuis./préparé avec viande +3560071169619 PRODUITS FRAIS Autres produits preparés +3560071169626 PRODUITS FRAIS Autres produits preparés +3560071169633 PRODUITS FRAIS Autres produits preparés +3560071170134 PRODUITS FRAIS Bacs Crèmes Glacées +3560071170165 PRODUITS FRAIS Glaces Cones et cornets +3560071170196 PRODUITS FRAIS Glaces Batonnets +3560071170226 PRODUITS FRAIS Glaces Batonnets +3560071170257 PRODUITS FRAIS Glaces Batonnets +3560071170424 EPICERIE Agglomerante +3560071170431 PRODUITS FRAIS Bacs Crèmes Glacées +3560071170462 PRODUITS FRAIS Glaces Batonnets +3560071170493 PRODUITS FRAIS Glaces Cones et cornets +3560071170547 LIQUIDES Bières Panaches +3560071170820 LIQUIDES Autres boissons non-gazeifiees Au thé +3560071170851 LIQUIDES Autres boissons non-gazeifiees Au thé +3560071170950 LIQUIDES Jus d'ananas à base de concentré +3560071171001 PRODUITS FRAIS Goûter enfant +3560071171018 EPICERIE Conserves de Peches +3560071171056 EPICERIE Conserves de Fruits melanges +3560071171087 EPICERIE Conserves de Fruits melanges +3560071171117 EPICERIE Conserves de Fruits melanges +3560071208370 EPICERIE Confiserie et chocolats noel +3560071208400 EPICERIE Confiserie et chocolats noel +3560071208462 EPICERIE Confiserie et chocolats noel +3560071208516 EPICERIE Confiserie et chocolats noel +3560071171148 EPICERIE Conserves de Fruits melanges +3560071171230 EPICERIE ,Chocolat tablette - amande,,noisette,,riz, +3560071171247 EPICERIE ,Chocolat tablette - amande,,noisette,,riz, +3560071171292 EPICERIE Conserves de Fruits melanges +3560071171353 EPICERIE Pâtes alimentaires sèches Spécialités +3560071171384 EPICERIE Pâtes alimentaires sèches Spécialités +3560071171414 LIQUIDES Jus multifruits à base de concentré +3560071171568 PRODUITS FRAIS Plat cuis./prépar.avec poisson +3560071171575 PRODUITS FRAIS Plat cuis./prépar.pate légume +3560071171674 PRODUITS FRAIS Libre service - Poulets +3560071171704 PRODUITS FRAIS Libre service - Poulets +3560071171735 PRODUITS FRAIS Libre service - Poulets +3560071172114 PRODUITS FRAIS Autres fruits de mer/preparés surgelés +3560071172121 PRODUITS FRAIS Autres fruits de mer/preparés surgelés +3560071172145 PRODUITS FRAIS Poissons surgelés nature tranche/morceau +3560071172206 PRODUITS FRAIS Plat cuis./préparé avec viande +3560071172213 LIQUIDES Ready to drink - A base de vin +3560071172275 EPICERIE Conserves de Petits pois +3560071172305 EPICERIE Pates à tartiner chocolat +3560071172480 PRODUITS FRAIS Bœuf haché / Préparation / Découpe +3560071173142 EPICERIE Infusions classiques +3560071174576 EPICERIE Farine blanche +3560071174613 PRODUITS FRAIS Corps gras de cuisine +3560071174644 PRODUITS FRAIS Corps gras a tartiner +3560071174859 LIQUIDES Boissons colas - Colas +3560071174866 LIQUIDES Boissons colas - Colas +3560071174873 LIQUIDES Sirops concentrés - Conc. d agrumes +3560071174903 EPICERIE Potages liquides +3560071174934 EPICERIE Potages deshydrates +3560071174965 EPICERIE Potages deshydrates +3560071175085 LIQUIDES Autres boissons non-gazeifiees Aux fruits +3560071175115 PRODUITS FRAIS Crèmes fraiches epaisses +3560071175184 PRODUITS FRAIS Poitrine de porc +3560071175191 PRODUITS FRAIS Poitrine de porc +3560071175344 PRODUITS FRAIS Libre service - Produits carnes prepares +3560071175481 EPICERIE Conserves d'Ananas +3560071175542 EPICERIE Conserves de Thon +3560071175573 EPICERIE Conserves de Thon +3560071175603 EPICERIE Conserves de Thon +3560071175634 EPICERIE Conserves de Thon +3560071175665 EPICERIE Conserves de Thon +3560071175696 EPICERIE Conserves de Thon +3560071176259 EPICERIE Conserves Poivrons +3560071176266 PRODUITS FRAIS Autres legumes surgelés +3560071176297 PRODUITS FRAIS Légumes verts surgelés +3560071176334 PRODUITS FRAIS Légumes verts surgelés +3560071176365 PRODUITS FRAIS Baies et fruits entiers surgelés +3560071176464 PRODUITS FRAIS Corps gras a tartiner +3560071176495 PRODUITS FRAIS Corps gras a tartiner +3560071176525 EPICERIE Conserves d'Ananas +3560071176556 PRODUITS FRAIS Corps gras a tartiner +3560071176594 PRODUITS FRAIS Corps gras a tartiner +3560071176648 PRODUITS FRAIS Frites surgelées +3560071176655 PRODUITS FRAIS Frites surgelées +3560071177232 PRODUITS FRAIS Pains précuits +3560071177249 PRODUITS FRAIS Pains hamburgers et hot-dogs +3609230255104 EPICERIE Tourterelles +3609230255142 EPICERIE Canaris +3609230255159 EPICERIE Oiseau exotique +3609230255173 EPICERIE Autres oiseaux - bassecour +3609230255180 EPICERIE Perruche +3609230255197 EPICERIE Autres rongeurs +3609230255203 EPICERIE Autres oiseaux - bassecour +3609230255210 EPICERIE Autres oiseaux - bassecour +3560071177256 PRODUITS FRAIS Panettone/brioche/prd tranche +3560071177263 PRODUITS FRAIS Patisseries industrielles - Madeleines +3560071177270 PRODUITS FRAIS Autres patisseries et gateaux industriels +3560071177287 PRODUITS FRAIS Autres patisseries et gateaux industriels +3560071177294 EPICERIE Barres céréalières +3560071177324 EPICERIE Conserves de Petits pois +3560071177355 EPICERIE Conserves de Haricots verts +3560071177386 EPICERIE Conserves de Petits pois carottes +3560071177416 EPICERIE Conserves de Petits pois +3560071177447 EPICERIE Conserves de Flageolets +3560071177560 EPICERIE Conserves de Petits pois +3560071177591 PRODUITS FRAIS Yaourts a boire +3560071177621 PRODUITS FRAIS Yaourts a boire +3560071177713 PRODUITS FRAIS Préparations à tartiner et rillettes +3560071177744 PRODUITS FRAIS Produits exotiques +3560071177751 PRODUITS FRAIS Produits exotiques +3560071177768 PRODUITS FRAIS Produits exotiques +3560071177775 PRODUITS FRAIS Produits exotiques +3560071177782 PRODUITS FRAIS Produits exotiques +3560071177799 PRODUITS FRAIS Produits exotiques +3560071177805 PRODUITS FRAIS Produits exotiques +3560071177812 PRODUITS FRAIS Produits exotiques +3560071177829 PRODUITS FRAIS Produits exotiques +3560071177874 LIQUIDES Autres boissons non-gazeifiees Au thé +3560071177904 LIQUIDES Autres boissons non-gazeifiees Au thé +3560071177997 PRODUITS FRAIS Pizzas +3560071178215 PRODUITS FRAIS Emmentals blocs +3560071178260 EPICERIE Biscuits sucrés Au chocolat +3560071178345 PRODUITS FRAIS Emmentals rapes +3560071178406 PRODUITS FRAIS Fromages de chevre +3560071178437 PRODUITS FRAIS Raclette +3560071179298 EPICERIE Biscuits sucrés Cookies +3560071179328 EPICERIE Biscuits sucrés Cookies +3560071179380 EPICERIE Conserves Asperges +5400101007208 PRODUITS FRAIS Corps gras de cuisine +3560071179410 EPICERIE Conserves Artichauts +3560071179441 EPICERIE Conserves Poivrons +3560071179472 PRODUITS FRAIS Légumes cuisines/ Purées / Gratins +5400101007802 PRODUITS FRAIS Pizzas surgelées - Cuite sur pierre +3560071179588 PRODUITS FRAIS Fromages frais - Féta +3560071179663 PRODUITS FRAIS Fromage hollandais +3560071180089 PRODUITS FRAIS ,Quiches,, tartes,, tourtes surgelées, +3560071180188 EPICERIE Pâtes alimentaires prêtes à l'emploi +3560071180218 EPICERIE Pâtes alimentaires sèches +3560071180249 EPICERIE Pâtes alimentaires sèches +3560071180270 EPICERIE Pâtes alimentaires sèches +3560071180690 EPICERIE Cafés en dosettes +3560071180706 EPICERIE Cafés en dosettes +3560071180720 EPICERIE Miels +3560071180737 EPICERIE Chocolat tablette - fourres +5400101066410 EPICERIE Cafés en dosettes +5400101066427 EPICERIE Cafés en dosettes +3560071181062 PRODUITS FRAIS ,Langoustes,, homards,, crabes surgelés, +3560071181192 EPICERIE Autres chocolats tablettes +5400101155534 EPICERIE Carottes +5400101155572 EPICERIE Conserves de Haricots verts +3560071181208 EPICERIE Chocolat tablette - fourres +3560071181215 EPICERIE Chocolat tablette - fourres +3560071181222 LIQUIDES Autres boissons non-gazeifiees Aux fruits +3560071181291 EPICERIE ,Chocolat patissier,,couverture, +3560071181550 PRODUITS FRAIS Légumes cuisines/ Purées / Gratins +3560071181598 EPICERIE Sauces froides +3560071181642 PRODUITS FRAIS ,Crevettes,, gambas surgelés, +3560071181666 EPICERIE Chocolat tablette - fourres +3560071181703 PRODUITS FRAIS Pizzas +3560071181734 PRODUITS FRAIS Légumes cuisines/ Purées / Gratins +3560071181864 EPICERIE Melange de graine +3560071182137 PRODUITS FRAIS Laits longue conservation aromatisé +3560071182144 PRODUITS FRAIS Laits longue conservation aromatisé +3560071182151 PRODUITS FRAIS Laits longue conservation aromatisé +3560071182168 PRODUITS FRAIS Laits longue conservation aromatisé +3560071182199 PRODUITS FRAIS Laits longue conservation aromatisé +3560071182205 PRODUITS FRAIS Laits longue conservation aromatisé +3560071182212 LIQUIDES Jus de fruits frais et légumes - Pur jus +3560071182229 LIQUIDES Jus de fruits frais et légumes - Pur jus +3560071182236 LIQUIDES Jus de fruits frais et légumes - Pur jus +3560071182274 PRODUITS FRAIS Compotes pommes + fruits +3560071182281 PRODUITS FRAIS Compotes de pommes +3560071182304 EPICERIE Biscuits sucrés Secs +3560071182816 EPICERIE ,Aides culinaires,, boillons solides et court bouillon, +3560071182830 EPICERIE ,Aides culinaires,, boillons solides et court bouillon, +3560071182847 EPICERIE ,Aides culinaires,, boillons solides et court bouillon, +3560071182915 EPICERIE ,Aides culinaires,, boillons solides et court bouillon, +3560071183202 PRODUITS FRAIS Autres produits traiteur frais +3560071183684 EPICERIE Huiles Olive +3560071183813 PRODUITS FRAIS Pizzas +3560071183844 PRODUITS FRAIS Pizzas +3560071183875 PRODUITS FRAIS Yaourts aromatises +3560071183882 EPICERIE ,Aides culinaires,, boillons solides et court bouillon, +3560071183899 LIQUIDES Autres whiskies et whiskeys +3560071184438 PRODUITS FRAIS Poissons surgelés entiers +3560071184445 PRODUITS FRAIS Calamar/encornet/poulpe/seches surgelés +3560071184599 PRODUITS FRAIS Fromages blanc nature +3560071184896 PRODUITS FRAIS Salades +3560071184902 PRODUITS FRAIS Salades +3560071185398 PRODUITS FRAIS Yaourts natures +3560071185435 PRODUITS FRAIS Foie gras +5400101183223 EPICERIE Conserves de Petits pois +3560071186647 PRODUITS FRAIS Crevettes +3560071187170 LIQUIDES Rhums ambres +3560071188177 PRODUITS FRAIS Crevettes +3560071188283 PRODUITS FRAIS Yaourts aux fruits +3560071188658 LIQUIDES Bières Blondes +3560071188689 LIQUIDES Bières Spécialité +3560071188719 LIQUIDES Bières Spécialité +3560071188733 LIQUIDES Bières Spécialité +3560071189310 EPICERIE Sauces chaudes - pâtes - riz +3560071189341 PRODUITS FRAIS Entrées exotiques +3560071189358 PRODUITS FRAIS Entrées exotiques +3560071189365 PRODUITS FRAIS Entrées exotiques +3560071189372 PRODUITS FRAIS Entrées exotiques +3560071189389 PRODUITS FRAIS Entrées exotiques +3560071189587 LIQUIDES Bières Blondes +3560071189709 LIQUIDES Bières Blondes +3560071189792 LIQUIDES Bières Blondes +3560071189952 PRODUITS FRAIS Pates natures +3560071190170 LIQUIDES Nectars de Pomme +3560071190361 EPICERIE Biscuits sucrés Secs +3560071190705 PRODUITS FRAIS Patisseries salees surgelées +3560071190736 PRODUITS FRAIS Patisseries salees surgelées +3560071190767 PRODUITS FRAIS Patisseries salees surgelées +3560071190798 PRODUITS FRAIS Patisseries salees surgelées +3560071190828 PRODUITS FRAIS Préparation pommes de terres +3560071190859 PRODUITS FRAIS Préparation pommes de terres +3560071191146 LIQUIDES Rhums blancs +3560071191207 PRODUITS FRAIS Autres Plats cuisinés surgelés +3560071191276 EPICERIE Biscuits sucrés Fourres +3560071191429 PRODUITS FRAIS ,Crèmes aux œufs,, petits pot crème, +5400101258730 PRODUITS FRAIS Pizzas surgelées - Feu de bois +3560071191436 EPICERIE Blé / Quinoa / Autres céréales +5400101261341 EPICERIE Corn flakes +3560071191450 EPICERIE Riz prêt à l'emploi +3560071191467 EPICERIE Riz prêt à l'emploi +3560071191474 EPICERIE Riz parfumés (Basmati & Thaï) +3560071191481 EPICERIE Riz Spécialités +3560071191672 PRODUITS FRAIS Blinis et croutons +3560071192266 EPICERIE Légumes secs +3560071192303 PRODUITS FRAIS Légumes cuisines/ Purées / Gratins +3560071192334 PRODUITS FRAIS Légumes cuisines/ Purées / Gratins +3560071192464 PRODUITS FRAIS Blinis et croutons +3560071193133 EPICERIE Sauces froides +3560071193140 EPICERIE Sauces froides +3560071193157 EPICERIE Sauces froides +3560071193164 EPICERIE Sauces froides +3560071193171 EPICERIE Sauces froides +3560071193577 EPICERIE Biscuits sucrés - Assortiments +3560071193737 EPICERIE Compotes boîtes et bocales +3560071193744 EPICERIE Compotes boîtes et bocales +3560071193751 EPICERIE Compotes boîtes et bocales +3560071193782 EPICERIE Epinards +3560071194055 EPICERIE Conserves de Fruits melanges +3560071194062 EPICERIE Conserves de Fruits melanges +3560071194352 EPICERIE Semoules de ble / Couscous +3560071195045 PRODUITS FRAIS Entrées exotiques +3560071195564 EPICERIE Riz parfumés (Basmati & Thaï) +3560071195618 PRODUITS FRAIS Yaourts sante et biologique nature +3560071195625 PRODUITS FRAIS Yaourts sante et biologique nature +3560071195632 PRODUITS FRAIS Yaourts sante et biologique nature +3560071195649 PRODUITS FRAIS Yaourts sante et biologique aromatisé +3560071195656 PRODUITS FRAIS Yaourts sante et biologique aromatisé +3560071195663 PRODUITS FRAIS Yaourts sante et biologique aromatisé +3560071196509 PRODUITS FRAIS Glaces Cones et cornets +3560071196523 PRODUITS FRAIS Glaces Batonnets +3560071196967 PRODUITS FRAIS Glaces Batonnets +3560071197223 PRODUITS FRAIS Glaces Batonnets +3560071197728 PRODUITS FRAIS Yaourts aromatises +3560071197735 PRODUITS FRAIS Yaourts sante et biologique aromatisé +3560071197742 PRODUITS FRAIS Yaourts aromatises +3560071197759 PRODUITS FRAIS Yaourts aromatises +3560071197766 PRODUITS FRAIS Yaourts aromatises +3560071197773 PRODUITS FRAIS Yaourts sante et biologique nature +3560071197780 PRODUITS FRAIS Yaourts aromatises +3560071197797 PRODUITS FRAIS Yaourts aromatises +3560071197803 PRODUITS FRAIS Yaourts sante et biologique aromatisé +3560071197810 PRODUITS FRAIS Yaourts aromatises +3560071197827 PRODUITS FRAIS Yaourts aromatises +3560071197834 PRODUITS FRAIS Yaourts sante et biologique nature +3560071198121 PRODUITS FRAIS Bacs Crèmes Glacées +3560071198541 PRODUITS FRAIS Glaces Batonnets +3560071199043 PRODUITS FRAIS Légumes verts surgelés +3560071199388 PRODUITS FRAIS Légumes verts surgelés +3560071202347 EPICERIE Olives farcies +3560071205058 EPICERIE Desserts préparés +3560071205089 EPICERIE Desserts préparés +3560071205607 EPICERIE Conserves de Petits pois carottes +3560071214036 PRODUITS FRAIS Glaces Pots et coupelles +3560071214067 PRODUITS FRAIS Glaces Pots et coupelles +3560071215088 PRODUITS FRAIS Glaces Batonnets +3560071215118 PRODUITS FRAIS Glaces Batonnets +3560071215149 PRODUITS FRAIS Glaces Batonnets +3560071215798 PRODUITS FRAIS Autres Plats cuisinés surgelés +3560071220808 EPICERIE Conserves de Haricots blancs +3560071220839 EPICERIE Conserves de Haricots blancs sauce tomate +3560071221058 EPICERIE Autres légumes +3560071221508 EPICERIE Vegetale +3560071222031 EPICERIE Agglomerante +5400101001602 PRODUITS FRAIS Autres produits traiteur frais +5400101006904 PRODUITS FRAIS Corps gras de cuisine +5400101007222 PRODUITS FRAIS Corps gras de cuisine +5400101007246 PRODUITS FRAIS Corps gras de cuisine +5400101028067 LIQUIDES Sirops concentrés à base de plantes +5400101035232 PRODUITS FRAIS Corps gras a tartiner +5400101064300 EPICERIE Desserts a preparer +5400101064317 EPICERIE Desserts a preparer +5400101117273 EPICERIE Conserves de Petits pois carottes +5400101160620 EPICERIE Chocolat tablette - noirs +5400101160637 EPICERIE Chocolat tablette - au lait +5400101165199 EPICERIE Pates à tartiner chocolat +5400101165977 EPICERIE Autres mélanges de légumes +5400101166035 EPICERIE Céleri +5400101166608 EPICERIE Pommes de terre +5400101169104 EPICERIE Conserves de Poires +5400101169692 EPICERIE Conserves Autres fruits +5400101171268 EPICERIE Conserves de Tomates concassées +5400101171282 EPICERIE Sauces chaudes à base de tomate et tomate frito +5400101173118 EPICERIE ,Chocolat tablette - amande,,noisette,,riz, +5400101173255 EPICERIE Macédoine de légumes +5400101173682 EPICERIE Conserves de Petits pois carottes +5400101173712 EPICERIE Conserves de Petits pois +8431876066913 EPICERIE Conserves - Autres plats cuisines +5400101177321 EPICERIE Moutardes +5400101178090 EPICERIE Moutardes +5400101178595 EPICERIE Macédoine de légumes +5400101178601 EPICERIE Autres mélanges de légumes +5400101178618 EPICERIE Autres mélanges de légumes +5400101179219 EPICERIE Bonbons gélifiés +5400101179226 EPICERIE Bonbons gélifiés +5400101179240 EPICERIE Bonbons gélifiés +8431876077964 EPICERIE Conserves de Petits pois +5400101185319 EPICERIE Conserves de Haricots verts +5400101185418 EPICERIE Salsifis +5400101185425 EPICERIE Salsifis +5400101189324 EPICERIE Autres mélanges de légumes +5400101189515 EPICERIE Autres farines +5400101203112 LIQUIDES Autres fruits gazéifiées +5400101204492 EPICERIE Conserves de Peches +5400101209152 PRODUITS FRAIS Foie gras +5400101213975 PRODUITS FRAIS Beurres Sales +5400101213999 PRODUITS FRAIS Beurres Sans sel +5400101219205 PRODUITS FRAIS Crèmes longue conservation +5400101223486 EPICERIE Conserves de Tomates concassées +5400101223509 EPICERIE Conserves de Tomates concassées +5400101226944 LIQUIDES Autres fruits gazéifiées +5400101227620 LIQUIDES Autres fruits gazéifiées +5400101240599 EPICERIE Pates à tartiner chocolat +5400101248304 PRODUITS FRAIS Beurres Sans sel +5400101259102 EPICERIE Moutardes +8012666008551 PRODUITS FRAIS Légumes verts surgelés +8012666008568 PRODUITS FRAIS Légumes verts surgelés +8012666008605 PRODUITS FRAIS Mélanges de legumes/garniture surgelés +8012666008612 PRODUITS FRAIS Autres legumes surgelés +8012666009251 PRODUITS FRAIS Préparation pommes de terres +8012666011957 EPICERIE Pates à tartiner chocolat +8012666012121 EPICERIE Conserves de Petits pois carottes +8012666012695 PRODUITS FRAIS Légumes cuisines/ Purées / Gratins +8012666013975 EPICERIE Infusions classiques +8012666016075 PRODUITS FRAIS Champignons surgelés +8012666017904 PRODUITS FRAIS Autres legumes surgelés +8012666018741 PRODUITS FRAIS Légumes verts surgelés +8012666022823 PRODUITS FRAIS Champignons surgelés +8012666024605 PRODUITS FRAIS Légumes cuisines/ Purées / Gratins +8431876001747 LIQUIDES Tonics et Bitter gazéifiées +8431876002676 LIQUIDES Limonades gazéifiées +8431876002713 LIQUIDES Tonics et Bitter gazéifiées +8431876003840 EPICERIE ,Chocolat tablette - amande,,noisette,,riz, +8431876003857 EPICERIE ,Chocolat tablette - amande,,noisette,,riz, +8431876003888 EPICERIE Chocolat tablette - au lait +8431876004243 PRODUITS FRAIS Plats cuisinés surgelés - specialites +8431876004250 PRODUITS FRAIS Plats cuisinés surgelés - specialites +8431876004588 PRODUITS FRAIS Autres legumes surgelés +8431876004649 PRODUITS FRAIS Légumes verts surgelés +8431876004687 PRODUITS FRAIS Légumes verts surgelés +8431876004823 PRODUITS FRAIS Légumes verts surgelés +8431876005004 EPICERIE Conserves de Salades de thon et autres +8431876005011 EPICERIE Conserves de Salades de thon et autres +8431876005035 EPICERIE Conserves de Salades de thon et autres +8431876006421 EPICERIE Cafés solubles +8431876006445 EPICERIE Cafés solubles +8431876006452 EPICERIE Cafés solubles +8431876113754 EPICERIE Moutardes +8431876006667 EPICERIE Chocolat tablette - noirs +8431876007640 EPICERIE Pâtes alimentaires aux œufs +8431876007664 EPICERIE Pâtes alimentaires aux œufs +8431876007671 EPICERIE Pâtes alimentaires aux œufs +8431876007688 EPICERIE Pâtes alimentaires sèches +8431876007756 EPICERIE Pâtes alimentaires sèches +8431876010954 PRODUITS FRAIS Yaourts natures +8431876012194 EPICERIE Conserves Poivrons +8431876012347 EPICERIE Conserves Poivrons +8431876013689 LIQUIDES Bières Blondes +8431876025620 EPICERIE Minerale +8431876044355 EPICERIE Minerale +8431876045871 EPICERIE Pâtes alimentaires aux œufs +8431876046540 EPICERIE Pâtes alimentaires sèches Spécialités +8431876060522 EPICERIE Pâtes alimentaires sèches +8431876060539 EPICERIE Pâtes alimentaires sèches +8431876064513 EPICERIE ,Chocolat tablette - amande,,noisette,,riz, +8431876064537 EPICERIE ,Chocolat tablette - amande,,noisette,,riz, +8431876071191 EPICERIE Pâtes alimentaires sèches +8431876073621 EPICERIE Pâtes alimentaires sèches +8431876073737 EPICERIE Cafés solubles +8431876081923 EPICERIE Chocolat tablette - noirs +8431876087666 LIQUIDES Tonics et Bitter gazéifiées +8431876091977 PRODUITS FRAIS Yaourts natures +8431876091984 PRODUITS FRAIS Yaourts aux fruits +8431876102611 EPICERIE Noix de cajou +8431876102758 PRODUITS FRAIS Autres produits snacking glacés +8431876102772 EPICERIE Conserves de Thon +8431876105483 EPICERIE Conserves de Thon +8431876105490 EPICERIE Conserves de Thon +8431876106138 PRODUITS FRAIS Bacs Crèmes Glacées +8431876109085 EPICERIE Conserves d'Ananas +8431876110302 EPICERIE Conserves de Salades de thon et autres +8431876110319 EPICERIE Conserves de Salades de thon et autres +8431876110326 EPICERIE Conserves de Salades de thon et autres +8431876110333 EPICERIE Conserves de Salades de thon et autres +8431876116236 EPICERIE Conserves d'Ananas +8431876122626 EPICERIE Autres graines salees +8431876123449 PRODUITS FRAIS Yaourts sante et biologique à base de soja +8431876123456 PRODUITS FRAIS Yaourts sante et biologique à base de soja +8431876123586 PRODUITS FRAIS Surimi surgelés +8431876124705 EPICERIE Cafés solubles +8431876128512 EPICERIE Fruits secs +8431876172102 PRODUITS FRAIS Yaourts aux fruits +8431876128567 EPICERIE ,Amandes,, noisettes,, noix, +8431876128925 EPICERIE Autres graines salees +8431876128932 EPICERIE Autres graines salees +8431876142075 EPICERIE Cacahuetes +8431876144451 EPICERIE Corn flakes +8431876147148 PRODUITS FRAIS Légumes cuisines/ Purées / Gratins +8431876147155 PRODUITS FRAIS Légumes cuisines/ Purées / Gratins +8431876147162 PRODUITS FRAIS Légumes cuisines/ Purées / Gratins +8431876147728 PRODUITS FRAIS Plats cuisinés surgelés - a base de pates +8431876151886 EPICERIE ,Amandes,, noisettes,, noix, +8431876154887 PRODUITS FRAIS Liégeois +8431876154894 PRODUITS FRAIS Liégeois +8431876165517 LIQUIDES Autres boissons non-gazeifiees Aux fruits +8431876170610 EPICERIE Autres graines salees +8431876170689 PRODUITS FRAIS Plats cuisinés surgelés - a base de pates +8431876173482 PRODUITS FRAIS Plats cuisinés surgelés - specialites +8431876174359 EPICERIE Thés parfumés +8431876177305 PRODUITS FRAIS Crèmes dessert +8431876180701 PRODUITS FRAIS Liégeois +8431876331110 EPICERIE Autres céréales +8431876331349 EPICERIE Autres graines salees +8431876331691 EPICERIE Conserves Poivrons +8431876331707 EPICERIE Conserves Poivrons +8431876332476 EPICERIE Cafés solubles +8431876332483 EPICERIE Cafés solubles diff --git a/scripts/convert_carrefour_data.pl b/scripts/imports/carrefour/convert_carrefour_data.pl similarity index 100% rename from scripts/convert_carrefour_data.pl rename to scripts/imports/carrefour/convert_carrefour_data.pl diff --git a/scripts/imports/carrefour/run_carrefour_import.sh b/scripts/imports/carrefour/run_carrefour_import.sh new file mode 100755 index 0000000000000..98a0b89af2327 --- /dev/null +++ b/scripts/imports/carrefour/run_carrefour_import.sh @@ -0,0 +1,76 @@ +#!/usr/bin/env bash + +# do not continue on failure +set -e + +# load utils +. scripts/imports/imports_utils.sh + +# this script must be launched from server root (/srv/off-pro) +export PERL5LIB=lib:$PERL5LIB + +# load paths +echo "Load paths" +. <(perl -e 'use ProductOpener::Paths qw/:all/; print base_paths_loading_script()') + +if [[ -z "$OFF_SFTP_HOME_DIR" ]] +then + >&2 "OFF_SFTP_HOME_DIR not defined, exiting" + exit 10 +fi + +DATA_TMP_DIR=$OFF_CACHE_TMP_DIR/carrefour-data + +# Separate image directory as we want to keep images cached for later imports +IMAGES_TMP_DIR=$OFF_CACHE_TMP_DIR/carrefour-images + +SUCCESS_FILE_PATH="$OFF_PRIVATE_DATA_DIR/carrefour-import-success" + +IMPORT_SINCE=$(import_since $SUCCESS_FILE_PATH) + +echo "IMPORT_SINCE: $IMPORT_SINCE days" + +# copy XML files modified since the last successful run +echo "Copy XML files modified since the last successful run" +rm -rf $DATA_TMP_DIR +mkdir $DATA_TMP_DIR +mkdir $DATA_TMP_DIR/data +find $OFF_SFTP_HOME_DIR/carrefour/data/ -mtime -$IMPORT_SINCE -type f -name "*.xml" -exec cp {} $DATA_TMP_DIR/data/ \; + +# mv files that are not human food (cosmetics and pet food) +# TODO: we could in fact just import them in the pro platform, and dispatch them +# to Open Beauty Facts and Open Pet Food Facts later, as we do for Unilever +mkdir $DATA_TMP_DIR/data.obf +mkdir $DATA_TMP_DIR/data.opff +grep -Z -l -r '"DPH -' $DATA_TMP_DIR/data | xargs --null -I{} mv {} $DATA_TMP_DIR/data.obf/ +grep -Z -l -r '"ALI - PRODUITS POUR ANIMAUX' $DATA_TMP_DIR/data | xargs --null -I{} mv {} $DATA_TMP_DIR/data.opff/ + +# Warning some Carrefour XML files are broken with 2 .* +# fix them by removing the second one: +find $DATA_TMP_DIR/data/ -name "*.xml" -type f -exec sed -i 's/<\/TabNutXMLPF>.*/<\/TabNutXMLPF>/g' {} \; + +# Unzip images +# TODO: we get images from time to time in .zip files, but the .xml files we get +# for products could have images from earlier zip files, so currently we unzip +# all images we got. +# Carrefour will soon send us CSV files with images urls, so this process will +# eventually be replaced (i.e. not worth improving it now) +# create the images dir if it does not exist yet +mkdir -p $IMAGES_TMP_DIR +# unzip -j: create all files in destination folder, without any path +unzip -j -o "$OFF_SFTP_HOME_DIR/carrefour/data/*.zip" -d "$IMAGES_TMP_DIR/" +# copy images.rules used to determine the image type from the image file name +cp ./scripts/imports/carrefour/images.rules $IMAGES_TMP_DIR + +# Convert Carrefour XML files to one OFF csv file +echo "Convert Carrefour XML files to OFF csv file" +./scripts/imports/carrefour/convert_carrefour_data.pl $DATA_TMP_DIR/data ./scripts/imports/carrefour/Nomenclature_OpenFoodFacts.csv > $DATA_TMP_DIR/carrefour-data.tsv || exit 101; + +# Note: for testing, we can import products under the carrefour-test-off2 org + +# import data +echo "Import data" +./scripts/import_csv_file.pl --csv_file $DATA_TMP_DIR/carrefour-data.tsv --user_id carrefour --comment "Import Carrefour" --source_id "carrefour" --source_name "Carrefour" --source_url "https://www.carrefour.fr" --manufacturer --org_id carrefour-test-off2 --define lc=fr --images_dir $IMAGES_TMP_DIR + +# mark successful run +mark_successful_run $SUCCESS_FILE_PATH diff --git a/scripts/imports/equadis/run_equadis_import.sh b/scripts/imports/equadis/run_equadis_import.sh new file mode 100755 index 0000000000000..358061f8cbd28 --- /dev/null +++ b/scripts/imports/equadis/run_equadis_import.sh @@ -0,0 +1,51 @@ +#!/usr/bin/env bash + +# do not continue on failure +set -e + +# load utils +. scripts/imports/imports_utils.sh + +# this script must be launched from server root (/srv/off-pro) +export PERL5LIB=lib:$PERL5LIB + +# load paths +. <(perl -e 'use ProductOpener::Paths qw/:all/; print base_paths_loading_script()') + +if [[ -z "$OFF_SFTP_HOME_DIR" ]] +then + >&2 "OFF_SFTP_HOME_DIR not defined, exiting" + exit 10 +fi + +DATA_TMP_DIR=$OFF_CACHE_TMP_DIR/equadis-data +IMAGES_TMP_DIR=$OFF_CACHE_TMP_DIR/equadis-images + +SUCCESS_FILE_PATH="$OFF_PRIVATE_DATA_DIR/equadis-import-success" + +IMPORT_SINCE=$(import_since $SUCCESS_FILE_PATH) + +echo "IMPORT_SINCE: $IMPORT_SINCE days" + +# copy files modified in the last successful run +rm -rf $DATA_TMP_DIR +mkdir $DATA_TMP_DIR +find $OFF_SFTP_HOME_DIR/equadis/data/ -mtime -$IMPORT_SINCE -type f -exec cp {} $DATA_TMP_DIR/ \; + +# turn Equadis xml files into JSON file +./scripts/convert_gs1_xml_to_json_in_dir.pl $DATA_TMP_DIR || exit 100; + +# convert JSON files to a single CSV file +./scripts/convert_gs1_json_to_off_csv.pl --input-dir $DATA_TMP_DIR --output $DATA_TMP_DIR/equadis-data.tsv || exit 101; + +# STOP here to test ! +# exit 1 + +# import CSV file +./scripts/import_csv_file.pl \ + --user_id equadis --org_id equadis --source_id equadis --source_name Equadis \ + --source_url https://equadis.com/ --manufacturer 1 --comment "Import from Equadis" \ + --define lc=fr --images_download_dir $IMAGES_TMP_DIR --csv_file $DATA_TMP_DIR/equadis-data.tsv || exit 102 + +# mark successful run +mark_successful_run $SUCCESS_FILE_PATH diff --git a/scripts/imports/imports_utils.sh b/scripts/imports/imports_utils.sh new file mode 100644 index 0000000000000..b4964bdf36bd5 --- /dev/null +++ b/scripts/imports/imports_utils.sh @@ -0,0 +1,39 @@ +# some utility functions for run_imports shell + + + +# find last run and deduce how many days to fetch +# +# first arg should be the path to the import success file +# containing a timestamp of last successful import +# it may not exists yet, in which case we default to one week +function import_since() { + SUCCESS_FILE_PATH=$1 + if [[ -z "$SUCCESS_FILE_PATH" ]] + then + >&2 echo "ERROR: missing path to success file" + fi + if [[ -f "$SUCCESS_FILE_PATH" ]] + then + LAST_TS=$(cat $SUCCESS_FILE_PATH) + CURRENT_TS=$(date +%s) + DIFF=$(( $CURRENT_TS - $LAST_TS )) + # 86400 seconds in a day, +1 because we want upper bound + IMPORT_SINCE=$(( $DIFF / 86400 + 1 )) + else + # defaults to one week + IMPORT_SINCE=7 + fi + echo $IMPORT_SINCE +} + +# mark a sucessful run of import by putting current timestamp in success file +# so that import_since can use it on next run +function mark_successful_run() { + SUCCESS_FILE_PATH=$1 + if [[ -z "$SUCCESS_FILE_PATH" ]] + then + >&2 echo "ERROR: missing path to success file" + fi + echo $(date +%s) > $SUCCESS_FILE_PATH +} diff --git a/scripts/imports/producers_imports.sh b/scripts/imports/producers_imports.sh new file mode 100644 index 0000000000000..f179b1ce14ff4 --- /dev/null +++ b/scripts/imports/producers_imports.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +# Equadis import +./scripts/imports/equadis/run_equadis_import.sh +# Agena import +./scripts/imports/agena3000/run_agena3000_import.sh +# Carrefour +./scripts/imports/carrefour/import_carrefour.sh + +# Export +./scripts/export_producers_platform_data_to_public_database.sh \ No newline at end of file diff --git a/scripts/make_user_moderator.pl b/scripts/make_user_moderator.pl index ced9b3d7dfe82..e37e6d4c64138 100755 --- a/scripts/make_user_moderator.pl +++ b/scripts/make_user_moderator.pl @@ -26,6 +26,7 @@ use CGI::Carp qw(fatalsToBrowser); use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; @@ -39,6 +40,6 @@ use Encode; my $userid = $ARGV[0]; -my $user_ref = retrieve("$data_root/users/$userid.sto"); +my $user_ref = retrieve("$BASE_DIRS{USERS}/$userid.sto"); $user_ref->{moderator} = 1; -store("$data_root/users/$userid.sto", $user_ref); +store("$BASE_DIRS{USERS}/$userid.sto", $user_ref); diff --git a/scripts/minion_producers.pl b/scripts/minion_producers.pl index adbbdb4b77a56..342ce94932cf9 100755 --- a/scripts/minion_producers.pl +++ b/scripts/minion_producers.pl @@ -49,13 +49,18 @@ $log->info("starting minion producers workers", {minion_backend => $server_options{minion_backend}}) if $log->is_info(); -load_data(); - if (not defined $server_options{minion_backend}) { - die("No Minion backend configured in lib/ProductOpener/Config2.pm\n"); } +# for worker, if we don't have a -q argument, deduce it from configuration +if ((grep {/^worker$/} @ARGV) and (!grep {/^-q$/} @ARGV)) { + push @ARGV, "-q"; + push @ARGV, $server_domain; +} + +load_data(); + plugin Minion => $server_options{minion_backend}; app->minion->add_task(import_csv_file => \&ProductOpener::Producers::import_csv_file_task); diff --git a/scripts/convert_gs1_xml_to_json_in_dir.js b/scripts/obsolete/convert_gs1_xml_to_json_in_dir.js similarity index 88% rename from scripts/convert_gs1_xml_to_json_in_dir.js rename to scripts/obsolete/convert_gs1_xml_to_json_in_dir.js index 0cb179ea3003b..7f777917a8017 100644 --- a/scripts/convert_gs1_xml_to_json_in_dir.js +++ b/scripts/obsolete/convert_gs1_xml_to_json_in_dir.js @@ -1,3 +1,6 @@ +// OBSOLETE: we want to avoid to use NODE for things that can be done in perl +// use convert_gs1_xml_to_json.pl instead + // This script is used to convert GDSN data from Equadis in XML format // to a corresponding JSON structure diff --git a/scripts/obsolete/credit_product_to_creator.pl b/scripts/obsolete/credit_product_to_creator.pl index 995ddb4f81e23..3173ab6d8a907 100755 --- a/scripts/obsolete/credit_product_to_creator.pl +++ b/scripts/obsolete/credit_product_to_creator.pl @@ -26,6 +26,7 @@ use utf8; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; @@ -61,7 +62,7 @@ my $path = product_path($code); $product_ref->{creator} = $creator; - store( "$data_root/products/$path/product.sto", $product_ref ); + store( "$BASE_DIRS{PRODUCTS}/$path/product.sto", $product_ref ); get_products_collection()->save($product_ref); } diff --git a/scripts/obsolete/fix_code_stored_as_number.pl b/scripts/obsolete/fix_code_stored_as_number.pl index 4329d491901f8..d769776a49745 100755 --- a/scripts/obsolete/fix_code_stored_as_number.pl +++ b/scripts/obsolete/fix_code_stored_as_number.pl @@ -29,6 +29,7 @@ use CGI::Carp qw(fatalsToBrowser); use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; @@ -179,7 +180,7 @@ if (not $pretend) { $product_ref->{update_key} = $key; - store("$data_root/products/$path/product.sto", $product_ref); + store("$BASE_DIRS{PRODUCTS}/$path/product.sto", $product_ref); # Make sure product code is saved as string and not a number # see bug #1077 - https://github.com/openfoodfacts/openfoodfacts-server/issues/1077 diff --git a/scripts/obsolete/fix_countries_removed_by_yuka.pl b/scripts/obsolete/fix_countries_removed_by_yuka.pl index 583130989a714..d2e8d28cd80c9 100755 --- a/scripts/obsolete/fix_countries_removed_by_yuka.pl +++ b/scripts/obsolete/fix_countries_removed_by_yuka.pl @@ -49,6 +49,7 @@ use CGI::Carp qw(fatalsToBrowser); use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; @@ -112,7 +113,7 @@ $n++; - my $changes_ref = retrieve("$data_root/products/$path/changes.sto"); + my $changes_ref = retrieve("$BASE_DIRS{PRODUCTS}/$path/changes.sto"); if ( not defined $changes_ref ) { next; } diff --git a/scripts/obsolete/fix_leading_zeros.pl b/scripts/obsolete/fix_leading_zeros.pl index 3d77966d90c09..5e6241a0b140d 100755 --- a/scripts/obsolete/fix_leading_zeros.pl +++ b/scripts/obsolete/fix_leading_zeros.pl @@ -26,6 +26,7 @@ use utf8; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; @@ -107,7 +108,7 @@ else { $products_collection->replace_one({"_id" => $product_ref->{_id}}, $product_ref, { upsert => 1 }); } - store("$data_root/products/$path/product.sto", $product_ref); + store("$BASE_DIRS{PRODUCTS}/$path/product.sto", $product_ref); } } } diff --git a/scripts/obsolete/fix_product.pl b/scripts/obsolete/fix_product.pl index 9dfb3604820ea..eeb0fca4ef1d0 100755 --- a/scripts/obsolete/fix_product.pl +++ b/scripts/obsolete/fix_product.pl @@ -26,6 +26,7 @@ use utf8; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; @@ -60,7 +61,7 @@ # Store - store( "$data_root/products/$path/product.sto", $product_ref ); + store( "$BASE_DIRS{PRODUCTS}/$path/product.sto", $product_ref ); get_products_collection()->save($product_ref); diff --git a/scripts/obsolete/fix_product2.pl b/scripts/obsolete/fix_product2.pl index 1cdf18fc6f8ac..95dcc78c2bd91 100755 --- a/scripts/obsolete/fix_product2.pl +++ b/scripts/obsolete/fix_product2.pl @@ -26,6 +26,7 @@ use utf8; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; @@ -59,7 +60,7 @@ $product_ref = retrieve_product($code); $product_ref->{creator} = 'adeline'; -store( "$data_root/products/$path/product.sto", $product_ref ); +store( "$BASE_DIRS{PRODUCTS}/$path/product.sto", $product_ref ); get_products_collection()->save($product_ref); exit(0); diff --git a/scripts/codeonline-import/run_codeonline_import.sh b/scripts/obsolete/imports/codeonline-import/run_codeonline_import.sh similarity index 100% rename from scripts/codeonline-import/run_codeonline_import.sh rename to scripts/obsolete/imports/codeonline-import/run_codeonline_import.sh diff --git a/scripts/codeonline-import/split_gs1_codeonline_json.pl b/scripts/obsolete/imports/codeonline-import/split_gs1_codeonline_json.pl similarity index 100% rename from scripts/codeonline-import/split_gs1_codeonline_json.pl rename to scripts/obsolete/imports/codeonline-import/split_gs1_codeonline_json.pl diff --git a/scripts/codeonline-import/stats_gs1_codeonline_json.pl b/scripts/obsolete/imports/codeonline-import/stats_gs1_codeonline_json.pl similarity index 100% rename from scripts/codeonline-import/stats_gs1_codeonline_json.pl rename to scripts/obsolete/imports/codeonline-import/stats_gs1_codeonline_json.pl diff --git a/scripts/obsolete/imports/fleary_michon/ExportOpenFoodFacts.php b/scripts/obsolete/imports/fleary_michon/ExportOpenFoodFacts.php new file mode 100644 index 0000000000000..a6329a21d9369 --- /dev/null +++ b/scripts/obsolete/imports/fleary_michon/ExportOpenFoodFacts.php @@ -0,0 +1,198 @@ + $nbdoc) + $pas = $nbdoc; + +$tab_id_record = array (); +$tab_media = $tab_erreur = array (); +while ( $debut < $nbdoc ) { + // Appel API pour obtenir la liste des produits à récupérer + logError("Appel API pour obtenir la liste des produits"); + $content = RecupUrl ( "$urldam/api/v1/search/?oauth_token=$oauth_token&per_page=$pas&bases[]=25&offset_start=$debut&query=$query" ); + $content = json_decode ( $content, true ); + // Pour chaque média, récupération de l'id (record_id) et de son emplacement (databox_id) + foreach ( $content ["response"] ["results"] ["records"] as $value ) { + $tab_id_record [] = array ( + "record_id" => $value ["record_id"], + "databox_id" => $value ["databox_id"] + ); + } + $debut += $pas; +} + +logError("Pour chaque média, récupération du nomGs1 et vérication image de référence unique"); +// Pour chaque média, récupération du nomGs1 et vérication image de référence unique +foreach ( $tab_id_record as $key => $record ) { + $base = $record ["databox_id"]; + $id = $record ["record_id"]; + + // Appel API pour obtenir la fiche descriptive d'une image + $urlcaption = "$urldam/api/v1/records/" . $base . "/" . $id . "/caption/"; + $token = "?oauth_token=$oauth_token"; + $servercaption = RecupUrl ( $urlcaption . $token ); + $caption = json_decode ( $servercaption, true ); + + //Initialisation de la variable $nomgs1 + $nomgs1 = ""; + $count = 0; + + //Boucle sur les metadonnées retournées par l'API + foreach ( $caption ["response"] ["caption_metadatas"] as $structure ) { + switch ($structure ["meta_structure_id"]) { + case 58 : + $nomgs1 = $structure ["value"]; + $count++; + break; + } + //Break lorsque le nomgs1 est trouvé + if ( $count>0 ) break; + } + // Si le nom GS1 est vide, passage au produit suivant + if (empty ( $nomgs1 )) + continue; + + //Extraction du nomgs1 sans le numero sequentiel dans $gs1racc, pour la verification de reference multiple + $gs1racc=substr($nomgs1, 0, -4); + + //Si $gs1racc n'existe pas dans le tableau $tab_media ni dans le tableau $tab_erreur + //Ajout des informations du produit (id, base, nomgs1) dans $tab_media + if (empty ( $tab_media [$gs1racc] ) && ! array_key_exists ( $gs1racc, $tab_erreur )) { + $tab_media [$gs1racc]["id"] = $id; + $tab_media [$gs1racc]["base"] = $base; + $tab_media [$gs1racc]["nomgs1"] = $nomgs1; + } // Sinon, erreur image de reference multiple + else { + unset ( $tab_media [$gs1racc] ); + $tab_erreur [$gs1racc] = $id; + } +} + +// Pour chaque media de $tab_media +// recherche de l'url de la sous definition normegs1 + +LogError("Pour chaque media recherche de l'url de la sous definition normegs1"); +foreach ( $tab_media as $key => $record ) { + $base = $record ["base"]; + $id = $record ["id"]; + $nomgs1 = $record ["nomgs1"]; + + // Appel API pour obtenir les sous définitions d'une image + $url = "$urldam/api/v1/records/" . $base . "/" . $id . "/embed/"; + $url .= "?oauth_token=$oauth_token"; + $server_output = RecupUrl ( $url ); + $server_output = json_decode ( $server_output, true ); + + //Initialisation de la variable $url + $url = ""; + foreach ( $server_output ["response"] ["embed"] as $structure ) { + if ($structure ["name"] != "normegs1") + continue; + $url = $structure ["permalink"] ["url"]; + } + + /* + * Traitement pour la récupération des images : + * Le traitement ci-dessous télécharge les images dans un dossier $dossier + */ + $dossier="download/"; + if (! empty ( $url )) { + #downloadFile ( $url_dl, "./$dossier" . $nomgs1 . ".png" ); + downloadFile ( $url, "./$dossier" . $nomgs1 . ".png" ); + } else { + logError ( "La sous definition Norme Gs1 n'existe pas pour l'image " . $nomgs1 . " (ID $id)\r\n" ); + } +} + +//Log des erreurs des images de reference multiple +foreach ( $tab_erreur as $key => $value ) { + $erreur = "Il existe plusieurs images de référence pour le GTIN " . $key . "\r\n"; + logError ( $erreur ); +} + +/** + * Log le message $string dans le fichier ./logs/logOpenFoodFacts+datedujour.log + * + * @param string $string + */ +function logError($string) { + // return true; + error_reporting ( null ); + $date = date ( "d/m/Y H:i:s" ); + $filename = "./logs/logOpenFoodFacts" . date ( "Ymd" ) . ".log"; + $logfile = fopen ( $filename, "a+" ); + fputs ( $logfile, $date . " - " . $string ); + fclose ( $logfile ); + error_reporting ( E_ALL ); +} + +/** + * Equivalent de file_gets_content avec un curl + * + * @param String $url + * Url d'appel a l'API + * @return String format JSON + */ +function RecupUrl($url) { + logError("RecupUrl: " . $url . "\n"); + $ch = curl_init (); + curl_setopt ( $ch, CURLOPT_SSL_VERIFYPEER, FALSE ); + curl_setopt ( $ch, CURLOPT_HEADER, false ); + curl_setopt ( $ch, CURLOPT_FOLLOWLOCATION, true ); + curl_setopt ( $ch, CURLOPT_URL, $url ); + curl_setopt ( $ch, CURLOPT_REFERER, $url ); + curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, TRUE ); + $data = curl_exec ( $ch ); + curl_close ( $ch ); + + return $data; +} + +/** + * Dépose le fichier $url dans le dossier $path + * + * @param String $url + * Url a telecharger + * @param String $filename + * chemin et nom du fichier a creer + */ +function downloadFile($url, $filename) { + logError("downloadFile url " . $url . " - filename " . $filename . "\n"); + $newfname = $filename; + $file = fopen ( $url, 'rb' ); + if ($file) { + $newf = fopen ( $newfname, 'wb' ); + if ($newf) { + while ( ! feof ( $file ) ) { + fwrite ( $newf, fread ( $file, 1024 * 8 ), 1024 * 8 ); + } + } + } + if ($file) { + fclose ( $file ); + } + if ($newf) { + fclose ( $newf ); + } +} + +?> diff --git a/scripts/obsolete/imports/fleary_michon/configOpenFoodFacts.php b/scripts/obsolete/imports/fleary_michon/configOpenFoodFacts.php new file mode 100644 index 0000000000000..37d58f36d273c --- /dev/null +++ b/scripts/obsolete/imports/fleary_michon/configOpenFoodFacts.php @@ -0,0 +1,9 @@ + diff --git a/scripts/obsolete/imports/fleary_michon/delete_broken_image_files.pl b/scripts/obsolete/imports/fleary_michon/delete_broken_image_files.pl new file mode 100755 index 0000000000000..b3ddfee0b3958 --- /dev/null +++ b/scripts/obsolete/imports/fleary_michon/delete_broken_image_files.pl @@ -0,0 +1,28 @@ +#!/usr/bin/perl -w + +use strict; + +print STDERR "Delete broken image files\n"; + +foreach my $file (@ARGV) { + + my $name = $file; + + next if $file !~ /\.(png|jpg)/; + + # only check new files + my $last_mod_time = (stat ($file))[9]; + if (time() - $last_mod_time > 86400 * 2) { + print STDERR "skip old file $file\n"; + next; + } + + my $result = `convert $file NULL 2>&1`; + if ($result =~ /Corrupt/i) { + print STDERR "$file seems broken:\nresult: $result\n\n"; + unlink($file); + } + else { + #print STDERR "result for file $file: $file\nresult: $result\n"; + } +} diff --git a/scripts/import_fleurymichon.pl b/scripts/obsolete/imports/fleary_michon/import_fleurymichon.pl similarity index 100% rename from scripts/import_fleurymichon.pl rename to scripts/obsolete/imports/fleary_michon/import_fleurymichon.pl diff --git a/cron/import_fleurymichon.sh b/scripts/obsolete/imports/fleary_michon/import_fleurymichon.sh similarity index 73% rename from cron/import_fleurymichon.sh rename to scripts/obsolete/imports/fleary_michon/import_fleurymichon.sh index 8852c4d6d549b..d1b149bbbdb1c 100755 --- a/cron/import_fleurymichon.sh +++ b/scripts/obsolete/imports/fleary_michon/import_fleurymichon.sh @@ -1,5 +1,12 @@ #!/bin/sh +>&2 echo "FIX this script before running it +- remove php +- load pathes from perl and use them +- eventually use timestamp to determine which file to import +" +exit(1) + cd /srv/off/imports/fleurymichon/images php ExportOpenFoodFacts.php diff --git a/scripts/obsolete/import_barilla.sh b/scripts/obsolete/imports/import_barilla.sh similarity index 100% rename from scripts/obsolete/import_barilla.sh rename to scripts/obsolete/imports/import_barilla.sh diff --git a/scripts/obsolete/import_baskalia_pechalou.sh b/scripts/obsolete/imports/import_baskalia_pechalou.sh similarity index 100% rename from scripts/obsolete/import_baskalia_pechalou.sh rename to scripts/obsolete/imports/import_baskalia_pechalou.sh diff --git a/scripts/obsolete/import_casino.sh b/scripts/obsolete/imports/import_casino.sh similarity index 100% rename from scripts/obsolete/import_casino.sh rename to scripts/obsolete/imports/import_casino.sh diff --git a/scripts/obsolete/import_foodrepo.sh b/scripts/obsolete/imports/import_foodrepo.sh similarity index 100% rename from scripts/obsolete/import_foodrepo.sh rename to scripts/obsolete/imports/import_foodrepo.sh diff --git a/scripts/obsolete/import_harrys.sh b/scripts/obsolete/imports/import_harrys.sh similarity index 100% rename from scripts/obsolete/import_harrys.sh rename to scripts/obsolete/imports/import_harrys.sh diff --git a/scripts/obsolete/import_iglo.sh b/scripts/obsolete/imports/import_iglo.sh similarity index 100% rename from scripts/obsolete/import_iglo.sh rename to scripts/obsolete/imports/import_iglo.sh diff --git a/scripts/obsolete/imports/import_ldc.sh b/scripts/obsolete/imports/import_ldc.sh new file mode 100755 index 0000000000000..75ac39f6e0a9f --- /dev/null +++ b/scripts/obsolete/imports/import_ldc.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +./import_csv_file.pl --csv_file /srv/off/imports/ldc/ldc-off.csv --user_id ldc --comment "Import LDC" --source_id "ldc" --source_name "LDC" --source_url "https://www.ldc.fr/" --images_dir /srv/off/imports/ldc/images --manufacturer diff --git a/scripts/obsolete/import_mxbot.sh b/scripts/obsolete/imports/import_mxbot.sh similarity index 100% rename from scripts/obsolete/import_mxbot.sh rename to scripts/obsolete/imports/import_mxbot.sh diff --git a/scripts/obsolete/imports/import_ocr_nutriscore.sh b/scripts/obsolete/imports/import_ocr_nutriscore.sh new file mode 100755 index 0000000000000..09ad04c0e9cb3 --- /dev/null +++ b/scripts/obsolete/imports/import_ocr_nutriscore.sh @@ -0,0 +1,3 @@ +#!/bin/sh +./import_csv_file.pl --csv_file /srv/off/imports/ocr/nutriscore/nutriscore.csv --user_id ocr-nutriscore --comment "Nutri-Score label" --no_source --import_lc fr --skip_not_existing_products + diff --git a/scripts/obsolete/import_openfood_ch.pl b/scripts/obsolete/imports/import_openfood_ch.pl similarity index 99% rename from scripts/obsolete/import_openfood_ch.pl rename to scripts/obsolete/imports/import_openfood_ch.pl index 1395ead1e385a..af27fa333db08 100755 --- a/scripts/obsolete/import_openfood_ch.pl +++ b/scripts/obsolete/imports/import_openfood_ch.pl @@ -22,8 +22,7 @@ use CGI::Carp qw(fatalsToBrowser); -use strict; -use utf8; +use ProductOpener::PerlStandards; binmode(STDOUT, ":encoding(UTF-8)"); diff --git a/scripts/obsolete/import_openfood_ch_name_translations.pl b/scripts/obsolete/imports/import_openfood_ch_name_translations.pl similarity index 99% rename from scripts/obsolete/import_openfood_ch_name_translations.pl rename to scripts/obsolete/imports/import_openfood_ch_name_translations.pl index 4b6279a7a4d8f..e6be647271b5d 100755 --- a/scripts/obsolete/import_openfood_ch_name_translations.pl +++ b/scripts/obsolete/imports/import_openfood_ch_name_translations.pl @@ -22,8 +22,7 @@ use CGI::Carp qw(fatalsToBrowser); -use strict; -use utf8; +use ProductOpener::PerlStandards; binmode(STDOUT, ":encoding(UTF-8)"); diff --git a/scripts/obsolete/import_saintelucie.sh b/scripts/obsolete/imports/import_saintelucie.sh similarity index 100% rename from scripts/obsolete/import_saintelucie.sh rename to scripts/obsolete/imports/import_saintelucie.sh diff --git a/scripts/obsolete/import_sodebo.pl b/scripts/obsolete/imports/import_sodebo.pl similarity index 99% rename from scripts/obsolete/import_sodebo.pl rename to scripts/obsolete/imports/import_sodebo.pl index 52b7134722846..830107fb03dfa 100755 --- a/scripts/obsolete/import_sodebo.pl +++ b/scripts/obsolete/imports/import_sodebo.pl @@ -22,8 +22,7 @@ use CGI::Carp qw(fatalsToBrowser); -use strict; -use utf8; +use ProductOpener::PerlStandards; binmode(STDOUT, ":encoding(UTF-8)"); diff --git a/scripts/obsolete/imports/import_stores_be_delhaize.sh b/scripts/obsolete/imports/import_stores_be_delhaize.sh new file mode 100755 index 0000000000000..c7348a196006c --- /dev/null +++ b/scripts/obsolete/imports/import_stores_be_delhaize.sh @@ -0,0 +1,2 @@ +#!/bin/sh +./import_csv_file.pl --csv_file /srv/off/imports/stores/be_delhaize_20190228.csv --user_id countrybot --comment "Products sold in Belgium" --no_source --import_lc fr --skip_not_existing_products --define countries="en:belgium" --define stores="Delhaize" diff --git a/scripts/obsolete/import_us_ndb.pl b/scripts/obsolete/imports/import_us_ndb.pl similarity index 99% rename from scripts/obsolete/import_us_ndb.pl rename to scripts/obsolete/imports/import_us_ndb.pl index 61c799f6abde9..23ca5965e7f1d 100755 --- a/scripts/obsolete/import_us_ndb.pl +++ b/scripts/obsolete/imports/import_us_ndb.pl @@ -22,8 +22,7 @@ use CGI::Carp qw(fatalsToBrowser); -use strict; -use utf8; +use ProductOpener::PerlStandards; binmode(STDOUT, ":encoding(UTF-8)"); diff --git a/scripts/copy_text_files.pl b/scripts/obsolete/migrations/copy_text_files.pl similarity index 100% rename from scripts/copy_text_files.pl rename to scripts/obsolete/migrations/copy_text_files.pl diff --git a/scripts/delete_old_cropped_images.pl b/scripts/obsolete/migrations/delete_old_cropped_images.pl similarity index 91% rename from scripts/delete_old_cropped_images.pl rename to scripts/obsolete/migrations/delete_old_cropped_images.pl index d45fca14732c3..185e8bc299937 100755 --- a/scripts/delete_old_cropped_images.pl +++ b/scripts/obsolete/migrations/delete_old_cropped_images.pl @@ -6,6 +6,7 @@ use CGI::Carp qw(fatalsToBrowser); use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Products qw/:all/; @@ -52,7 +53,7 @@ ($$) } if (scalar $#products < 0) { - find_products("$data_root/products", ''); + find_products($BASE_DIRS{PRODUCTS}, ''); } # Create directory to move old images to @@ -75,12 +76,12 @@ ($$) my $path = product_path($code); - my $product_ref = retrieve("$data_root/products/$path/product.sto") - or print "not defined $data_root/products/$path/product.sto\n"; + my $product_ref = retrieve("$BASE_DIRS{PRODUCTS}/$path/product.sto") + or print "not defined $BASE_DIRS{PRODUCTS}/$path/product.sto\n"; if ((defined $product_ref)) { - my $dir = "$www_root/images/products/$path"; + my $dir = "$BASE_DIRS{PRODUCTS_IMAGES}/$path"; # Store the highest version number for each imageid @@ -133,7 +134,7 @@ ($$) my $current_dir = "$www_root/old-images/products"; foreach my $component (split("/", $path)) { $current_dir .= "/$component"; - (-e "$current_dir") or mkdir($current_dir, 0755); + (-e $current_dir) or mkdir($current_dir, 0755); } require File::Copy; diff --git a/scripts/delete_spam_users.pl b/scripts/obsolete/migrations/delete_spam_users.pl similarity index 86% rename from scripts/delete_spam_users.pl rename to scripts/obsolete/migrations/delete_spam_users.pl index ff62c3b246fb6..c8e391a04f3ef 100755 --- a/scripts/delete_spam_users.pl +++ b/scripts/obsolete/migrations/delete_spam_users.pl @@ -28,6 +28,7 @@ use ProductOpener::PerlStandards; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Users qw/:all/; @@ -50,7 +51,7 @@ my @userids; if (scalar $#userids < 0) { - opendir DH, "$data_root/users" or die "Couldn't open the current directory: $!"; + opendir DH, $BASE_DIRS{USERS} or die "Couldn't open the current directory: $!"; @userids = sort(readdir(DH)); closedir(DH); } @@ -75,26 +76,26 @@ next if $userid eq "." or $userid eq ".."; next if $userid eq 'all'; - my $user_ref = retrieve("$data_root/users/$userid"); + my $user_ref = retrieve("$BASE_DIRS{USERS}/$userid"); if ((defined $user_ref) and (is_suspicious_name($user_ref->{name}))) { print $user_ref->{name} . "\n"; push @emails_to_delete, $user_ref->{email}; eval {print $jsonl_file $json->encode($user_ref) . "\n";}; - $dry_run or move("$data_root/users/$userid", "$spam_users_dir/$userid"); + $dry_run or move("$BASE_DIRS{USERS}/$userid", "$spam_users_dir/$userid"); $i++; } } close($jsonl_file); -my $emails_ref = retrieve("$data_root/users/users_emails.sto"); +my $emails_ref = retrieve("$BASE_DIRS{USERS}/users_emails.sto"); foreach my $email (@emails_to_delete) { delete $emails_ref->{$email}; } -$dry_run or store("$data_root/users/users_emails.sto", $emails_ref); +$dry_run or store("$BASE_DIRS{USERS}/users/users_emails.sto", $emails_ref); print "$i accounts removed\n"; diff --git a/scripts/obsolete/remove_deleted_products_from_db.pl b/scripts/obsolete/remove_deleted_products_from_db.pl index 201ef87aae8d2..ee675496b09de 100755 --- a/scripts/obsolete/remove_deleted_products_from_db.pl +++ b/scripts/obsolete/remove_deleted_products_from_db.pl @@ -26,6 +26,7 @@ use utf8; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; @@ -64,7 +65,7 @@ if (not defined $product_ref) { print STDERR "cannot load product $code\n"; - my $product_ref = retrieve("$data_root/products/$path/product.sto"); + my $product_ref = retrieve("$BASE_DIRS{PRODUCTS}/$path/product.sto"); if (defined $product_ref) { print STDERR "deleted : $product_ref->{deleted} - _id : $product_ref->{_id}\n"; get_products_collection()->delete_one({"code" => $code}); @@ -79,7 +80,7 @@ # Store - # store("$data_root/products/$path/product.sto", $product_ref); + # store("$BASE_DIRS{PRODUCTS}/$path/product.sto", $product_ref); # get_products_collection()->save($product_ref); } diff --git a/scripts/obsolete/test_additifs.pl b/scripts/obsolete/test_additifs.pl index e4514a6a91380..73e2cb914dfc2 100755 --- a/scripts/obsolete/test_additifs.pl +++ b/scripts/obsolete/test_additifs.pl @@ -26,6 +26,7 @@ use utf8; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; @@ -121,8 +122,8 @@ next if $path =~ /invalid/; - if (-e "$data_root/products/$path/product.sto") { - #store("$data_root/products/$path/product.sto", $product_ref); + if (-e "$BASE_DIRS{PRODUCTS}/$path/product.sto") { + #store("$BASE_DIRS{PRODUCTS}/$path/product.sto", $product_ref); #get_products_collection()->save($product_ref); # print $OUT "$product_ref->{code} - $product_ref->{name} : " . join (" ", sort @{$product_ref->{$class . '_tags'}}) . "
    \n"; diff --git a/scripts/obsolete/update_all_products_all_fields.pl b/scripts/obsolete/update_all_products_all_fields.pl index 8b566c61f99c9..e6cb4b8b7db37 100755 --- a/scripts/obsolete/update_all_products_all_fields.pl +++ b/scripts/obsolete/update_all_products_all_fields.pl @@ -26,6 +26,7 @@ use utf8; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; @@ -133,7 +134,7 @@ #$User_id = 'fieldbot'; #store_product($product_ref, "allow Unicode characters in normalized values of tag fields"); - store("$data_root/products/$path/product.sto", $product_ref); + store("$BASE_DIRS{PRODUCTS}/$path/product.sto", $product_ref); $products_collection->save($product_ref); } diff --git a/scripts/obsolete/update_all_products_categories.pl b/scripts/obsolete/update_all_products_categories.pl index dbfd47f996dd9..18273389bc3ad 100755 --- a/scripts/obsolete/update_all_products_categories.pl +++ b/scripts/obsolete/update_all_products_categories.pl @@ -26,6 +26,7 @@ use utf8; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; @@ -77,7 +78,7 @@ ProductOpener::Food::special_process_product($product_ref); } - store( "$data_root/products/$path/product.sto", $product_ref ); + store( "$BASE_DIRS{PRODUCTS}/$path/product.sto", $product_ref ); $products_collection->save($product_ref); } diff --git a/scripts/obsolete/update_all_products_codes.pl b/scripts/obsolete/update_all_products_codes.pl index dd37433ebb8c0..c0fce57c7a51c 100755 --- a/scripts/obsolete/update_all_products_codes.pl +++ b/scripts/obsolete/update_all_products_codes.pl @@ -26,6 +26,7 @@ use utf8; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; @@ -69,7 +70,7 @@ compute_codes($product_ref); - store( "$data_root/products/$path/product.sto", $product_ref ); + store( "$BASE_DIRS{PRODUCTS}/$path/product.sto", $product_ref ); $products_collection->save($product_ref); } } diff --git a/scripts/obsolete/update_all_products_countries.pl b/scripts/obsolete/update_all_products_countries.pl index 7aa13bf083f5a..384d67464657d 100755 --- a/scripts/obsolete/update_all_products_countries.pl +++ b/scripts/obsolete/update_all_products_countries.pl @@ -26,6 +26,7 @@ use utf8; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; @@ -88,7 +89,7 @@ # Store - store( "$data_root/products/$path/product.sto", $product_ref ); + store( "$BASE_DIRS{PRODUCTS}/$path/product.sto", $product_ref ); $products_collection->save($product_ref); } diff --git a/scripts/obsolete/update_all_products_countries_add.pl b/scripts/obsolete/update_all_products_countries_add.pl index 2e00d443e42a8..c82f2be83a25c 100755 --- a/scripts/obsolete/update_all_products_countries_add.pl +++ b/scripts/obsolete/update_all_products_countries_add.pl @@ -26,6 +26,7 @@ use utf8; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; @@ -130,7 +131,7 @@ # Check lock and previous version if ($product_ref->{$field} eq '') { - my $changes_ref = retrieve("$data_root/products/$path/changes.sto"); + my $changes_ref = retrieve("$BASE_DIRS{PRODUCTS}/$path/changes.sto"); if ((defined $changes_ref) and (defined $changes_ref->[0])) { my $ip = $changes_ref->[0]{ip}; @@ -189,7 +190,7 @@ # Store #if ($code eq '!3033710076017') { - store("$data_root/products/$path/product.sto", $product_ref); + store("$BASE_DIRS{PRODUCTS}/$path/product.sto", $product_ref); $products_collection->save($product_ref); } } diff --git a/scripts/obsolete/update_all_products_countries_fix.pl b/scripts/obsolete/update_all_products_countries_fix.pl index 59b624128578b..683e810deb6b6 100755 --- a/scripts/obsolete/update_all_products_countries_fix.pl +++ b/scripts/obsolete/update_all_products_countries_fix.pl @@ -26,6 +26,7 @@ use utf8; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; @@ -90,7 +91,7 @@ $product_ref->{countries} = display_taxonomy_tag($lc, "countries", $countryid); if ($code ne '993605347529') { - store("$data_root/products/$path/product.sto", $product_ref); + store("$BASE_DIRS{PRODUCTS}/$path/product.sto", $product_ref); $products_collection->save($product_ref); } } diff --git a/scripts/obsolete/update_all_products_creator.pl b/scripts/obsolete/update_all_products_creator.pl index 52b2705a9d13d..9dc7844294a1f 100644 --- a/scripts/obsolete/update_all_products_creator.pl +++ b/scripts/obsolete/update_all_products_creator.pl @@ -26,6 +26,7 @@ use utf8; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; @@ -65,7 +66,7 @@ # Update #extract_ingredients_classes_from_text($product_ref); - my $changes_ref = retrieve("$data_root/products/$path/changes.sto"); + my $changes_ref = retrieve("$BASE_DIRS{PRODUCTS}/$path/changes.sto"); if ( not defined $changes_ref ) { $changes_ref = [ {} ]; @@ -80,7 +81,7 @@ # Store - store( "$data_root/products/$path/product.sto", $product_ref ); + store( "$BASE_DIRS{PRODUCTS}/$path/product.sto", $product_ref ); $products_collection->save($product_ref); } diff --git a/scripts/obsolete/update_all_products_emb_codes.pl b/scripts/obsolete/update_all_products_emb_codes.pl index 8bfccfd61b608..c8c6197f64e68 100755 --- a/scripts/obsolete/update_all_products_emb_codes.pl +++ b/scripts/obsolete/update_all_products_emb_codes.pl @@ -26,6 +26,7 @@ use utf8; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; @@ -121,7 +122,7 @@ # Store - store("$data_root/products/$path/product.sto", $product_ref); + store("$BASE_DIRS{PRODUCTS}/$path/product.sto", $product_ref); $products_collection->save($product_ref); } diff --git a/scripts/obsolete/update_all_products_energy.pl b/scripts/obsolete/update_all_products_energy.pl index da7cc7cad83c6..9438bba5879d6 100755 --- a/scripts/obsolete/update_all_products_energy.pl +++ b/scripts/obsolete/update_all_products_energy.pl @@ -26,6 +26,7 @@ use utf8; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; @@ -69,7 +70,7 @@ # Store - store("$data_root/products/$path/product.sto", $product_ref); + store("$BASE_DIRS{PRODUCTS}/$path/product.sto", $product_ref); $products_collection->save($product_ref); } diff --git a/scripts/obsolete/update_all_products_from_dir_in_mongodb.pl b/scripts/obsolete/update_all_products_from_dir_in_mongodb.pl index f499f50665698..c04a955e7ae0a 100755 --- a/scripts/obsolete/update_all_products_from_dir_in_mongodb.pl +++ b/scripts/obsolete/update_all_products_from_dir_in_mongodb.pl @@ -26,6 +26,7 @@ use utf8; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; @@ -87,7 +88,7 @@ ($$) if (scalar $#products < 0) { - find_products("$data_root/products",''); + find_products($BASE_DIRS{PRODUCTS},''); } @@ -109,7 +110,7 @@ ($$) #my $product_ref = retrieve_product($code); - my $product_ref = retrieve("$data_root/products/$path/product.sto") or print "not defined $data_root/products/$path/product.sto\n"; + my $product_ref = retrieve("$BASE_DIRS{PRODUCTS}/$path/product.sto") or print "not defined $BASE_DIRS{PRODUCTS}/$path/product.sto\n"; if ((defined $product_ref)) { diff --git a/scripts/obsolete/update_all_products_from_dir_remove_dotted_fields.pl b/scripts/obsolete/update_all_products_from_dir_remove_dotted_fields.pl index 3b604946aa072..9debfea73ebd2 100644 --- a/scripts/obsolete/update_all_products_from_dir_remove_dotted_fields.pl +++ b/scripts/obsolete/update_all_products_from_dir_remove_dotted_fields.pl @@ -26,6 +26,7 @@ use utf8; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; @@ -87,7 +88,7 @@ ($$) if (scalar $#products < 0) { - find_products("$data_root/products",''); + find_products($BASE_DIRS{PRODUCTS},''); } @@ -110,7 +111,7 @@ ($$) #my $product_ref = retrieve_product($code); - my $product_ref = retrieve("$data_root/products/$path/product.sto") or print "not defined $data_root/products/$path/product.sto\n"; + my $product_ref = retrieve("$BASE_DIRS{PRODUCTS}/$path/product.sto") or print "not defined $BASE_DIRS{PRODUCTS}/$path/product.sto\n"; if ((defined $product_ref)) { @@ -153,7 +154,7 @@ ($$) $codes{$code} = 1; if ($update) { - store("$data_root/products/$path/product.sto", $product_ref); + store("$BASE_DIRS{PRODUCTS}/$path/product.sto", $product_ref); $updated++; } } diff --git a/scripts/obsolete/update_all_products_history.pl b/scripts/obsolete/update_all_products_history.pl index 1be62eecdec90..83c5a313b95d4 100755 --- a/scripts/obsolete/update_all_products_history.pl +++ b/scripts/obsolete/update_all_products_history.pl @@ -26,6 +26,7 @@ use utf8; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; @@ -67,7 +68,7 @@ $lc = $product_ref->{lc}; $lang = $lc; - my $changes_ref = retrieve("$data_root/products/$path/changes.sto"); + my $changes_ref = retrieve("$BASE_DIRS{PRODUCTS}/$path/changes.sto"); if ( not defined $changes_ref ) { $changes_ref = []; } @@ -82,9 +83,9 @@ # add 0 just to make sure we have a number... last_modified_t at some point contained strings like "1431125369" $product_ref->{sortkey} = 0 + $product_ref->{last_modified_t} - ((1 - $product_ref->{complete}) * 1000000000); - store( "$data_root/products/$path/product.sto", $product_ref ); + store( "$BASE_DIRS{PRODUCTS}/$path/product.sto", $product_ref ); $products_collection->save($product_ref); - store( "$data_root/products/$path/changes.sto", $changes_ref ); + store( "$BASE_DIRS{PRODUCTS}/$path/changes.sto", $changes_ref ); } } diff --git a/scripts/obsolete/update_all_products_history_from_dir.pl b/scripts/obsolete/update_all_products_history_from_dir.pl index ae39d75b3f23d..9f271fd029057 100755 --- a/scripts/obsolete/update_all_products_history_from_dir.pl +++ b/scripts/obsolete/update_all_products_history_from_dir.pl @@ -26,6 +26,7 @@ use utf8; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; @@ -85,7 +86,7 @@ ($$) if (scalar $#products < 0) { - find_products("$data_root/products",''); + find_products($BASE_DIRS{PRODUCTS},''); } @@ -111,7 +112,7 @@ ($$) $lc = $product_ref->{lc}; $lang = $lc; - my $changes_ref = retrieve("$data_root/products/$path/changes.sto"); + my $changes_ref = retrieve("$BASE_DIRS{PRODUCTS}/$path/changes.sto"); if (not defined $changes_ref) { $changes_ref = []; } @@ -119,9 +120,9 @@ ($$) compute_product_history_and_completeness($product_ref, $changes_ref); - store( "$data_root/products/$path/product.sto", $product_ref ); + store( "$BASE_DIRS{PRODUCTS}/$path/product.sto", $product_ref ); $products_collection->save($product_ref); - store( "$data_root/products/$path/changes.sto", $changes_ref ); + store( "$BASE_DIRS{PRODUCTS}/$path/changes.sto", $changes_ref ); } } diff --git a/scripts/obsolete/update_all_products_history_fromdir.pl b/scripts/obsolete/update_all_products_history_fromdir.pl index dd89633bee509..783a99d402a2e 100755 --- a/scripts/obsolete/update_all_products_history_fromdir.pl +++ b/scripts/obsolete/update_all_products_history_fromdir.pl @@ -26,6 +26,7 @@ use utf8; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; @@ -85,7 +86,7 @@ ($$) if (scalar $#products < 0) { - find_products("$data_root/products",''); + find_products($BASE_DIRS{PRODUCTS},''); } @@ -104,14 +105,14 @@ ($$) # print STDERR "updating product $code\n"; #my $product_ref = retrieve_product($code); - my $product_ref = retrieve("$data_root/products/$path/product.sto"); + my $product_ref = retrieve("$BASE_DIRS{PRODUCTS}/$path/product.sto"); if ((defined $product_ref) and ($code ne '')) { $lc = $product_ref->{lc}; $lang = $lc; - my $changes_ref = retrieve("$data_root/products/$path/changes.sto"); + my $changes_ref = retrieve("$BASE_DIRS{PRODUCTS}/$path/changes.sto"); if (not defined $changes_ref) { $changes_ref = []; } @@ -133,9 +134,9 @@ ($$) #if ($product_ref->{code} eq '3596710313266') { delete $product_ref->{deleted}; - store("$data_root/products/$path/product.sto", $product_ref); + store("$BASE_DIRS{PRODUCTS}/$path/product.sto", $product_ref); $products_collection->save($product_ref); - store("$data_root/products/$path/changes.sto", $changes_ref); + store("$BASE_DIRS{PRODUCTS}/$path/changes.sto", $changes_ref); #} } } @@ -148,9 +149,9 @@ ($$) print "!!! deleted non empty product: $code\n"; } - #store("$data_root/products/$path/product.sto", $product_ref); + #store("$BASE_DIRS{PRODUCTS}/$path/product.sto", $product_ref); #$products_collection->save($product_ref); - #store("$data_root/products/$path/changes.sto", $changes_ref); + #store("$BASE_DIRS{PRODUCTS}/$path/changes.sto", $changes_ref); } } diff --git a/scripts/obsolete/update_all_products_in_mongodb.pl b/scripts/obsolete/update_all_products_in_mongodb.pl index 3856345611b92..615044199101b 100755 --- a/scripts/obsolete/update_all_products_in_mongodb.pl +++ b/scripts/obsolete/update_all_products_in_mongodb.pl @@ -26,6 +26,7 @@ use utf8; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; @@ -67,7 +68,7 @@ # Store #my $path = product_path($code); - #store("$data_root/products/$path/product.sto", $product_ref); + #store("$BASE_DIRS{PRODUCTS}/$path/product.sto", $product_ref); $products_collection->save($product_ref); } } diff --git a/scripts/obsolete/update_all_products_ingredients.pl b/scripts/obsolete/update_all_products_ingredients.pl index efe601a177329..72da71b127ec2 100755 --- a/scripts/obsolete/update_all_products_ingredients.pl +++ b/scripts/obsolete/update_all_products_ingredients.pl @@ -26,6 +26,7 @@ use utf8; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; @@ -74,7 +75,7 @@ next if $path =~ /invalid/; - store( "$data_root/products/$path/product.sto", $product_ref ); + store( "$BASE_DIRS{PRODUCTS}/$path/product.sto", $product_ref ); $products_collection->save($product_ref); } diff --git a/scripts/obsolete/update_all_products_ingredients_classes.pl b/scripts/obsolete/update_all_products_ingredients_classes.pl index 27ffddaf0e16e..f2e04fcc5149e 100755 --- a/scripts/obsolete/update_all_products_ingredients_classes.pl +++ b/scripts/obsolete/update_all_products_ingredients_classes.pl @@ -26,6 +26,7 @@ use utf8; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; @@ -74,8 +75,8 @@ next if $path =~ /invalid/; - if ( -e "$data_root/products/$path/product.sto" ) { - store( "$data_root/products/$path/product.sto", $product_ref ); + if ( -e "$BASE_DIRS{PRODUCTS}/$path/product.sto" ) { + store( "$BASE_DIRS{PRODUCTS}/$path/product.sto", $product_ref ); $products_collection->save($product_ref); if (defined $product_ref->{old_additives_tags}) { diff --git a/scripts/obsolete/update_all_products_labels.pl b/scripts/obsolete/update_all_products_labels.pl index 2b297f5b955e5..2e06c43205054 100755 --- a/scripts/obsolete/update_all_products_labels.pl +++ b/scripts/obsolete/update_all_products_labels.pl @@ -26,6 +26,7 @@ use utf8; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; @@ -78,7 +79,7 @@ # Store - store( "$data_root/products/$path/product.sto", $product_ref ); + store( "$BASE_DIRS{PRODUCTS}/$path/product.sto", $product_ref ); $products_collection->save($product_ref); } diff --git a/scripts/obsolete/update_all_products_lang_lc.pl b/scripts/obsolete/update_all_products_lang_lc.pl index 4a436d06979b6..767271ac4125f 100755 --- a/scripts/obsolete/update_all_products_lang_lc.pl +++ b/scripts/obsolete/update_all_products_lang_lc.pl @@ -26,6 +26,7 @@ use utf8; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; @@ -68,7 +69,7 @@ # Store - store("$data_root/products/$path/product.sto", $product_ref); + store("$BASE_DIRS{PRODUCTS}/$path/product.sto", $product_ref); $products_collection->save($product_ref); } diff --git a/scripts/obsolete/update_all_products_language_fields.pl b/scripts/obsolete/update_all_products_language_fields.pl index 84c3f5e710dd6..b5e80bb1365cb 100755 --- a/scripts/obsolete/update_all_products_language_fields.pl +++ b/scripts/obsolete/update_all_products_language_fields.pl @@ -26,6 +26,7 @@ use utf8; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; @@ -97,9 +98,9 @@ foreach my $size ($thumb_size, $small_size, $display_size, 'full') { # copy images to new name with language - (! -e "$www_root/images/products/$path/${field}_$lc.$rev.$size.jpg") and system("cp -a $www_root/images/products/$path/$field.$rev.$size.jpg $www_root/images/products/$path/${field}_$lc.$rev.$size.jpg"); + (! -e "$BASE_DIRS{PRODUCTS_IMAGES}/$path/${field}_$lc.$rev.$size.jpg") and system("cp -a $BASE_DIRS{PRODUCTS_IMAGES}/$path/$field.$rev.$size.jpg $BASE_DIRS{PRODUCTS_IMAGES}/$path/${field}_$lc.$rev.$size.jpg"); } - (-e "$www_root/images/products/$path/$field.$rev.full.json") and (! -e "$www_root/images/products/$path/${field}_$lc.$rev.full.json") and system("cp -a $www_root/images/products/$path/$field.$rev.full.json $www_root/images/products/$path/${field}_$lc.$rev.full.json"); + (-e "$BASE_DIRS{PRODUCTS_IMAGES}/$path/$field.$rev.full.json") and (! -e "$BASE_DIRS{PRODUCTS_IMAGES}/$path/${field}_$lc.$rev.full.json") and system("cp -a $BASE_DIRS{PRODUCTS_IMAGES}/$path/$field.$rev.full.json $BASE_DIRS{PRODUCTS_IMAGES}/$path/${field}_$lc.$rev.full.json"); } } @@ -111,7 +112,7 @@ #$User_id = 'fieldbot'; #store_product($product_ref, "allow Unicode characters in normalized values of tag fields"); - store( "$data_root/products/$path/product.sto", $product_ref ); + store( "$BASE_DIRS{PRODUCTS}/$path/product.sto", $product_ref ); $products_collection->save($product_ref); } diff --git a/scripts/obsolete/update_all_products_languages.pl b/scripts/obsolete/update_all_products_languages.pl index 76c0cef22bc4f..40d5646065a81 100755 --- a/scripts/obsolete/update_all_products_languages.pl +++ b/scripts/obsolete/update_all_products_languages.pl @@ -26,6 +26,7 @@ use utf8; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; @@ -79,7 +80,7 @@ #$User_id = 'fieldbot'; #store_product($product_ref, "allow Unicode characters in normalized values of tag fields"); - store( "$data_root/products/$path/product.sto", $product_ref ); + store( "$BASE_DIRS{PRODUCTS}/$path/product.sto", $product_ref ); $products_collection->save($product_ref); } diff --git a/scripts/obsolete/update_all_products_nutriments_fields.pl b/scripts/obsolete/update_all_products_nutriments_fields.pl index dde23f341b735..003e78e9d3371 100755 --- a/scripts/obsolete/update_all_products_nutriments_fields.pl +++ b/scripts/obsolete/update_all_products_nutriments_fields.pl @@ -26,6 +26,7 @@ use utf8; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; @@ -78,7 +79,7 @@ # Store - store( "$data_root/products/$path/product.sto", $product_ref ); + store( "$BASE_DIRS{PRODUCTS}/$path/product.sto", $product_ref ); $products_collection->save($product_ref); } diff --git a/scripts/obsolete/update_all_products_nutriments_typo.pl b/scripts/obsolete/update_all_products_nutriments_typo.pl index e0d1b87ed312b..57e3c3246585a 100755 --- a/scripts/obsolete/update_all_products_nutriments_typo.pl +++ b/scripts/obsolete/update_all_products_nutriments_typo.pl @@ -26,6 +26,7 @@ use utf8; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; @@ -96,7 +97,7 @@ # Store - store("$data_root/products/$path/product.sto", $product_ref); + store("$BASE_DIRS{PRODUCTS}/$path/product.sto", $product_ref); $products_collection->save($product_ref); print STDERR "updated product $code\n"; diff --git a/scripts/obsolete/update_all_products_nutrition_score.pl b/scripts/obsolete/update_all_products_nutrition_score.pl index a70af769a2ec9..cc0c1622de83b 100755 --- a/scripts/obsolete/update_all_products_nutrition_score.pl +++ b/scripts/obsolete/update_all_products_nutrition_score.pl @@ -26,6 +26,7 @@ use utf8; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; @@ -72,7 +73,7 @@ next if $path =~ /invalid/; - store( "$data_root/products/$path/product.sto", $product_ref ); + store( "$BASE_DIRS{PRODUCTS}/$path/product.sto", $product_ref ); $products_collection->save($product_ref); } diff --git a/scripts/obsolete/update_all_products_packager_codes.pl b/scripts/obsolete/update_all_products_packager_codes.pl index 96b3c514668e6..9d78cb24fd7e4 100755 --- a/scripts/obsolete/update_all_products_packager_codes.pl +++ b/scripts/obsolete/update_all_products_packager_codes.pl @@ -26,6 +26,7 @@ use utf8; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; @@ -97,7 +98,7 @@ } # Store - store("$data_root/products/$path/product.sto", $product_ref); + store("$BASE_DIRS{PRODUCTS}/$path/product.sto", $product_ref); $products_collection->save($product_ref); } diff --git a/scripts/obsolete/update_all_products_periods_from_expiration_date.pl b/scripts/obsolete/update_all_products_periods_from_expiration_date.pl index fe8da9893773c..ef7747f075ab1 100755 --- a/scripts/obsolete/update_all_products_periods_from_expiration_date.pl +++ b/scripts/obsolete/update_all_products_periods_from_expiration_date.pl @@ -26,6 +26,7 @@ use utf8; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; @@ -86,7 +87,7 @@ # Store - store( "$data_root/products/$path/product.sto", $product_ref ); + store( "$BASE_DIRS{PRODUCTS}/$path/product.sto", $product_ref ); $products_collection->save($product_ref); } diff --git a/scripts/obsolete/update_all_products_sortkey.pl b/scripts/obsolete/update_all_products_sortkey.pl index a2e6b5f0a1ed6..e3a454a1cc92d 100755 --- a/scripts/obsolete/update_all_products_sortkey.pl +++ b/scripts/obsolete/update_all_products_sortkey.pl @@ -26,6 +26,7 @@ use utf8; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; @@ -68,7 +69,7 @@ # Store - store( "$data_root/products/$path/product.sto", $product_ref ); + store( "$BASE_DIRS{PRODUCTS}/$path/product.sto", $product_ref ); $products_collection->save($product_ref); } diff --git a/scripts/obsolete/update_all_products_unknown_nutriments.pl b/scripts/obsolete/update_all_products_unknown_nutriments.pl index 39ba24e9df63d..3b5b92cb48b44 100755 --- a/scripts/obsolete/update_all_products_unknown_nutriments.pl +++ b/scripts/obsolete/update_all_products_unknown_nutriments.pl @@ -26,6 +26,7 @@ use utf8; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; @@ -77,7 +78,7 @@ # Store - store("$data_root/products/$path/product.sto", $product_ref); + store("$BASE_DIRS{PRODUCTS}/$path/product.sto", $product_ref); $products_collection->save($product_ref); print STDERR "updated product $code\n"; diff --git a/scripts/obsolete/update_all_products_zero_scans.pl b/scripts/obsolete/update_all_products_zero_scans.pl index ccb809035356b..7a2a1bd545312 100755 --- a/scripts/obsolete/update_all_products_zero_scans.pl +++ b/scripts/obsolete/update_all_products_zero_scans.pl @@ -26,6 +26,7 @@ use utf8; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; @@ -71,7 +72,7 @@ # Store - store( "$data_root/products/$path/product.sto", $product_ref ); + store( "$BASE_DIRS{PRODUCTS}/$path/product.sto", $product_ref ); $products_collection->save($product_ref); } diff --git a/scripts/obsolete/update_users.pl b/scripts/obsolete/update_users.pl index 4a1deaf99bd74..1fa9bce8c3f8d 100755 --- a/scripts/obsolete/update_users.pl +++ b/scripts/obsolete/update_users.pl @@ -26,13 +26,14 @@ use utf8; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; my @userids; if (scalar $#userids < 0) { - opendir DH, "$data_root/users" or die "Couldn't open the current directory: $!"; + opendir DH, $BASE_DIRS{USERS} or die "Couldn't open the current directory: $!"; @userids = sort(readdir(DH)); closedir(DH); } @@ -42,7 +43,7 @@ next if $userid eq "." or $userid eq ".."; next if $userid eq 'all'; - my $user_ref = retrieve("$data_root/users/$userid"); + my $user_ref = retrieve("$BASE_DIRS{USERS}/$userid"); my @keys = qw(name email password twitter); @@ -50,7 +51,7 @@ utf8::is_utf8($user_ref->{$key}) or utf8::decode($user_ref->{$key}); } - store("$data_root/users/$userid", $user_ref); + store("$BASE_DIRS{USERS}/$userid", $user_ref); } exit(0); diff --git a/scripts/obsolete/upload_photos.pl b/scripts/obsolete/upload_photos.pl index 8355e9dc258bb..ef6e59e2bdf23 100755 --- a/scripts/obsolete/upload_photos.pl +++ b/scripts/obsolete/upload_photos.pl @@ -2,10 +2,10 @@ use CGI::Carp qw(fatalsToBrowser); -use strict; -use utf8; +use ProductOpener::PerlStandards; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; @@ -128,7 +128,7 @@ my $time = time(); -if (opendir (DH, "$images_dir")) { +if (opendir (DH, $images_dir)) { foreach my $file (sort readdir(DH)) { #next if $file gt "2013-07-13 11.02.07"; diff --git a/scripts/obsolete/usda_ndb_gen_dl_scripts.pl b/scripts/obsolete/usda_ndb_gen_dl_scripts.pl new file mode 100755 index 0000000000000..b91b82e44c631 --- /dev/null +++ b/scripts/obsolete/usda_ndb_gen_dl_scripts.pl @@ -0,0 +1,45 @@ +#!/usr/bin/perl -w + +use strict; + +my @ips = qw(fixme); + +my @keys = qw(fixme); + +my @ids = (); + +open (my $in, "<", "ids.txt"); + +my @scripts = (); + +my $i = 0; + +while (<$in>) { + chomp; + my $id = $_; + $i++; + + my $j = int ($i / 10000); + + my $key = $keys[$j]; + my $ip = $ips[$j]; + + $scripts[$j] .= <", "dl$j.sh"); + print $file <save($product_ref); } } diff --git a/scripts/reset_password_for_user.pl b/scripts/reset_password_for_user.pl index 5562d21238b75..ca817900d6494 100755 --- a/scripts/reset_password_for_user.pl +++ b/scripts/reset_password_for_user.pl @@ -26,6 +26,7 @@ use CGI::Carp qw(fatalsToBrowser); use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; @@ -39,6 +40,6 @@ use Encode; my $userid = $ARGV[0]; -my $user_ref = retrieve("$data_root/users/$userid.sto"); +my $user_ref = retrieve("$BASE_DIRS{USERS}/$userid.sto"); $user_ref->{encrypted_password} = create_password_hash(encode_utf8(decode utf8 => $ARGV[1])); -store("$data_root/users/$userid.sto", $user_ref); +store("$BASE_DIRS{USERS}/$userid.sto", $user_ref); diff --git a/scripts/revert_changes_from_user.pl b/scripts/revert_changes_from_user.pl index 8a70bdb0b4f61..b2afc37cb889c 100755 --- a/scripts/revert_changes_from_user.pl +++ b/scripts/revert_changes_from_user.pl @@ -44,7 +44,9 @@ ; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; use ProductOpener::Tags qw/:all/; @@ -98,9 +100,7 @@ sleep(5); -if (!-e "$data_root/reverted_products") { - mkdir("$data_root/reverted_products", oct(755)) or die("Could not create $data_root/reverted_products : $!\n"); -} +ensure_dir_created_or_die($BASE_DIRS{REVERTED_PRODUCTS}); while (my $product_ref = $cursor->next) { @@ -111,12 +111,12 @@ print STDERR "reverting product $code\n"; - if (!-e "$data_root/products/$path") { - print STDERR "$data_root/products/$path does not exist, skipping\n"; + if (!-e "$BASE_DIRS{PRODUCTS}/$path") { + print STDERR "$BASE_DIRS{PRODUCTS}/$path does not exist, skipping\n"; next; } - my $changes_ref = retrieve("$data_root/products/$path/changes.sto"); + my $changes_ref = retrieve("$BASE_DIRS{PRODUCTS}/$path/changes.sto"); if (not defined $changes_ref) { $changes_ref = []; } @@ -165,11 +165,11 @@ if (not exists $deleted_revs{$rev}) { my $target = "$path/$rev.sto"; $target =~ s/\//_/g; # substitute "/" by _ to have a filename - my $cmd = "mv $data_root/products/$path/$rev.sto $data_root/reverted_products/$target"; + my $cmd = "mv $BASE_DIRS{PRODUCTS}/$path/$rev.sto $BASE_DIRS{REVERTED_PRODUCTS}/$target"; print STDERR "$code - $cmd\n"; if (not $pretend) { # move revision to reverted folder to keep track - move("$data_root/products/$path/$rev.sto", "$data_root/reverted_products/$target") + move("$BASE_DIRS{PRODUCTS}/$path/$rev.sto", "$BASE_DIRS{REVERTED_PRODUCTS}/$target") or die "Could not execute $cmd : $!\n"; } # mark revision as removed @@ -184,35 +184,35 @@ my $target = "$path/product.sto"; $target =~ s/\//_/g; # keep a copy of current product - my $cmd = "mv $data_root/products/$path/product.sto $data_root/reverted_products/$target"; + my $cmd = "mv $BASE_DIRS{PRODUCTS}/$path/product.sto $BASE_DIRS{REVERTED_PRODUCTS}/$target"; print STDERR "$code - $cmd\n"; # move does not work for symlinks on different file systems - #move("$data_root/products/$path/product.sto", "$data_root/reverted_products/$target") or die "Could not execute $cmd : $!\n"; + #move("$BASE_DIRS{PRODUCTS}/$path/product.sto", "$BASE_DIRS{REVERTED_PRODUCTS}/$target") or die "Could not execute $cmd : $!\n"; if (not $pretend) { (system($cmd) == 0) or die "Could not execute $cmd : $!\n"; } # and a copy of changes.sto $target = "$path/changes.sto" . "." . time(); $target =~ s/\//_/g; - $cmd = "mv $data_root/products/$path/changes.sto $target"; + $cmd = "mv $BASE_DIRS{PRODUCTS}/$path/changes.sto $target"; print STDERR "$code - $cmd\n"; if (not $pretend) { - move("$data_root/products/$path/changes.sto", "$data_root/reverted_products/$target") + move("$BASE_DIRS{PRODUCTS}/$path/changes.sto", "$BASE_DIRS{REVERTED_PRODUCTS}/$target") or die "Could not execute $cmd : $!\n"; } # we had edits prior target user edits, rewind product to those changes if ($previous_rev > 0) { # restore revision prior to target user changes - $cmd = "ln -s $previous_rev.sto $data_root/products/$path/product.sto"; + $cmd = "ln -s $previous_rev.sto $BASE_DIRS{PRODUCTS}/$path/product.sto"; print STDERR "$code - $cmd\n"; if (not $pretend) { - symlink("$previous_rev.sto", "$data_root/products/$path/product.sto") + symlink("$previous_rev.sto", "$BASE_DIRS{PRODUCTS}/$path/product.sto") or die "Could not execute $cmd : $!\n"; } # restore changes.sto - print STDERR "updating $data_root/products/$path/changes.sto\n"; + print STDERR "updating $BASE_DIRS{PRODUCTS}/$path/changes.sto\n"; if (not $pretend) { - store("$data_root/products/$path/changes.sto", $new_changes_ref); + store("$BASE_DIRS{PRODUCTS}/$path/changes.sto", $new_changes_ref); } } diff --git a/scripts/run_cloud_vision_ocr.pl b/scripts/run_cloud_vision_ocr.pl index 1c5bb7800d1a1..2a2b289f607cd 100755 --- a/scripts/run_cloud_vision_ocr.pl +++ b/scripts/run_cloud_vision_ocr.pl @@ -27,6 +27,7 @@ binmode(STDOUT, ":encoding(UTF-8)"); use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Images qw/:all/; use AnyEvent::Inotify::Simple; @@ -34,7 +35,7 @@ use Log::Any::Adapter 'TAP'; use EV; -open(my $LOG, ">>", "$data_root/logs/run_cloud_vision_ocr.log"); +open(my $LOG, ">>", "$BASE_DIRS{LOGS}/run_cloud_vision_ocr.log"); sub send_file_to_ocr ($file) { my $destination = readlink $file; @@ -72,7 +73,7 @@ ($file) $json_file .= ".json.gz"; print $LOG "file: $file destination: $destination code: $code image_url: $image_url json_file: $json_file\n"; - open(my $gv_logs, ">>:encoding(UTF-8)", "$data_root/logs/cloud_vision.log"); + open(my $gv_logs, ">>:encoding(UTF-8)", "$BASE_DIRS{LOGS}/cloud_vision.log"); my $cloudvision_ref = send_image_to_cloud_vision($file, $json_file, \@CLOUD_VISION_FEATURES_FULL, $gv_logs); diff --git a/scripts/run_ocr.py b/scripts/run_ocr.py index 3227888ed625c..cf078d1a3d6d9 100644 --- a/scripts/run_ocr.py +++ b/scripts/run_ocr.py @@ -30,7 +30,7 @@ API_KEY ) -BASE_IMAGE_DIR = pathlib.Path("/srv2/off/html/images/products") +BASE_IMAGE_DIR = pathlib.Path("/srv/off/html/images/products") session = requests.Session() diff --git a/scripts/scanbot.pl b/scripts/scanbot.pl index a775e4315247b..efc45d0d52df7 100755 --- a/scripts/scanbot.pl +++ b/scripts/scanbot.pl @@ -30,6 +30,7 @@ use CGI::Carp qw(fatalsToBrowser); use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; @@ -110,10 +111,8 @@ # Save scan product data in /data # This scan data can then be filtered and used as input for other scripts such as add_nutriscore_to_scanbot_csv.pl -my $output_dir = "$data_root/data/scanbot.$year"; -if (!-e $output_dir) { - mkdir($output_dir, oct(755)) or die("Could not create $output_dir : $!\n"); -} +my $output_dir = "$BASE_DIRS{PRIVATE_DATA}/scanbot.$year"; +ensure_dir_created_or_die($output_dir); my %ips = (); @@ -205,7 +204,7 @@ # next if not defined retrieve_product($code); my $product_id = $code; my $path = product_path_from_id($product_id); - my $product_path = "$data_root/products/$path/product.sto"; + my $product_path = "$BASE_DIRS{PRODUCTS}/$path/product.sto"; next if !-e $product_path; $countries_ranks_for_products{$code} = {}; @@ -242,7 +241,7 @@ if ($update_scans) { - my $scans_ref = retrieve_json("$data_root/products/all_products_scans.json"); + my $scans_ref = retrieve_json("$BASE_DIRS{PRODUCTS}/all_products_scans.json"); if (not defined $scans_ref) { $scans_ref = {}; } @@ -253,7 +252,7 @@ unique_scans_n_by_country => \%countries_for_all_products, }; - store_json("$data_root/products/all_products_scans.json", $scans_ref); + store_json("$BASE_DIRS{PRODUCTS}/all_products_scans.json", $scans_ref); } print STDERR "Ranking products for all countries\n"; @@ -340,7 +339,7 @@ if ($update_scans) { - my $scans_ref = retrieve_json("$data_root/products/$path/scans.json"); + my $scans_ref = retrieve_json("$BASE_DIRS{PRODUCTS}/$path/scans.json"); if (not defined $scans_ref) { $scans_ref = {}; } @@ -352,7 +351,7 @@ unique_scans_rank_by_country => $countries_ranks_for_products{$code}, }; - store_json("$data_root/products/$path/scans.json", $scans_ref); + store_json("$BASE_DIRS{PRODUCTS}/$path/scans.json", $scans_ref); } # Update popularity_tags + add countries @@ -506,7 +505,7 @@ } else { print "updating scan count for $code\n"; - store("$data_root/products/$path/product.sto", $product_ref); + store("$BASE_DIRS{PRODUCTS}/$path/product.sto", $product_ref); get_products_collection()->replace_one({"_id" => $product_ref->{_id}}, $product_ref, {upsert => 1}); } } diff --git a/scripts/snippets/remove_broken_entry_with_empty_email.pl b/scripts/snippets/remove_broken_entry_with_empty_email.pl index e632a59226075..3bacdb2dcb010 100755 --- a/scripts/snippets/remove_broken_entry_with_empty_email.pl +++ b/scripts/snippets/remove_broken_entry_with_empty_email.pl @@ -3,11 +3,12 @@ use ProductOpener::PerlStandards; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; -my $emails_ref = retrieve("$data_root/users/users_emails.sto"); +my $emails_ref = retrieve("$BASE_DIRS{USERS}/users_emails.sto"); if (defined $emails_ref->{''}) { delete $emails_ref->{''}; - store("$data_root/users/users_emails.sto", $emails_ref); + store("$BASE_DIRS{USERS}/users_emails.sto", $emails_ref); } diff --git a/scripts/tests/test_imports_utils.sh b/scripts/tests/test_imports_utils.sh new file mode 100755 index 0000000000000..622541cec019a --- /dev/null +++ b/scripts/tests/test_imports_utils.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env bash + +. scripts/imports/imports_utils.sh + +function fail { + >&2 echo $1 + # commit suicide, as `exit`` would only exit the function + kill -SIGPIPE "$$" +} + + +TMP_DIR=$(mktemp -d) + +SUCCESS_FILE=$TMP_DIR/success + +import_since 2>$TMP_DIR/err >/dev/null +grep -q "missing path" $TMP_DIR/err || fail "should have missing path error" +mark_successful_run 2>$TMP_DIR/err +grep -q "missing path" $TMP_DIR/err || fail "should have missing path error" +[[ -f $SUCCESS_FILE ]] && fail "should not have success file" + +NO_DATA_SINCE=$(import_since $SUCCESS_FILE) + +[[ $NO_DATA_SINCE -eq 7 ]] || fail "should get 7 without any file got $NO_DATA_SINCE" + +mark_successful_run $SUCCESS_FILE + +NO_DATA_SINCE=$(import_since $SUCCESS_FILE) + +[[ $NO_DATA_SINCE -eq 1 ]] || fail "should get 1 just after run got $NO_DATA_SINCE" + +# we need eval because of redirection to a file designated by a variable +eval "date +'%s' --date='50 hours ago'>$SUCCESS_FILE" + +NO_DATA_SINCE=$(import_since $SUCCESS_FILE) + +[[ $NO_DATA_SINCE -eq 3 ]] || fail "should get 3 got $NO_DATA_SINCE" + +rm -rf $TMP_DIR + +echo "SUCCESS - "$(basename $0) \ No newline at end of file diff --git a/scripts/update_all_products.pl b/scripts/update_all_products.pl index 27141a741c935..c41be3ef65117 100755 --- a/scripts/update_all_products.pl +++ b/scripts/update_all_products.pl @@ -56,6 +56,7 @@ ; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; @@ -607,7 +608,7 @@ my $rev = $product_ref->{rev} - 1; while ($rev >= 1) { - my $rev_product_ref = retrieve("$data_root/products/$path/$rev.sto"); + my $rev_product_ref = retrieve("$BASE_DIRS{PRODUCTS}/$path/$rev.sto"); if ((defined $rev_product_ref) and (defined $rev_product_ref->{ingredients_text_es})) { my $rindex = rindex($rev_product_ref->{ingredients_text_es}, $current_ingredients); @@ -699,7 +700,7 @@ if ($fix_rev_not_incremented) { # https://github.com/openfoodfacts/openfoodfacts-server/issues/2321 - my $changes_ref = retrieve("$data_root/products/$path/changes.sto"); + my $changes_ref = retrieve("$BASE_DIRS{PRODUCTS}/$path/changes.sto"); if (defined $changes_ref) { my $change_ref = $changes_ref->[-1]; my $last_rev = $change_ref->{rev}; @@ -712,7 +713,7 @@ my $blame_ref = {}; compute_product_history_and_completeness($data_root, $product_ref, $changes_ref, $blame_ref); compute_data_sources($product_ref, $changes_ref); - store("$data_root/products/$path/changes.sto", $changes_ref); + store("$BASE_DIRS{PRODUCTS}/$path/changes.sto", $changes_ref); } else { next; @@ -838,9 +839,9 @@ require File::Copy; foreach my $size (100, 200, 400, "full") { - my $source = "$www_root/images/products/$path/${imgid}_zu.$rev.$size.jpg"; + my $source = "$BASE_DIRS{PRODUCTS_IMAGES}/$path/${imgid}_zu.$rev.$size.jpg"; my $target - = "$www_root/images/products/$path/${imgid}_" + = "$BASE_DIRS{PRODUCTS_IMAGES}/$path/${imgid}_" . $product_ref->{lc} . ".$rev.$size.jpg"; print STDERR "move $source to $target\n"; @@ -982,7 +983,7 @@ # Save product so that OCR results now: # autorotate may call image_process_crop which will read the product file on disk and # write a new one - store("$data_root/products/$path/product.sto", $product_ref); + store("$BASE_DIRS{PRODUCTS}/$path/product.sto", $product_ref); eval { @@ -1063,7 +1064,7 @@ } if ($compute_data_sources) { - my $changes_ref = retrieve("$data_root/products/$path/changes.sto"); + my $changes_ref = retrieve("$BASE_DIRS{PRODUCTS}/$path/changes.sto"); if (not defined $changes_ref) { $changes_ref = []; } @@ -1131,7 +1132,7 @@ if ($fix_yuka_salt) { # https://github.com/openfoodfacts/openfoodfacts-server/issues/2945 my $blame_ref = {}; - my $changes_ref = retrieve("$data_root/products/$path/changes.sto"); + my $changes_ref = retrieve("$BASE_DIRS{PRODUCTS}/$path/changes.sto"); compute_product_history_and_completeness($data_root, $product_ref, $changes_ref, $blame_ref); if ( @@ -1243,18 +1244,18 @@ } if (($compute_history) or ((defined $User_id) and ($User_id ne '') and ($product_values_changed))) { - my $changes_ref = retrieve("$data_root/products/$path/changes.sto"); + my $changes_ref = retrieve("$BASE_DIRS{PRODUCTS}/$path/changes.sto"); if (not defined $changes_ref) { $changes_ref = []; } my $blame_ref = {}; compute_product_history_and_completeness($data_root, $product_ref, $changes_ref, $blame_ref); compute_data_sources($product_ref, $changes_ref); - store("$data_root/products/$path/changes.sto", $changes_ref); + store("$BASE_DIRS{PRODUCTS}/$path/changes.sto", $changes_ref); } if ($restore_values_deleted_by_user) { - my $changes_ref = retrieve("$data_root/products/$path/changes.sto"); + my $changes_ref = retrieve("$BASE_DIRS{PRODUCTS}/$path/changes.sto"); if (not defined $changes_ref) { $changes_ref = []; } @@ -1272,7 +1273,7 @@ $rev = $revs; # was not set before June 2012 } - my $rev_product_ref = retrieve("$data_root/products/$path/$rev.sto"); + my $rev_product_ref = retrieve("$BASE_DIRS{PRODUCTS}/$path/$rev.sto"); if (defined $rev_product_ref) { @@ -1364,7 +1365,7 @@ if (!$mongodb_to_mongodb) { # Store data to .sto file - store("$data_root/products/$path/product.sto", $product_ref); + store("$BASE_DIRS{PRODUCTS}/$path/product.sto", $product_ref); } # Store data to mongodb diff --git a/scripts/update_all_products_from_dir_in_mongodb.pl b/scripts/update_all_products_from_dir_in_mongodb.pl index bbb31cb5ac984..2da3e5d11aacb 100755 --- a/scripts/update_all_products_from_dir_in_mongodb.pl +++ b/scripts/update_all_products_from_dir_in_mongodb.pl @@ -26,6 +26,7 @@ use CGI::Carp qw(fatalsToBrowser); use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; @@ -94,10 +95,10 @@ ($$) if (not defined $owner) { die("The owner must be specified on the producers platform"); } - find_products("$data_root/products/$owner", ''); + find_products("$BASE_DIRS{PRODUCTS}/$owner", ''); } else { - find_products("$data_root/products", ''); + find_products($BASE_DIRS{PRODUCTS}, ''); } } @@ -118,8 +119,8 @@ ($$) my $path = product_path_from_id($product_id); #my $product_ref = retrieve_product($code); - my $product_ref = retrieve("$data_root/products/$path/product.sto") - or print "not defined $data_root/products/$path/product.sto\n"; + my $product_ref = retrieve("$BASE_DIRS{PRODUCTS}/$path/product.sto") + or print "not defined $BASE_DIRS{PRODUCTS}/$path/product.sto\n"; if ((defined $product_ref)) { diff --git a/scripts/update_recent_changes.pl b/scripts/update_recent_changes.pl index a8b8e3fa5a343..c0dbbb99fbc3e 100755 --- a/scripts/update_recent_changes.pl +++ b/scripts/update_recent_changes.pl @@ -11,6 +11,7 @@ use CGI::Carp qw(fatalsToBrowser); use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use ProductOpener::Store qw/:all/; use ProductOpener::Index qw/:all/; use ProductOpener::Display qw/:all/; @@ -57,7 +58,7 @@ my $code = $product_ref->{code}; my $path = product_path($product_ref); - my $changes_path = "$data_root/products/$path/changes.sto"; + my $changes_path = "$BASE_DIRS{PRODUCTS}/$path/changes.sto"; print STDERR "updating product $code from $changes_path\n"; my $changes_ref = retrieve($changes_path); diff --git a/scripts/update_top_translators.pl b/scripts/update_top_translators.pl index b58c125f7d157..444a443d37b1b 100755 --- a/scripts/update_top_translators.pl +++ b/scripts/update_top_translators.pl @@ -25,6 +25,7 @@ use Exporter qw< import >; use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; use LWP::UserAgent; use JSON::PP; @@ -87,7 +88,7 @@ sub download_export { print STDERR "download_export: success\n"; my $csv_response = $res->decoded_content; - my $filename = "$www_root/data/top_translators.csv"; + my $filename = "$BASE_DIRS{PUBLIC_DATA}/top_translators.csv"; print STDERR "download_export: saving response to $filename\n"; open(my $OUT, ">:encoding(UTF-8)", $filename); diff --git a/stop_words.txt b/stop_words.txt index eb226cc3f399c..64015d94a4c84 100644 --- a/stop_words.txt +++ b/stop_words.txt @@ -21,6 +21,7 @@ aromatisées arôme auth autocomplete +autocompletion backend backticks barcode @@ -60,6 +61,7 @@ dataset datasets de dont +dropdown ecoscore eg emb @@ -140,6 +142,7 @@ malus margarines matche md +memcached métal microservice microservices @@ -202,6 +205,7 @@ saturés scanbot scrypt Scrypt +sftp sirop slad Sonnenblumen diff --git a/templates/api/knowledge-panels/environment/ecoscore/ecoscore.tt.json b/templates/api/knowledge-panels/environment/ecoscore/ecoscore.tt.json index 276c315187f1d..eba0a4d51523e 100644 --- a/templates/api/knowledge-panels/environment/ecoscore/ecoscore.tt.json +++ b/templates/api/knowledge-panels/environment/ecoscore/ecoscore.tt.json @@ -4,7 +4,7 @@ "environment" ], "title_element": { - "icon_url": "[% static_subdomain %]/images/attributes/ecoscore-[% panel.grade %].svg", + "icon_url": "[% static_subdomain %]/images/attributes/dist/ecoscore-[% panel.grade %].svg", "title": "[% panel.title %]", "type": "grade", "grade": "[% panel.grade %]", diff --git a/templates/api/knowledge-panels/environment/ecoscore/ecoscore_not_applicable.tt.json b/templates/api/knowledge-panels/environment/ecoscore/ecoscore_not_applicable.tt.json index 8301f4d38b3b1..0d643d68c1ad9 100644 --- a/templates/api/knowledge-panels/environment/ecoscore/ecoscore_not_applicable.tt.json +++ b/templates/api/knowledge-panels/environment/ecoscore/ecoscore_not_applicable.tt.json @@ -4,7 +4,7 @@ "environment" ], "title_element": { - "icon_url": "[% static_subdomain %]/images/attributes/ecoscore-not-applicable.svg", + "icon_url": "[% static_subdomain %]/images/attributes/dist/ecoscore-not-applicable.svg", "title": "[% lang("attribute_ecoscore_not_applicable_title") %]", "subtitle": "[% panel.subtitle %]", "type": "grade", diff --git a/templates/api/knowledge-panels/environment/ecoscore/ecoscore_unknown.tt.json b/templates/api/knowledge-panels/environment/ecoscore/ecoscore_unknown.tt.json index 16f563a1bcfb4..e1f718cb2de33 100644 --- a/templates/api/knowledge-panels/environment/ecoscore/ecoscore_unknown.tt.json +++ b/templates/api/knowledge-panels/environment/ecoscore/ecoscore_unknown.tt.json @@ -4,7 +4,7 @@ "environment" ], "title_element": { - "icon_url": "[% static_subdomain %]/images/attributes/ecoscore-unknown.svg", + "icon_url": "[% static_subdomain %]/images/attributes/dist/ecoscore-unknown.svg", "title": "[% lang("attribute_ecoscore_unknown_title") %] - [% lang("attribute_ecoscore_unknown_description_short") %]", "type": "grade", "grade": "unknown", diff --git a/templates/api/knowledge-panels/environment/ecoscore/total.tt.json b/templates/api/knowledge-panels/environment/ecoscore/total.tt.json index 18df5d490439e..906122a64970d 100644 --- a/templates/api/knowledge-panels/environment/ecoscore/total.tt.json +++ b/templates/api/knowledge-panels/environment/ecoscore/total.tt.json @@ -9,7 +9,7 @@ "subtitle": "[% lang("front_alt") %][% sep %]: [% product_name_brand_quantity(product) %]", "type": "grade", "grade": "[% panel.grade %]", - "icon_url": "[% static_subdomain %]/images/attributes/ecoscore-[% panel.grade %].svg", + "icon_url": "[% static_subdomain %]/images/attributes/dist/ecoscore-[% panel.grade %].svg", }, "elements": [ { diff --git a/templates/api/knowledge-panels/health/ingredients/nova.tt.json b/templates/api/knowledge-panels/health/ingredients/nova.tt.json index ad53f94965ac3..cfc8edc75105f 100644 --- a/templates/api/knowledge-panels/health/ingredients/nova.tt.json +++ b/templates/api/knowledge-panels/health/ingredients/nova.tt.json @@ -6,10 +6,10 @@ "title_element": { [% IF product.nova_group.defined && product.nova_group > 0 %] [% SET nova_group = product.nova_group %] - "icon_url": "[% static_subdomain %]/images/attributes/nova-group-[% product.nova_group %].svg", + "icon_url": "[% static_subdomain %]/images/attributes/dist/nova-group-[% product.nova_group %].svg", "title": "[% lang('attribute_nova_' _ nova_group _ '_description_short') %]", [% ELSE %] - "icon_url": "[% static_subdomain %]/images/attributes/nova-group-unknown.svg", + "icon_url": "[% static_subdomain %]/images/attributes/dist/nova-group-unknown.svg", "title": "[% lang('attribute_nova_unknown_description_short') %]", [% END %] }, diff --git a/templates/api/knowledge-panels/health/nutriscore/nutriscore.tt.json b/templates/api/knowledge-panels/health/nutriscore/nutriscore.tt.json index 92c8c308d1470..054d0e0564e73 100644 --- a/templates/api/knowledge-panels/health/nutriscore/nutriscore.tt.json +++ b/templates/api/knowledge-panels/health/nutriscore/nutriscore.tt.json @@ -4,7 +4,7 @@ "health" ], "title_element": { - "icon_url": "[% static_subdomain %]/images/attributes/nutriscore-[% panel.nutriscore_grade %].svg", + "icon_url": "[% static_subdomain %]/images/attributes/dist/nutriscore-[% panel.nutriscore_grade %].svg", [% IF panel.nutriscore_unknown_reason_short %] "subtitle": "[% panel.nutriscore_unknown_reason_short %]", [% END %] diff --git a/templates/web/pages/product/includes/nutriscore.tt.html b/templates/web/pages/product/includes/nutriscore.tt.html index 73d706b423a94..cfd289003bc8a 100644 --- a/templates/web/pages/product/includes/nutriscore.tt.html +++ b/templates/web/pages/product/includes/nutriscore.tt.html @@ -7,7 +7,7 @@

    [% lang('nutrition_grade_fr_title') %] [% IF nutriscore_grade.defined %] - [% lang('nutrition_grade_fr_alt}') %] [% nutriscore_grade | ucfirst %] + [% lang('nutrition_grade_fr_alt}') %] [% nutriscore_grade | ucfirst %]
    [% END %] diff --git a/tests/integration/convert_and_import_excel_file.t b/tests/integration/convert_and_import_excel_file.t index 61d31ea9a765a..40e8cd7aca745 100644 --- a/tests/integration/convert_and_import_excel_file.t +++ b/tests/integration/convert_and_import_excel_file.t @@ -14,6 +14,7 @@ use File::Path qw/make_path remove_tree/; use ProductOpener::Config '$data_root'; use ProductOpener::Data qw/execute_query get_products_collection/; use ProductOpener::Producers qw/load_csv_or_excel_file convert_file/; +use ProductOpener::Paths qw/%BASE_DIRS/; use ProductOpener::Products "retrieve_product"; use ProductOpener::Store "store"; use ProductOpener::Test qw/:all/; @@ -46,19 +47,19 @@ sub fake_download_image ($) { my @tests = ( { - test_case => "test", + id => "test", excel_file => "test.xlsx", columns_fields_json => "test.columns_fields.json", default_values => {lc => "en", countries => "en", brands => "Default brand"}, }, { - test_case => "packagings-mousquetaires", + id => "packagings-mousquetaires", excel_file => "packagings-mousquetaires.xlsx", columns_fields_json => "packagings-mousquetaires.columns_fields.json", default_values => {lc => "fr", countries => "fr"}, }, { - test_case => "carrefour-images", + id => "carrefour-images", excel_file => "carrefour-images.csv", columns_fields_json => "carrefour-images.columns_fields.json", default_values => {lc => "fr", countries => "fr"}, @@ -78,7 +79,7 @@ foreach my $test_ref (@tests) { my $columns_fields_json = $inputs_dir . $test_ref->{columns_fields_json}; # expected results - my $test_case = $test_ref->{test_case}; + my $test_case = $test_ref->{id}; my $expected_test_results_dir = $expected_results_dir . "/" . $test_case; my $outputs_test_dir = $outputs_dir . "/" . $test_case; make_path($outputs_test_dir); @@ -110,10 +111,10 @@ foreach my $test_ref (@tests) { # Compare the converted CSV file to the expected CSV file ensure_expected_results_dir($expected_test_results_dir . "/converted_csv", $update_expected_results); compare_csv_file_to_expected_results($converted_file, $expected_test_results_dir . "/converted_csv", - $update_expected_results); + $update_expected_results, "$test_case - convert csv"); compare_to_expected_results($conv_results_ref, $expected_test_results_dir . "/converted_csv/conversion_results.json", - $update_expected_results); + $update_expected_results, {id => "$test_case - convert"}); # step4 import file my $datestring = localtime(); @@ -126,6 +127,9 @@ foreach my $test_ref (@tests) { "images_download_dir" => $outputs_test_dir . "/images", }; + # we need to put $outputs_test_dir in base paths to have ensure_dir_created working + $BASE_DIRS{TEST_DL_IMAGES_DIR} = $outputs_dir; + my $stats_ref; # run @@ -146,7 +150,8 @@ foreach my $test_ref (@tests) { normalize_products_for_test_comparison(\@products); # verify result - compare_array_to_expected_results(\@products, $expected_test_results_dir . "/products", $update_expected_results); + compare_array_to_expected_results(\@products, $expected_test_results_dir . "/products", + $update_expected_results, "$test_case - import"); # also verify sto if (!$update_expected_results) { @@ -156,11 +161,11 @@ foreach my $test_ref (@tests) { } normalize_products_for_test_comparison(\@sto_products); compare_array_to_expected_results(\@products, $expected_test_results_dir . "/products", - $update_expected_results); + $update_expected_results, "$test_case - import sto"); } compare_to_expected_results($stats_ref, $expected_test_results_dir . "/products/stats.json", - $update_expected_results); + $update_expected_results, {id => "$test_case - import stats"}); # TODO verify images # clean csv and sto @@ -169,4 +174,6 @@ foreach my $test_ref (@tests) { rmdir remove_tree($outputs_dir); } +delete($BASE_DIRS{TEST_DL_IMAGES_DIR}); + done_testing(); diff --git a/tests/integration/create_user.t b/tests/integration/create_user.t index b1c5c394fb07b..3903e59c85acb 100644 --- a/tests/integration/create_user.t +++ b/tests/integration/create_user.t @@ -8,12 +8,13 @@ use ProductOpener::Test qw/:all/; use ProductOpener::TestDefaults qw/:all/; use ProductOpener::Config qw/:all/; use ProductOpener::Users qw/:all/; +use ProductOpener::Paths qw/:all/; remove_all_users(); wait_application_ready(); # we need to create spam user log to be able to tail on it -open(my $log, ">>", "$data_root/logs/user_spam.log"); -$log . close(); +open(my $log, ">>", "$BASE_DIRS{LOGS}/user_spam.log"); +close($log); my $ua = new_client(); @@ -48,7 +49,7 @@ foreach my $args_ref (["name", "click http://test.com"], ["faxnumber", "0"]) { my $userid = "bob$testnum"; my %create_user_args = (%default_user_form, ($arg_name => $arg_value, "userid" => $userid, email => "bob$testnum\@test.com")); - my $logid = tail_log_start("$data_root//logs/user_spam.log"); + my $logid = tail_log_start("$BASE_DIRS{LOGS}/user_spam.log"); $response = create_user($ua, \%create_user_args); my $logged = tail_log_read($logid); like($response->content, qr/class="error_page"/, "Error in the page - $testnum"); diff --git a/tests/integration/expected_test_results/api_v2_product_read/get-attribute-groups-fr.json b/tests/integration/expected_test_results/api_v2_product_read/get-attribute-groups-fr.json index c5e341d3c98be..db7b64fe70d44 100644 --- a/tests/integration/expected_test_results/api_v2_product_read/get-attribute-groups-fr.json +++ b/tests/integration/expected_test_results/api_v2_product_read/get-attribute-groups-fr.json @@ -8,7 +8,7 @@ "description" : "", "description_short" : "Données manquantes pour calculer le Nutri-Score", "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nutriscore-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nutriscore-unknown.svg", "id" : "nutriscore", "match" : 0, "name" : "Nutri-Score", @@ -18,7 +18,7 @@ }, { "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nutrient-level-salt-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nutrient-level-salt-unknown.svg", "id" : "low_salt", "missing" : "Données nutritionnelles manquantes", "name" : "Sel", @@ -27,7 +27,7 @@ }, { "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nutrient-level-fat-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nutrient-level-fat-unknown.svg", "id" : "low_fat", "missing" : "Données nutritionnelles manquantes", "name" : "Matières grasses", @@ -36,7 +36,7 @@ }, { "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nutrient-level-sugars-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nutrient-level-sugars-unknown.svg", "id" : "low_sugars", "missing" : "Données nutritionnelles manquantes", "name" : "Sucres", @@ -45,7 +45,7 @@ }, { "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nutrient-level-saturated-fat-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nutrient-level-saturated-fat-unknown.svg", "id" : "low_saturated_fat", "missing" : "Données nutritionnelles manquantes", "name" : "Acides gras saturés", @@ -61,7 +61,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-gluten.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-gluten.svg", "id" : "allergens_no_gluten", "match" : 100, "name" : "Gluten", @@ -71,7 +71,7 @@ { "debug" : "en:milk in allergens", "grade" : "e", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/contains-milk.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/contains-milk.svg", "id" : "allergens_no_milk", "match" : 0, "name" : "Lait", @@ -81,7 +81,7 @@ { "debug" : "en:eggs in allergens", "grade" : "e", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/contains-eggs.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/contains-eggs.svg", "id" : "allergens_no_eggs", "match" : 0, "name" : "Œufs", @@ -91,7 +91,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-nuts.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-nuts.svg", "id" : "allergens_no_nuts", "match" : 100, "name" : "Fruits à coque", @@ -101,7 +101,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-peanuts.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-peanuts.svg", "id" : "allergens_no_peanuts", "match" : 100, "name" : "Arachides", @@ -111,7 +111,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-sesame-seeds.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-sesame-seeds.svg", "id" : "allergens_no_sesame_seeds", "match" : 100, "name" : "Graines de sésame", @@ -121,7 +121,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-soybeans.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-soybeans.svg", "id" : "allergens_no_soybeans", "match" : 100, "name" : "Soja", @@ -131,7 +131,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-celery.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-celery.svg", "id" : "allergens_no_celery", "match" : 100, "name" : "Céleri", @@ -141,7 +141,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-mustard.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-mustard.svg", "id" : "allergens_no_mustard", "match" : 100, "name" : "Moutarde", @@ -151,7 +151,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-lupin.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-lupin.svg", "id" : "allergens_no_lupin", "match" : 100, "name" : "Lupin", @@ -161,7 +161,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-fish.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-fish.svg", "id" : "allergens_no_fish", "match" : 100, "name" : "Poisson", @@ -171,7 +171,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-crustaceans.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-crustaceans.svg", "id" : "allergens_no_crustaceans", "match" : 100, "name" : "Crustacés", @@ -181,7 +181,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-molluscs.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-molluscs.svg", "id" : "allergens_no_molluscs", "match" : 100, "name" : "Mollusques", @@ -191,7 +191,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-sulphur-dioxide-and-sulphites.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-sulphur-dioxide-and-sulphites.svg", "id" : "allergens_no_sulphur_dioxide_and_sulphites", "match" : 100, "name" : "Anhydride sulfureux et sulfites", @@ -207,7 +207,7 @@ "attributes" : [ { "grade" : "e", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/non-vegan.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/non-vegan.svg", "id" : "vegan", "match" : 0, "name" : "Végétalien", @@ -217,7 +217,7 @@ }, { "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/vegetarian.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/vegetarian.svg", "id" : "vegetarian", "match" : 100, "name" : "Végétarien", @@ -227,7 +227,7 @@ }, { "grade" : "e", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/contains-palm-oil.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/contains-palm-oil.svg", "id" : "palm_oil_free", "match" : 0, "name" : "Sans huile de palme", @@ -245,7 +245,7 @@ "description" : "", "description_short" : "Aliments transformés", "grade" : "b", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nova-group-3.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nova-group-3.svg", "id" : "nova", "match" : 75, "name" : "Groupe NOVA", @@ -255,7 +255,7 @@ }, { "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/0-additives.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/0-additives.svg", "id" : "additives", "match" : 100, "name" : "Additifs", @@ -273,7 +273,7 @@ "description" : "", "description_short" : "Impact modéré sur l'environnement", "grade" : "c", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/ecoscore-c.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/ecoscore-c.svg", "id" : "ecoscore", "match" : 47, "name" : "Eco-Score", @@ -285,7 +285,7 @@ "description" : "", "description_short" : "Pas de risque de déforestation", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/forest-footprint-a.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/forest-footprint-a.svg", "id" : "forest_footprint", "match" : 99.9416666666667, "name" : "Empreinte forêt", @@ -302,7 +302,7 @@ "description" : "L'agriculture biologique vise à protéger l'environnement et à conserver la biodiversité en prohibant ou limitant l'utilisation d'engrais synthétiques, de pesticides et d'additifs alimentaires.", "description_short" : "Encourage la durabilité écologique et la biodiversité.", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/organic.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/organic.svg", "id" : "labels_organic", "match" : 100, "name" : "Agriculture biologique", @@ -313,7 +313,7 @@ "description" : "Quand vous achetez des produits du commerce équitable, les producteurs dans les pays en développement sont payés un prix plus haut et plus équitable, ce qui les aide à atteindre des plus hauts standards sociaux et environnementaux et à les conserver.", "description_short" : "Les produits du commerce équitable aident les producteurs des pays en voie de développement.", "grade" : "e", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/not-fair-trade.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/not-fair-trade.svg", "id" : "labels_fair_trade", "match" : 0, "name" : "Commerce équitable", diff --git a/tests/integration/expected_test_results/api_v2_product_read/get-attribute-groups.json b/tests/integration/expected_test_results/api_v2_product_read/get-attribute-groups.json index adde97493ac12..d39d9a5c6e3ee 100644 --- a/tests/integration/expected_test_results/api_v2_product_read/get-attribute-groups.json +++ b/tests/integration/expected_test_results/api_v2_product_read/get-attribute-groups.json @@ -8,7 +8,7 @@ "description" : "", "description_short" : "Missing data to compute the Nutri-Score", "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nutriscore-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nutriscore-unknown.svg", "id" : "nutriscore", "match" : 0, "name" : "Nutri-Score", @@ -18,7 +18,7 @@ }, { "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nutrient-level-salt-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nutrient-level-salt-unknown.svg", "id" : "low_salt", "missing" : "Missing nutrition facts", "name" : "Salt", @@ -27,7 +27,7 @@ }, { "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nutrient-level-fat-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nutrient-level-fat-unknown.svg", "id" : "low_fat", "missing" : "Missing nutrition facts", "name" : "Fat", @@ -36,7 +36,7 @@ }, { "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nutrient-level-sugars-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nutrient-level-sugars-unknown.svg", "id" : "low_sugars", "missing" : "Missing nutrition facts", "name" : "Sugars", @@ -45,7 +45,7 @@ }, { "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nutrient-level-saturated-fat-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nutrient-level-saturated-fat-unknown.svg", "id" : "low_saturated_fat", "missing" : "Missing nutrition facts", "name" : "Saturated fat", @@ -61,7 +61,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-gluten.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-gluten.svg", "id" : "allergens_no_gluten", "match" : 100, "name" : "Gluten", @@ -71,7 +71,7 @@ { "debug" : "en:milk in allergens", "grade" : "e", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/contains-milk.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/contains-milk.svg", "id" : "allergens_no_milk", "match" : 0, "name" : "Milk", @@ -81,7 +81,7 @@ { "debug" : "en:eggs in allergens", "grade" : "e", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/contains-eggs.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/contains-eggs.svg", "id" : "allergens_no_eggs", "match" : 0, "name" : "Eggs", @@ -91,7 +91,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-nuts.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-nuts.svg", "id" : "allergens_no_nuts", "match" : 100, "name" : "Nuts", @@ -101,7 +101,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-peanuts.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-peanuts.svg", "id" : "allergens_no_peanuts", "match" : 100, "name" : "Peanuts", @@ -111,7 +111,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-sesame-seeds.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-sesame-seeds.svg", "id" : "allergens_no_sesame_seeds", "match" : 100, "name" : "Sesame seeds", @@ -121,7 +121,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-soybeans.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-soybeans.svg", "id" : "allergens_no_soybeans", "match" : 100, "name" : "Soybeans", @@ -131,7 +131,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-celery.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-celery.svg", "id" : "allergens_no_celery", "match" : 100, "name" : "Celery", @@ -141,7 +141,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-mustard.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-mustard.svg", "id" : "allergens_no_mustard", "match" : 100, "name" : "Mustard", @@ -151,7 +151,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-lupin.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-lupin.svg", "id" : "allergens_no_lupin", "match" : 100, "name" : "Lupin", @@ -161,7 +161,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-fish.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-fish.svg", "id" : "allergens_no_fish", "match" : 100, "name" : "Fish", @@ -171,7 +171,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-crustaceans.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-crustaceans.svg", "id" : "allergens_no_crustaceans", "match" : 100, "name" : "Crustaceans", @@ -181,7 +181,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-molluscs.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-molluscs.svg", "id" : "allergens_no_molluscs", "match" : 100, "name" : "Molluscs", @@ -191,7 +191,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-sulphur-dioxide-and-sulphites.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-sulphur-dioxide-and-sulphites.svg", "id" : "allergens_no_sulphur_dioxide_and_sulphites", "match" : 100, "name" : "Sulphur dioxide and sulphites", @@ -207,7 +207,7 @@ "attributes" : [ { "grade" : "e", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/non-vegan.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/non-vegan.svg", "id" : "vegan", "match" : 0, "name" : "Vegan", @@ -217,7 +217,7 @@ }, { "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/vegetarian.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/vegetarian.svg", "id" : "vegetarian", "match" : 100, "name" : "Vegetarian", @@ -227,7 +227,7 @@ }, { "grade" : "e", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/contains-palm-oil.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/contains-palm-oil.svg", "id" : "palm_oil_free", "match" : 0, "name" : "Palm oil free", @@ -245,7 +245,7 @@ "description" : "", "description_short" : "Processed foods", "grade" : "b", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nova-group-3.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nova-group-3.svg", "id" : "nova", "match" : 75, "name" : "NOVA group", @@ -255,7 +255,7 @@ }, { "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/0-additives.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/0-additives.svg", "id" : "additives", "match" : 100, "name" : "Additives", @@ -273,7 +273,7 @@ "description" : "", "description_short" : "Moderate environmental impact", "grade" : "c", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/ecoscore-c.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/ecoscore-c.svg", "id" : "ecoscore", "match" : 47, "name" : "Eco-Score", @@ -285,7 +285,7 @@ "description" : "", "description_short" : "Almost no risk of deforestation", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/forest-footprint-a.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/forest-footprint-a.svg", "id" : "forest_footprint", "match" : 99.9416666666667, "name" : "Forest footprint", @@ -302,7 +302,7 @@ "description" : "Organic farming aims to protect the environment and to conserve biodiversity by prohibiting or limiting the use of synthetic fertilizers, pesticides and food additives.", "description_short" : "Promotes ecological sustainability and biodiversity.", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/organic.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/organic.svg", "id" : "labels_organic", "match" : 100, "name" : "Organic farming", @@ -313,7 +313,7 @@ "description" : "When you buy fair trade products, producers in developing countries are paid an higher and fairer price, which helps them improve and sustain higher social and often environmental standards.", "description_short" : "Fair trade products help producers in developing countries.", "grade" : "e", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/not-fair-trade.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/not-fair-trade.svg", "id" : "labels_fair_trade", "match" : 0, "name" : "Fair trade", 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 fb216b7bdccc1..441dda5b95dea 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 @@ -871,7 +871,7 @@ "level" : "info", "title_element" : { "grade" : "c", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/ecoscore-c.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/ecoscore-c.svg", "title" : "Eco-Score C - Moderate environmental impact", "type" : "grade" }, @@ -1187,7 +1187,7 @@ "level" : "info", "title_element" : { "grade" : "c", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/ecoscore-c.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/ecoscore-c.svg", "subtitle" : "Product: Some product - 100 g", "title" : "Impact for this product: C (Score: 46/100)", "type" : "grade" @@ -1501,7 +1501,7 @@ ], "level" : "info", "title_element" : { - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nova-group-3.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nova-group-3.svg", "title" : "Processed foods" }, "topics" : [ @@ -1542,7 +1542,7 @@ "level" : "info", "title_element" : { "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nutriscore-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nutriscore-unknown.svg", "subtitle" : "Missing nutrition facts", "title" : "Missing data to compute the Nutri-Score", "type" : "grade" 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 785102403c65c..6d251efa526da 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 @@ -34,7 +34,7 @@ "description" : "", "description_short" : "Missing data to compute the Nutri-Score", "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nutriscore-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nutriscore-unknown.svg", "id" : "nutriscore", "match" : 0, "name" : "Nutri-Score", @@ -44,7 +44,7 @@ }, { "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nutrient-level-salt-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nutrient-level-salt-unknown.svg", "id" : "low_salt", "missing" : "Missing nutrition facts", "name" : "Salt", @@ -53,7 +53,7 @@ }, { "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nutrient-level-fat-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nutrient-level-fat-unknown.svg", "id" : "low_fat", "missing" : "Missing nutrition facts", "name" : "Fat", @@ -62,7 +62,7 @@ }, { "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nutrient-level-sugars-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nutrient-level-sugars-unknown.svg", "id" : "low_sugars", "missing" : "Missing nutrition facts", "name" : "Sugars", @@ -71,7 +71,7 @@ }, { "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nutrient-level-saturated-fat-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nutrient-level-saturated-fat-unknown.svg", "id" : "low_saturated_fat", "missing" : "Missing nutrition facts", "name" : "Saturated fat", @@ -87,7 +87,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-gluten.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-gluten.svg", "id" : "allergens_no_gluten", "match" : 100, "name" : "Gluten", @@ -97,7 +97,7 @@ { "debug" : "en:milk in allergens", "grade" : "e", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/contains-milk.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/contains-milk.svg", "id" : "allergens_no_milk", "match" : 0, "name" : "Milk", @@ -107,7 +107,7 @@ { "debug" : "en:eggs in allergens", "grade" : "e", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/contains-eggs.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/contains-eggs.svg", "id" : "allergens_no_eggs", "match" : 0, "name" : "Eggs", @@ -117,7 +117,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-nuts.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-nuts.svg", "id" : "allergens_no_nuts", "match" : 100, "name" : "Nuts", @@ -127,7 +127,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-peanuts.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-peanuts.svg", "id" : "allergens_no_peanuts", "match" : 100, "name" : "Peanuts", @@ -137,7 +137,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-sesame-seeds.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-sesame-seeds.svg", "id" : "allergens_no_sesame_seeds", "match" : 100, "name" : "Sesame seeds", @@ -147,7 +147,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-soybeans.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-soybeans.svg", "id" : "allergens_no_soybeans", "match" : 100, "name" : "Soybeans", @@ -157,7 +157,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-celery.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-celery.svg", "id" : "allergens_no_celery", "match" : 100, "name" : "Celery", @@ -167,7 +167,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-mustard.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-mustard.svg", "id" : "allergens_no_mustard", "match" : 100, "name" : "Mustard", @@ -177,7 +177,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-lupin.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-lupin.svg", "id" : "allergens_no_lupin", "match" : 100, "name" : "Lupin", @@ -187,7 +187,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-fish.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-fish.svg", "id" : "allergens_no_fish", "match" : 100, "name" : "Fish", @@ -197,7 +197,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-crustaceans.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-crustaceans.svg", "id" : "allergens_no_crustaceans", "match" : 100, "name" : "Crustaceans", @@ -207,7 +207,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-molluscs.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-molluscs.svg", "id" : "allergens_no_molluscs", "match" : 100, "name" : "Molluscs", @@ -217,7 +217,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-sulphur-dioxide-and-sulphites.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-sulphur-dioxide-and-sulphites.svg", "id" : "allergens_no_sulphur_dioxide_and_sulphites", "match" : 100, "name" : "Sulphur dioxide and sulphites", @@ -233,7 +233,7 @@ "attributes" : [ { "grade" : "e", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/non-vegan.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/non-vegan.svg", "id" : "vegan", "match" : 0, "name" : "Vegan", @@ -243,7 +243,7 @@ }, { "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/vegetarian.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/vegetarian.svg", "id" : "vegetarian", "match" : 100, "name" : "Vegetarian", @@ -253,7 +253,7 @@ }, { "grade" : "e", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/contains-palm-oil.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/contains-palm-oil.svg", "id" : "palm_oil_free", "match" : 0, "name" : "Palm oil free", @@ -271,7 +271,7 @@ "description" : "", "description_short" : "Processed foods", "grade" : "b", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nova-group-3.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nova-group-3.svg", "id" : "nova", "match" : 75, "name" : "NOVA group", @@ -281,7 +281,7 @@ }, { "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/0-additives.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/0-additives.svg", "id" : "additives", "match" : 100, "name" : "Additives", @@ -299,7 +299,7 @@ "description" : "", "description_short" : "Moderate environmental impact", "grade" : "c", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/ecoscore-c.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/ecoscore-c.svg", "id" : "ecoscore", "match" : 47, "name" : "Eco-Score", @@ -311,7 +311,7 @@ "description" : "", "description_short" : "Almost no risk of deforestation", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/forest-footprint-a.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/forest-footprint-a.svg", "id" : "forest_footprint", "match" : 99.9416666666667, "name" : "Forest footprint", @@ -328,7 +328,7 @@ "description" : "Organic farming aims to protect the environment and to conserve biodiversity by prohibiting or limiting the use of synthetic fertilizers, pesticides and food additives.", "description_short" : "Promotes ecological sustainability and biodiversity.", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/organic.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/organic.svg", "id" : "labels_organic", "match" : 100, "name" : "Organic farming", @@ -339,7 +339,7 @@ "description" : "When you buy fair trade products, producers in developing countries are paid an higher and fairer price, which helps them improve and sustain higher social and often environmental standards.", "description_short" : "Fair trade products help producers in developing countries.", "grade" : "e", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/not-fair-trade.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/not-fair-trade.svg", "id" : "labels_fair_trade", "match" : 0, "name" : "Fair trade", @@ -358,7 +358,7 @@ "description" : "", "description_short" : "Missing data to compute the Nutri-Score", "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nutriscore-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nutriscore-unknown.svg", "id" : "nutriscore", "match" : 0, "name" : "Nutri-Score", @@ -368,7 +368,7 @@ }, { "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nutrient-level-salt-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nutrient-level-salt-unknown.svg", "id" : "low_salt", "missing" : "Missing nutrition facts", "name" : "Salt", @@ -377,7 +377,7 @@ }, { "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nutrient-level-fat-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nutrient-level-fat-unknown.svg", "id" : "low_fat", "missing" : "Missing nutrition facts", "name" : "Fat", @@ -386,7 +386,7 @@ }, { "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nutrient-level-sugars-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nutrient-level-sugars-unknown.svg", "id" : "low_sugars", "missing" : "Missing nutrition facts", "name" : "Sugars", @@ -395,7 +395,7 @@ }, { "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nutrient-level-saturated-fat-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nutrient-level-saturated-fat-unknown.svg", "id" : "low_saturated_fat", "missing" : "Missing nutrition facts", "name" : "Saturated fat", @@ -411,7 +411,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-gluten.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-gluten.svg", "id" : "allergens_no_gluten", "match" : 100, "name" : "Gluten", @@ -421,7 +421,7 @@ { "debug" : "en:milk in allergens", "grade" : "e", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/contains-milk.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/contains-milk.svg", "id" : "allergens_no_milk", "match" : 0, "name" : "Milk", @@ -431,7 +431,7 @@ { "debug" : "en:eggs in allergens", "grade" : "e", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/contains-eggs.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/contains-eggs.svg", "id" : "allergens_no_eggs", "match" : 0, "name" : "Eggs", @@ -441,7 +441,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-nuts.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-nuts.svg", "id" : "allergens_no_nuts", "match" : 100, "name" : "Nuts", @@ -451,7 +451,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-peanuts.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-peanuts.svg", "id" : "allergens_no_peanuts", "match" : 100, "name" : "Peanuts", @@ -461,7 +461,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-sesame-seeds.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-sesame-seeds.svg", "id" : "allergens_no_sesame_seeds", "match" : 100, "name" : "Sesame seeds", @@ -471,7 +471,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-soybeans.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-soybeans.svg", "id" : "allergens_no_soybeans", "match" : 100, "name" : "Soybeans", @@ -481,7 +481,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-celery.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-celery.svg", "id" : "allergens_no_celery", "match" : 100, "name" : "Celery", @@ -491,7 +491,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-mustard.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-mustard.svg", "id" : "allergens_no_mustard", "match" : 100, "name" : "Mustard", @@ -501,7 +501,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-lupin.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-lupin.svg", "id" : "allergens_no_lupin", "match" : 100, "name" : "Lupin", @@ -511,7 +511,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-fish.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-fish.svg", "id" : "allergens_no_fish", "match" : 100, "name" : "Fish", @@ -521,7 +521,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-crustaceans.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-crustaceans.svg", "id" : "allergens_no_crustaceans", "match" : 100, "name" : "Crustaceans", @@ -531,7 +531,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-molluscs.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-molluscs.svg", "id" : "allergens_no_molluscs", "match" : 100, "name" : "Molluscs", @@ -541,7 +541,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-sulphur-dioxide-and-sulphites.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-sulphur-dioxide-and-sulphites.svg", "id" : "allergens_no_sulphur_dioxide_and_sulphites", "match" : 100, "name" : "Sulphur dioxide and sulphites", @@ -557,7 +557,7 @@ "attributes" : [ { "grade" : "e", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/non-vegan.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/non-vegan.svg", "id" : "vegan", "match" : 0, "name" : "Vegan", @@ -567,7 +567,7 @@ }, { "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/vegetarian.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/vegetarian.svg", "id" : "vegetarian", "match" : 100, "name" : "Vegetarian", @@ -577,7 +577,7 @@ }, { "grade" : "e", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/contains-palm-oil.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/contains-palm-oil.svg", "id" : "palm_oil_free", "match" : 0, "name" : "Palm oil free", @@ -595,7 +595,7 @@ "description" : "", "description_short" : "Processed foods", "grade" : "b", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nova-group-3.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nova-group-3.svg", "id" : "nova", "match" : 75, "name" : "NOVA group", @@ -605,7 +605,7 @@ }, { "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/0-additives.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/0-additives.svg", "id" : "additives", "match" : 100, "name" : "Additives", @@ -623,7 +623,7 @@ "description" : "", "description_short" : "Moderate environmental impact", "grade" : "c", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/ecoscore-c.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/ecoscore-c.svg", "id" : "ecoscore", "match" : 47, "name" : "Eco-Score", @@ -635,7 +635,7 @@ "description" : "", "description_short" : "Almost no risk of deforestation", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/forest-footprint-a.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/forest-footprint-a.svg", "id" : "forest_footprint", "match" : 99.9416666666667, "name" : "Forest footprint", @@ -652,7 +652,7 @@ "description" : "Organic farming aims to protect the environment and to conserve biodiversity by prohibiting or limiting the use of synthetic fertilizers, pesticides and food additives.", "description_short" : "Promotes ecological sustainability and biodiversity.", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/organic.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/organic.svg", "id" : "labels_organic", "match" : 100, "name" : "Organic farming", @@ -663,7 +663,7 @@ "description" : "When you buy fair trade products, producers in developing countries are paid an higher and fairer price, which helps them improve and sustain higher social and often environmental standards.", "description_short" : "Fair trade products help producers in developing countries.", "grade" : "e", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/not-fair-trade.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/not-fair-trade.svg", "id" : "labels_fair_trade", "match" : 0, "name" : "Fair trade", @@ -1519,7 +1519,7 @@ "level" : "info", "title_element" : { "grade" : "c", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/ecoscore-c.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/ecoscore-c.svg", "title" : "Eco-Score C - Moderate environmental impact", "type" : "grade" }, @@ -1835,7 +1835,7 @@ "level" : "info", "title_element" : { "grade" : "c", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/ecoscore-c.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/ecoscore-c.svg", "subtitle" : "Product: Some product - 100 g", "title" : "Impact for this product: C (Score: 46/100)", "type" : "grade" @@ -2149,7 +2149,7 @@ ], "level" : "info", "title_element" : { - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nova-group-3.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nova-group-3.svg", "title" : "Processed foods" }, "topics" : [ @@ -2190,7 +2190,7 @@ "level" : "info", "title_element" : { "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nutriscore-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nutriscore-unknown.svg", "subtitle" : "Missing nutrition facts", "title" : "Missing data to compute the Nutri-Score", "type" : "grade" 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 450f70ab514ae..c9740ce4bf670 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 @@ -184,7 +184,7 @@ "level" : "info", "title_element" : { "grade" : "c", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/ecoscore-c.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/ecoscore-c.svg", "title" : "Eco-Score C - Impact modéré sur l'environnement", "type" : "grade" }, @@ -500,7 +500,7 @@ "level" : "info", "title_element" : { "grade" : "c", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/ecoscore-c.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/ecoscore-c.svg", "subtitle" : "Produit : Some product - 100 g", "title" : "Impact pour ce produit: C (Score: 46/100)", "type" : "grade" @@ -814,7 +814,7 @@ ], "level" : "info", "title_element" : { - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nova-group-3.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nova-group-3.svg", "title" : "Aliments transformés" }, "topics" : [ @@ -855,7 +855,7 @@ "level" : "info", "title_element" : { "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nutriscore-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nutriscore-unknown.svg", "subtitle" : "Données nutritionnelles manquantes", "title" : "Données manquantes pour calculer le Nutri-Score", "type" : "grade" 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 f90f9337561e0..a32d59b8596fa 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 @@ -184,7 +184,7 @@ "level" : "info", "title_element" : { "grade" : "c", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/ecoscore-c.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/ecoscore-c.svg", "title" : "Eco-Score C - Moderate environmental impact", "type" : "grade" }, @@ -500,7 +500,7 @@ "level" : "info", "title_element" : { "grade" : "c", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/ecoscore-c.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/ecoscore-c.svg", "subtitle" : "Product: Some product - 100 g", "title" : "Impact for this product: C (Score: 46/100)", "type" : "grade" @@ -814,7 +814,7 @@ ], "level" : "info", "title_element" : { - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nova-group-3.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nova-group-3.svg", "title" : "Processed foods" }, "topics" : [ @@ -855,7 +855,7 @@ "level" : "info", "title_element" : { "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nutriscore-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nutriscore-unknown.svg", "subtitle" : "Missing nutrition facts", "title" : "Missing data to compute the Nutri-Score", "type" : "grade" diff --git a/tests/integration/expected_test_results/api_v3_product_read/get-attribute-groups-fr.json b/tests/integration/expected_test_results/api_v3_product_read/get-attribute-groups-fr.json index 388b8cdd6ec37..73bbba653dd75 100644 --- a/tests/integration/expected_test_results/api_v3_product_read/get-attribute-groups-fr.json +++ b/tests/integration/expected_test_results/api_v3_product_read/get-attribute-groups-fr.json @@ -9,7 +9,7 @@ "description" : "", "description_short" : "Données manquantes pour calculer le Nutri-Score", "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nutriscore-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nutriscore-unknown.svg", "id" : "nutriscore", "match" : 0, "name" : "Nutri-Score", @@ -19,7 +19,7 @@ }, { "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nutrient-level-salt-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nutrient-level-salt-unknown.svg", "id" : "low_salt", "missing" : "Données nutritionnelles manquantes", "name" : "Sel", @@ -28,7 +28,7 @@ }, { "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nutrient-level-fat-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nutrient-level-fat-unknown.svg", "id" : "low_fat", "missing" : "Données nutritionnelles manquantes", "name" : "Matières grasses", @@ -37,7 +37,7 @@ }, { "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nutrient-level-sugars-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nutrient-level-sugars-unknown.svg", "id" : "low_sugars", "missing" : "Données nutritionnelles manquantes", "name" : "Sucres", @@ -46,7 +46,7 @@ }, { "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nutrient-level-saturated-fat-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nutrient-level-saturated-fat-unknown.svg", "id" : "low_saturated_fat", "missing" : "Données nutritionnelles manquantes", "name" : "Acides gras saturés", @@ -62,7 +62,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-gluten.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-gluten.svg", "id" : "allergens_no_gluten", "match" : 100, "name" : "Gluten", @@ -72,7 +72,7 @@ { "debug" : "en:milk in allergens", "grade" : "e", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/contains-milk.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/contains-milk.svg", "id" : "allergens_no_milk", "match" : 0, "name" : "Lait", @@ -82,7 +82,7 @@ { "debug" : "en:eggs in allergens", "grade" : "e", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/contains-eggs.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/contains-eggs.svg", "id" : "allergens_no_eggs", "match" : 0, "name" : "Œufs", @@ -92,7 +92,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-nuts.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-nuts.svg", "id" : "allergens_no_nuts", "match" : 100, "name" : "Fruits à coque", @@ -102,7 +102,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-peanuts.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-peanuts.svg", "id" : "allergens_no_peanuts", "match" : 100, "name" : "Arachides", @@ -112,7 +112,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-sesame-seeds.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-sesame-seeds.svg", "id" : "allergens_no_sesame_seeds", "match" : 100, "name" : "Graines de sésame", @@ -122,7 +122,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-soybeans.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-soybeans.svg", "id" : "allergens_no_soybeans", "match" : 100, "name" : "Soja", @@ -132,7 +132,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-celery.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-celery.svg", "id" : "allergens_no_celery", "match" : 100, "name" : "Céleri", @@ -142,7 +142,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-mustard.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-mustard.svg", "id" : "allergens_no_mustard", "match" : 100, "name" : "Moutarde", @@ -152,7 +152,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-lupin.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-lupin.svg", "id" : "allergens_no_lupin", "match" : 100, "name" : "Lupin", @@ -162,7 +162,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-fish.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-fish.svg", "id" : "allergens_no_fish", "match" : 100, "name" : "Poisson", @@ -172,7 +172,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-crustaceans.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-crustaceans.svg", "id" : "allergens_no_crustaceans", "match" : 100, "name" : "Crustacés", @@ -182,7 +182,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-molluscs.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-molluscs.svg", "id" : "allergens_no_molluscs", "match" : 100, "name" : "Mollusques", @@ -192,7 +192,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-sulphur-dioxide-and-sulphites.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-sulphur-dioxide-and-sulphites.svg", "id" : "allergens_no_sulphur_dioxide_and_sulphites", "match" : 100, "name" : "Anhydride sulfureux et sulfites", @@ -208,7 +208,7 @@ "attributes" : [ { "grade" : "e", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/non-vegan.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/non-vegan.svg", "id" : "vegan", "match" : 0, "name" : "Végétalien", @@ -218,7 +218,7 @@ }, { "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/vegetarian.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/vegetarian.svg", "id" : "vegetarian", "match" : 100, "name" : "Végétarien", @@ -228,7 +228,7 @@ }, { "grade" : "e", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/contains-palm-oil.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/contains-palm-oil.svg", "id" : "palm_oil_free", "match" : 0, "name" : "Sans huile de palme", @@ -246,7 +246,7 @@ "description" : "", "description_short" : "Aliments transformés", "grade" : "b", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nova-group-3.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nova-group-3.svg", "id" : "nova", "match" : 75, "name" : "Groupe NOVA", @@ -256,7 +256,7 @@ }, { "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/0-additives.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/0-additives.svg", "id" : "additives", "match" : 100, "name" : "Additifs", @@ -274,7 +274,7 @@ "description" : "", "description_short" : "Impact modéré sur l'environnement", "grade" : "c", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/ecoscore-c.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/ecoscore-c.svg", "id" : "ecoscore", "match" : 47, "name" : "Eco-Score", @@ -286,7 +286,7 @@ "description" : "", "description_short" : "Pas de risque de déforestation", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/forest-footprint-a.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/forest-footprint-a.svg", "id" : "forest_footprint", "match" : 99.9416666666667, "name" : "Empreinte forêt", @@ -303,7 +303,7 @@ "description" : "L'agriculture biologique vise à protéger l'environnement et à conserver la biodiversité en prohibant ou limitant l'utilisation d'engrais synthétiques, de pesticides et d'additifs alimentaires.", "description_short" : "Encourage la durabilité écologique et la biodiversité.", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/organic.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/organic.svg", "id" : "labels_organic", "match" : 100, "name" : "Agriculture biologique", @@ -314,7 +314,7 @@ "description" : "Quand vous achetez des produits du commerce équitable, les producteurs dans les pays en développement sont payés un prix plus haut et plus équitable, ce qui les aide à atteindre des plus hauts standards sociaux et environnementaux et à les conserver.", "description_short" : "Les produits du commerce équitable aident les producteurs des pays en voie de développement.", "grade" : "e", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/not-fair-trade.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/not-fair-trade.svg", "id" : "labels_fair_trade", "match" : 0, "name" : "Commerce équitable", diff --git a/tests/integration/expected_test_results/api_v3_product_read/get-attribute-groups.json b/tests/integration/expected_test_results/api_v3_product_read/get-attribute-groups.json index 8fcb487439908..057605df4a053 100644 --- a/tests/integration/expected_test_results/api_v3_product_read/get-attribute-groups.json +++ b/tests/integration/expected_test_results/api_v3_product_read/get-attribute-groups.json @@ -9,7 +9,7 @@ "description" : "", "description_short" : "Missing data to compute the Nutri-Score", "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nutriscore-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nutriscore-unknown.svg", "id" : "nutriscore", "match" : 0, "name" : "Nutri-Score", @@ -19,7 +19,7 @@ }, { "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nutrient-level-salt-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nutrient-level-salt-unknown.svg", "id" : "low_salt", "missing" : "Missing nutrition facts", "name" : "Salt", @@ -28,7 +28,7 @@ }, { "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nutrient-level-fat-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nutrient-level-fat-unknown.svg", "id" : "low_fat", "missing" : "Missing nutrition facts", "name" : "Fat", @@ -37,7 +37,7 @@ }, { "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nutrient-level-sugars-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nutrient-level-sugars-unknown.svg", "id" : "low_sugars", "missing" : "Missing nutrition facts", "name" : "Sugars", @@ -46,7 +46,7 @@ }, { "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nutrient-level-saturated-fat-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nutrient-level-saturated-fat-unknown.svg", "id" : "low_saturated_fat", "missing" : "Missing nutrition facts", "name" : "Saturated fat", @@ -62,7 +62,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-gluten.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-gluten.svg", "id" : "allergens_no_gluten", "match" : 100, "name" : "Gluten", @@ -72,7 +72,7 @@ { "debug" : "en:milk in allergens", "grade" : "e", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/contains-milk.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/contains-milk.svg", "id" : "allergens_no_milk", "match" : 0, "name" : "Milk", @@ -82,7 +82,7 @@ { "debug" : "en:eggs in allergens", "grade" : "e", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/contains-eggs.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/contains-eggs.svg", "id" : "allergens_no_eggs", "match" : 0, "name" : "Eggs", @@ -92,7 +92,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-nuts.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-nuts.svg", "id" : "allergens_no_nuts", "match" : 100, "name" : "Nuts", @@ -102,7 +102,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-peanuts.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-peanuts.svg", "id" : "allergens_no_peanuts", "match" : 100, "name" : "Peanuts", @@ -112,7 +112,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-sesame-seeds.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-sesame-seeds.svg", "id" : "allergens_no_sesame_seeds", "match" : 100, "name" : "Sesame seeds", @@ -122,7 +122,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-soybeans.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-soybeans.svg", "id" : "allergens_no_soybeans", "match" : 100, "name" : "Soybeans", @@ -132,7 +132,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-celery.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-celery.svg", "id" : "allergens_no_celery", "match" : 100, "name" : "Celery", @@ -142,7 +142,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-mustard.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-mustard.svg", "id" : "allergens_no_mustard", "match" : 100, "name" : "Mustard", @@ -152,7 +152,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-lupin.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-lupin.svg", "id" : "allergens_no_lupin", "match" : 100, "name" : "Lupin", @@ -162,7 +162,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-fish.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-fish.svg", "id" : "allergens_no_fish", "match" : 100, "name" : "Fish", @@ -172,7 +172,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-crustaceans.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-crustaceans.svg", "id" : "allergens_no_crustaceans", "match" : 100, "name" : "Crustaceans", @@ -182,7 +182,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-molluscs.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-molluscs.svg", "id" : "allergens_no_molluscs", "match" : 100, "name" : "Molluscs", @@ -192,7 +192,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-sulphur-dioxide-and-sulphites.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-sulphur-dioxide-and-sulphites.svg", "id" : "allergens_no_sulphur_dioxide_and_sulphites", "match" : 100, "name" : "Sulphur dioxide and sulphites", @@ -208,7 +208,7 @@ "attributes" : [ { "grade" : "e", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/non-vegan.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/non-vegan.svg", "id" : "vegan", "match" : 0, "name" : "Vegan", @@ -218,7 +218,7 @@ }, { "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/vegetarian.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/vegetarian.svg", "id" : "vegetarian", "match" : 100, "name" : "Vegetarian", @@ -228,7 +228,7 @@ }, { "grade" : "e", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/contains-palm-oil.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/contains-palm-oil.svg", "id" : "palm_oil_free", "match" : 0, "name" : "Palm oil free", @@ -246,7 +246,7 @@ "description" : "", "description_short" : "Processed foods", "grade" : "b", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nova-group-3.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nova-group-3.svg", "id" : "nova", "match" : 75, "name" : "NOVA group", @@ -256,7 +256,7 @@ }, { "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/0-additives.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/0-additives.svg", "id" : "additives", "match" : 100, "name" : "Additives", @@ -274,7 +274,7 @@ "description" : "", "description_short" : "Moderate environmental impact", "grade" : "c", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/ecoscore-c.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/ecoscore-c.svg", "id" : "ecoscore", "match" : 47, "name" : "Eco-Score", @@ -286,7 +286,7 @@ "description" : "", "description_short" : "Almost no risk of deforestation", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/forest-footprint-a.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/forest-footprint-a.svg", "id" : "forest_footprint", "match" : 99.9416666666667, "name" : "Forest footprint", @@ -303,7 +303,7 @@ "description" : "Organic farming aims to protect the environment and to conserve biodiversity by prohibiting or limiting the use of synthetic fertilizers, pesticides and food additives.", "description_short" : "Promotes ecological sustainability and biodiversity.", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/organic.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/organic.svg", "id" : "labels_organic", "match" : 100, "name" : "Organic farming", @@ -314,7 +314,7 @@ "description" : "When you buy fair trade products, producers in developing countries are paid an higher and fairer price, which helps them improve and sustain higher social and often environmental standards.", "description_short" : "Fair trade products help producers in developing countries.", "grade" : "e", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/not-fair-trade.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/not-fair-trade.svg", "id" : "labels_fair_trade", "match" : 0, "name" : "Fair trade", 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 05b2f8486f63f..745ea71c413d7 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 @@ -873,7 +873,7 @@ "level" : "info", "title_element" : { "grade" : "c", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/ecoscore-c.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/ecoscore-c.svg", "title" : "Eco-Score C - Moderate environmental impact", "type" : "grade" }, @@ -1189,7 +1189,7 @@ "level" : "info", "title_element" : { "grade" : "c", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/ecoscore-c.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/ecoscore-c.svg", "subtitle" : "Product: Some product - 100 g", "title" : "Impact for this product: C (Score: 46/100)", "type" : "grade" @@ -1503,7 +1503,7 @@ ], "level" : "info", "title_element" : { - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nova-group-3.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nova-group-3.svg", "title" : "Processed foods" }, "topics" : [ @@ -1544,7 +1544,7 @@ "level" : "info", "title_element" : { "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nutriscore-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nutriscore-unknown.svg", "subtitle" : "Missing nutrition facts", "title" : "Missing data to compute the Nutri-Score", "type" : "grade" 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 9dfb5cf5f2b07..5c9519c63808f 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 @@ -35,7 +35,7 @@ "description" : "", "description_short" : "Missing data to compute the Nutri-Score", "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nutriscore-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nutriscore-unknown.svg", "id" : "nutriscore", "match" : 0, "name" : "Nutri-Score", @@ -45,7 +45,7 @@ }, { "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nutrient-level-salt-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nutrient-level-salt-unknown.svg", "id" : "low_salt", "missing" : "Missing nutrition facts", "name" : "Salt", @@ -54,7 +54,7 @@ }, { "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nutrient-level-fat-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nutrient-level-fat-unknown.svg", "id" : "low_fat", "missing" : "Missing nutrition facts", "name" : "Fat", @@ -63,7 +63,7 @@ }, { "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nutrient-level-sugars-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nutrient-level-sugars-unknown.svg", "id" : "low_sugars", "missing" : "Missing nutrition facts", "name" : "Sugars", @@ -72,7 +72,7 @@ }, { "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nutrient-level-saturated-fat-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nutrient-level-saturated-fat-unknown.svg", "id" : "low_saturated_fat", "missing" : "Missing nutrition facts", "name" : "Saturated fat", @@ -88,7 +88,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-gluten.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-gluten.svg", "id" : "allergens_no_gluten", "match" : 100, "name" : "Gluten", @@ -98,7 +98,7 @@ { "debug" : "en:milk in allergens", "grade" : "e", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/contains-milk.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/contains-milk.svg", "id" : "allergens_no_milk", "match" : 0, "name" : "Milk", @@ -108,7 +108,7 @@ { "debug" : "en:eggs in allergens", "grade" : "e", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/contains-eggs.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/contains-eggs.svg", "id" : "allergens_no_eggs", "match" : 0, "name" : "Eggs", @@ -118,7 +118,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-nuts.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-nuts.svg", "id" : "allergens_no_nuts", "match" : 100, "name" : "Nuts", @@ -128,7 +128,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-peanuts.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-peanuts.svg", "id" : "allergens_no_peanuts", "match" : 100, "name" : "Peanuts", @@ -138,7 +138,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-sesame-seeds.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-sesame-seeds.svg", "id" : "allergens_no_sesame_seeds", "match" : 100, "name" : "Sesame seeds", @@ -148,7 +148,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-soybeans.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-soybeans.svg", "id" : "allergens_no_soybeans", "match" : 100, "name" : "Soybeans", @@ -158,7 +158,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-celery.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-celery.svg", "id" : "allergens_no_celery", "match" : 100, "name" : "Celery", @@ -168,7 +168,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-mustard.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-mustard.svg", "id" : "allergens_no_mustard", "match" : 100, "name" : "Mustard", @@ -178,7 +178,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-lupin.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-lupin.svg", "id" : "allergens_no_lupin", "match" : 100, "name" : "Lupin", @@ -188,7 +188,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-fish.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-fish.svg", "id" : "allergens_no_fish", "match" : 100, "name" : "Fish", @@ -198,7 +198,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-crustaceans.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-crustaceans.svg", "id" : "allergens_no_crustaceans", "match" : 100, "name" : "Crustaceans", @@ -208,7 +208,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-molluscs.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-molluscs.svg", "id" : "allergens_no_molluscs", "match" : 100, "name" : "Molluscs", @@ -218,7 +218,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-sulphur-dioxide-and-sulphites.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-sulphur-dioxide-and-sulphites.svg", "id" : "allergens_no_sulphur_dioxide_and_sulphites", "match" : 100, "name" : "Sulphur dioxide and sulphites", @@ -234,7 +234,7 @@ "attributes" : [ { "grade" : "e", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/non-vegan.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/non-vegan.svg", "id" : "vegan", "match" : 0, "name" : "Vegan", @@ -244,7 +244,7 @@ }, { "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/vegetarian.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/vegetarian.svg", "id" : "vegetarian", "match" : 100, "name" : "Vegetarian", @@ -254,7 +254,7 @@ }, { "grade" : "e", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/contains-palm-oil.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/contains-palm-oil.svg", "id" : "palm_oil_free", "match" : 0, "name" : "Palm oil free", @@ -272,7 +272,7 @@ "description" : "", "description_short" : "Processed foods", "grade" : "b", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nova-group-3.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nova-group-3.svg", "id" : "nova", "match" : 75, "name" : "NOVA group", @@ -282,7 +282,7 @@ }, { "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/0-additives.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/0-additives.svg", "id" : "additives", "match" : 100, "name" : "Additives", @@ -300,7 +300,7 @@ "description" : "", "description_short" : "Moderate environmental impact", "grade" : "c", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/ecoscore-c.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/ecoscore-c.svg", "id" : "ecoscore", "match" : 47, "name" : "Eco-Score", @@ -312,7 +312,7 @@ "description" : "", "description_short" : "Almost no risk of deforestation", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/forest-footprint-a.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/forest-footprint-a.svg", "id" : "forest_footprint", "match" : 99.9416666666667, "name" : "Forest footprint", @@ -329,7 +329,7 @@ "description" : "Organic farming aims to protect the environment and to conserve biodiversity by prohibiting or limiting the use of synthetic fertilizers, pesticides and food additives.", "description_short" : "Promotes ecological sustainability and biodiversity.", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/organic.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/organic.svg", "id" : "labels_organic", "match" : 100, "name" : "Organic farming", @@ -340,7 +340,7 @@ "description" : "When you buy fair trade products, producers in developing countries are paid an higher and fairer price, which helps them improve and sustain higher social and often environmental standards.", "description_short" : "Fair trade products help producers in developing countries.", "grade" : "e", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/not-fair-trade.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/not-fair-trade.svg", "id" : "labels_fair_trade", "match" : 0, "name" : "Fair trade", @@ -359,7 +359,7 @@ "description" : "", "description_short" : "Missing data to compute the Nutri-Score", "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nutriscore-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nutriscore-unknown.svg", "id" : "nutriscore", "match" : 0, "name" : "Nutri-Score", @@ -369,7 +369,7 @@ }, { "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nutrient-level-salt-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nutrient-level-salt-unknown.svg", "id" : "low_salt", "missing" : "Missing nutrition facts", "name" : "Salt", @@ -378,7 +378,7 @@ }, { "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nutrient-level-fat-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nutrient-level-fat-unknown.svg", "id" : "low_fat", "missing" : "Missing nutrition facts", "name" : "Fat", @@ -387,7 +387,7 @@ }, { "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nutrient-level-sugars-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nutrient-level-sugars-unknown.svg", "id" : "low_sugars", "missing" : "Missing nutrition facts", "name" : "Sugars", @@ -396,7 +396,7 @@ }, { "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nutrient-level-saturated-fat-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nutrient-level-saturated-fat-unknown.svg", "id" : "low_saturated_fat", "missing" : "Missing nutrition facts", "name" : "Saturated fat", @@ -412,7 +412,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-gluten.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-gluten.svg", "id" : "allergens_no_gluten", "match" : 100, "name" : "Gluten", @@ -422,7 +422,7 @@ { "debug" : "en:milk in allergens", "grade" : "e", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/contains-milk.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/contains-milk.svg", "id" : "allergens_no_milk", "match" : 0, "name" : "Milk", @@ -432,7 +432,7 @@ { "debug" : "en:eggs in allergens", "grade" : "e", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/contains-eggs.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/contains-eggs.svg", "id" : "allergens_no_eggs", "match" : 0, "name" : "Eggs", @@ -442,7 +442,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-nuts.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-nuts.svg", "id" : "allergens_no_nuts", "match" : 100, "name" : "Nuts", @@ -452,7 +452,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-peanuts.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-peanuts.svg", "id" : "allergens_no_peanuts", "match" : 100, "name" : "Peanuts", @@ -462,7 +462,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-sesame-seeds.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-sesame-seeds.svg", "id" : "allergens_no_sesame_seeds", "match" : 100, "name" : "Sesame seeds", @@ -472,7 +472,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-soybeans.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-soybeans.svg", "id" : "allergens_no_soybeans", "match" : 100, "name" : "Soybeans", @@ -482,7 +482,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-celery.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-celery.svg", "id" : "allergens_no_celery", "match" : 100, "name" : "Celery", @@ -492,7 +492,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-mustard.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-mustard.svg", "id" : "allergens_no_mustard", "match" : 100, "name" : "Mustard", @@ -502,7 +502,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-lupin.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-lupin.svg", "id" : "allergens_no_lupin", "match" : 100, "name" : "Lupin", @@ -512,7 +512,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-fish.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-fish.svg", "id" : "allergens_no_fish", "match" : 100, "name" : "Fish", @@ -522,7 +522,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-crustaceans.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-crustaceans.svg", "id" : "allergens_no_crustaceans", "match" : 100, "name" : "Crustaceans", @@ -532,7 +532,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-molluscs.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-molluscs.svg", "id" : "allergens_no_molluscs", "match" : 100, "name" : "Molluscs", @@ -542,7 +542,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/no-sulphur-dioxide-and-sulphites.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/no-sulphur-dioxide-and-sulphites.svg", "id" : "allergens_no_sulphur_dioxide_and_sulphites", "match" : 100, "name" : "Sulphur dioxide and sulphites", @@ -558,7 +558,7 @@ "attributes" : [ { "grade" : "e", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/non-vegan.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/non-vegan.svg", "id" : "vegan", "match" : 0, "name" : "Vegan", @@ -568,7 +568,7 @@ }, { "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/vegetarian.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/vegetarian.svg", "id" : "vegetarian", "match" : 100, "name" : "Vegetarian", @@ -578,7 +578,7 @@ }, { "grade" : "e", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/contains-palm-oil.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/contains-palm-oil.svg", "id" : "palm_oil_free", "match" : 0, "name" : "Palm oil free", @@ -596,7 +596,7 @@ "description" : "", "description_short" : "Processed foods", "grade" : "b", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nova-group-3.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nova-group-3.svg", "id" : "nova", "match" : 75, "name" : "NOVA group", @@ -606,7 +606,7 @@ }, { "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/0-additives.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/0-additives.svg", "id" : "additives", "match" : 100, "name" : "Additives", @@ -624,7 +624,7 @@ "description" : "", "description_short" : "Moderate environmental impact", "grade" : "c", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/ecoscore-c.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/ecoscore-c.svg", "id" : "ecoscore", "match" : 47, "name" : "Eco-Score", @@ -636,7 +636,7 @@ "description" : "", "description_short" : "Almost no risk of deforestation", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/forest-footprint-a.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/forest-footprint-a.svg", "id" : "forest_footprint", "match" : 99.9416666666667, "name" : "Forest footprint", @@ -653,7 +653,7 @@ "description" : "Organic farming aims to protect the environment and to conserve biodiversity by prohibiting or limiting the use of synthetic fertilizers, pesticides and food additives.", "description_short" : "Promotes ecological sustainability and biodiversity.", "grade" : "a", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/organic.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/organic.svg", "id" : "labels_organic", "match" : 100, "name" : "Organic farming", @@ -664,7 +664,7 @@ "description" : "When you buy fair trade products, producers in developing countries are paid an higher and fairer price, which helps them improve and sustain higher social and often environmental standards.", "description_short" : "Fair trade products help producers in developing countries.", "grade" : "e", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/not-fair-trade.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/not-fair-trade.svg", "id" : "labels_fair_trade", "match" : 0, "name" : "Fair trade", @@ -1521,7 +1521,7 @@ "level" : "info", "title_element" : { "grade" : "c", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/ecoscore-c.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/ecoscore-c.svg", "title" : "Eco-Score C - Moderate environmental impact", "type" : "grade" }, @@ -1837,7 +1837,7 @@ "level" : "info", "title_element" : { "grade" : "c", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/ecoscore-c.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/ecoscore-c.svg", "subtitle" : "Product: Some product - 100 g", "title" : "Impact for this product: C (Score: 46/100)", "type" : "grade" @@ -2151,7 +2151,7 @@ ], "level" : "info", "title_element" : { - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nova-group-3.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nova-group-3.svg", "title" : "Processed foods" }, "topics" : [ @@ -2192,7 +2192,7 @@ "level" : "info", "title_element" : { "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nutriscore-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nutriscore-unknown.svg", "subtitle" : "Missing nutrition facts", "title" : "Missing data to compute the Nutri-Score", "type" : "grade" 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 7b63bd1000103..38824131ad5e6 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 @@ -185,7 +185,7 @@ "level" : "info", "title_element" : { "grade" : "c", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/ecoscore-c.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/ecoscore-c.svg", "title" : "Eco-Score C - Impact modéré sur l'environnement", "type" : "grade" }, @@ -501,7 +501,7 @@ "level" : "info", "title_element" : { "grade" : "c", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/ecoscore-c.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/ecoscore-c.svg", "subtitle" : "Produit : Some product - 100 g", "title" : "Impact pour ce produit: C (Score: 46/100)", "type" : "grade" @@ -815,7 +815,7 @@ ], "level" : "info", "title_element" : { - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nova-group-3.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nova-group-3.svg", "title" : "Aliments transformés" }, "topics" : [ @@ -856,7 +856,7 @@ "level" : "info", "title_element" : { "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nutriscore-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nutriscore-unknown.svg", "subtitle" : "Données nutritionnelles manquantes", "title" : "Données manquantes pour calculer le Nutri-Score", "type" : "grade" 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 9f36fb602efb8..00b26310f9549 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 @@ -185,7 +185,7 @@ "level" : "info", "title_element" : { "grade" : "c", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/ecoscore-c.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/ecoscore-c.svg", "title" : "Eco-Score C - Moderate environmental impact", "type" : "grade" }, @@ -501,7 +501,7 @@ "level" : "info", "title_element" : { "grade" : "c", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/ecoscore-c.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/ecoscore-c.svg", "subtitle" : "Product: Some product - 100 g", "title" : "Impact for this product: C (Score: 46/100)", "type" : "grade" @@ -815,7 +815,7 @@ ], "level" : "info", "title_element" : { - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nova-group-3.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nova-group-3.svg", "title" : "Processed foods" }, "topics" : [ @@ -856,7 +856,7 @@ "level" : "info", "title_element" : { "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nutriscore-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nutriscore-unknown.svg", "subtitle" : "Missing nutrition facts", "title" : "Missing data to compute the Nutri-Score", "type" : "grade" diff --git a/tests/integration/expected_test_results/api_v3_product_write/patch-request-fields-updated-attribute-groups-knowledge-panels.json b/tests/integration/expected_test_results/api_v3_product_write/patch-request-fields-updated-attribute-groups-knowledge-panels.json index b3ae8cfb93741..e989ed12d88b3 100644 --- a/tests/integration/expected_test_results/api_v3_product_write/patch-request-fields-updated-attribute-groups-knowledge-panels.json +++ b/tests/integration/expected_test_results/api_v3_product_write/patch-request-fields-updated-attribute-groups-knowledge-panels.json @@ -9,7 +9,7 @@ "description" : "", "description_short" : "Missing data to compute the Nutri-Score", "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nutriscore-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nutriscore-unknown.svg", "id" : "nutriscore", "match" : 0, "name" : "Nutri-Score", @@ -19,7 +19,7 @@ }, { "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nutrient-level-salt-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nutrient-level-salt-unknown.svg", "id" : "low_salt", "missing" : "Missing nutrition facts", "name" : "Salt", @@ -28,7 +28,7 @@ }, { "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nutrient-level-fat-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nutrient-level-fat-unknown.svg", "id" : "low_fat", "missing" : "Missing nutrition facts", "name" : "Fat", @@ -37,7 +37,7 @@ }, { "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nutrient-level-sugars-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nutrient-level-sugars-unknown.svg", "id" : "low_sugars", "missing" : "Missing nutrition facts", "name" : "Sugars", @@ -46,7 +46,7 @@ }, { "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nutrient-level-saturated-fat-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nutrient-level-saturated-fat-unknown.svg", "id" : "low_saturated_fat", "missing" : "Missing nutrition facts", "name" : "Saturated fat", @@ -62,7 +62,7 @@ { "debug" : "missing ingredients list", "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/gluten-content-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/gluten-content-unknown.svg", "id" : "allergens_no_gluten", "name" : "Gluten", "panel_id" : "ingredients", @@ -72,7 +72,7 @@ { "debug" : "missing ingredients list", "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/milk-content-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/milk-content-unknown.svg", "id" : "allergens_no_milk", "name" : "Milk", "panel_id" : "ingredients", @@ -82,7 +82,7 @@ { "debug" : "missing ingredients list", "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/eggs-content-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/eggs-content-unknown.svg", "id" : "allergens_no_eggs", "name" : "Eggs", "panel_id" : "ingredients", @@ -92,7 +92,7 @@ { "debug" : "missing ingredients list", "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nuts-content-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nuts-content-unknown.svg", "id" : "allergens_no_nuts", "name" : "Nuts", "panel_id" : "ingredients", @@ -102,7 +102,7 @@ { "debug" : "missing ingredients list", "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/peanuts-content-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/peanuts-content-unknown.svg", "id" : "allergens_no_peanuts", "name" : "Peanuts", "panel_id" : "ingredients", @@ -112,7 +112,7 @@ { "debug" : "missing ingredients list", "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/sesame-seeds-content-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/sesame-seeds-content-unknown.svg", "id" : "allergens_no_sesame_seeds", "name" : "Sesame seeds", "panel_id" : "ingredients", @@ -122,7 +122,7 @@ { "debug" : "missing ingredients list", "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/soybeans-content-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/soybeans-content-unknown.svg", "id" : "allergens_no_soybeans", "name" : "Soybeans", "panel_id" : "ingredients", @@ -132,7 +132,7 @@ { "debug" : "missing ingredients list", "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/celery-content-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/celery-content-unknown.svg", "id" : "allergens_no_celery", "name" : "Celery", "panel_id" : "ingredients", @@ -142,7 +142,7 @@ { "debug" : "missing ingredients list", "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/mustard-content-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/mustard-content-unknown.svg", "id" : "allergens_no_mustard", "name" : "Mustard", "panel_id" : "ingredients", @@ -152,7 +152,7 @@ { "debug" : "missing ingredients list", "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/lupin-content-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/lupin-content-unknown.svg", "id" : "allergens_no_lupin", "name" : "Lupin", "panel_id" : "ingredients", @@ -162,7 +162,7 @@ { "debug" : "missing ingredients list", "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/fish-content-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/fish-content-unknown.svg", "id" : "allergens_no_fish", "name" : "Fish", "panel_id" : "ingredients", @@ -172,7 +172,7 @@ { "debug" : "missing ingredients list", "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/crustaceans-content-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/crustaceans-content-unknown.svg", "id" : "allergens_no_crustaceans", "name" : "Crustaceans", "panel_id" : "ingredients", @@ -182,7 +182,7 @@ { "debug" : "missing ingredients list", "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/molluscs-content-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/molluscs-content-unknown.svg", "id" : "allergens_no_molluscs", "name" : "Molluscs", "panel_id" : "ingredients", @@ -192,7 +192,7 @@ { "debug" : "missing ingredients list", "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/sulphur-dioxide-and-sulphites-content-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/sulphur-dioxide-and-sulphites-content-unknown.svg", "id" : "allergens_no_sulphur_dioxide_and_sulphites", "name" : "Sulphur dioxide and sulphites", "panel_id" : "ingredients", @@ -208,7 +208,7 @@ "attributes" : [ { "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/vegan-status-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/vegan-status-unknown.svg", "id" : "vegan", "name" : "Vegan", "panel_id" : "ingredients", @@ -217,7 +217,7 @@ }, { "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/vegetarian-status-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/vegetarian-status-unknown.svg", "id" : "vegetarian", "name" : "Vegetarian", "panel_id" : "ingredients", @@ -226,7 +226,7 @@ }, { "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/palm-oil-content-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/palm-oil-content-unknown.svg", "id" : "palm_oil_free", "name" : "Palm oil free", "panel_id" : "ingredients", @@ -243,7 +243,7 @@ "description" : "", "description_short" : "Food processing level unknown", "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nova-group-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nova-group-unknown.svg", "id" : "nova", "match" : 0, "name" : "NOVA group", @@ -255,7 +255,7 @@ "description" : "", "description_short" : "", "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/additives-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/additives-unknown.svg", "id" : "additives", "match" : 0, "missing" : "Missing ingredients list", @@ -274,7 +274,7 @@ "description" : "", "description_short" : "Unknown environmental impact", "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/ecoscore-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/ecoscore-unknown.svg", "id" : "ecoscore", "match" : 0, "name" : "Eco-Score", @@ -286,7 +286,7 @@ "description" : "", "description_short" : "Currently only for products with chicken or eggs", "grade" : "e", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/forest-footprint-not-computed.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/forest-footprint-not-computed.svg", "id" : "forest_footprint", "match" : 0, "name" : "Forest footprint", @@ -303,7 +303,7 @@ "description" : "Organic farming aims to protect the environment and to conserve biodiversity by prohibiting or limiting the use of synthetic fertilizers, pesticides and food additives.", "description_short" : "Organic products promote ecological sustainability and biodiversity.", "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/organic-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/organic-unknown.svg", "id" : "labels_organic", "name" : "Organic farming", "status" : "unknown", @@ -313,7 +313,7 @@ "description" : "When you buy fair trade products, producers in developing countries are paid an higher and fairer price, which helps them improve and sustain higher social and often environmental standards.", "description_short" : "Fair trade products help producers in developing countries.", "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/fair-trade-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/fair-trade-unknown.svg", "id" : "labels_fair_trade", "name" : "Fair trade", "status" : "unknown", @@ -347,7 +347,7 @@ "level" : "info", "title_element" : { "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/ecoscore-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/ecoscore-unknown.svg", "title" : "Eco-Score not computed - Unknown environmental impact", "type" : "grade" }, @@ -495,7 +495,7 @@ ], "level" : "info", "title_element" : { - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nova-group-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nova-group-unknown.svg", "title" : "Food processing level unknown" }, "topics" : [ @@ -544,7 +544,7 @@ "level" : "info", "title_element" : { "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nutriscore-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nutriscore-unknown.svg", "subtitle" : "Missing category and nutrition facts", "title" : "Missing data to compute the Nutri-Score", "type" : "grade" 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 f7f59d5419389..48ed01d496c89 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 @@ -189,7 +189,7 @@ "level" : "info", "title_element" : { "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/ecoscore-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/ecoscore-unknown.svg", "title" : "Eco-Score not computed - Unknown environmental impact", "type" : "grade" }, @@ -527,7 +527,7 @@ ], "level" : "info", "title_element" : { - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nova-group-1.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nova-group-1.svg", "title" : "Unprocessed or minimally processed foods" }, "topics" : [ @@ -610,7 +610,7 @@ "level" : "info", "title_element" : { "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nutriscore-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nutriscore-unknown.svg", "subtitle" : "Missing nutrition facts", "title" : "Missing data to compute the Nutri-Score", "type" : "grade" 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 4a3544d20d3fd..0de636c5d4dc5 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 @@ -152,7 +152,7 @@ "level" : "info", "title_element" : { "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/ecoscore-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/ecoscore-unknown.svg", "title" : "Eco-Score not computed - Unknown environmental impact", "type" : "grade" }, @@ -489,7 +489,7 @@ ], "level" : "info", "title_element" : { - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nova-group-1.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nova-group-1.svg", "title" : "Unprocessed or minimally processed foods" }, "topics" : [ @@ -530,7 +530,7 @@ "level" : "info", "title_element" : { "grade" : "unknown", - "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/nutriscore-unknown.svg", + "icon_url" : "http://static.openfoodfacts.localhost/images/attributes/dist/nutriscore-unknown.svg", "subtitle" : "Missing nutrition facts", "title" : "Missing data to compute the Nutri-Score", "type" : "grade" diff --git a/tests/integration/export.t b/tests/integration/export.t index cb400a015622e..cf54eb9dfa613 100644 --- a/tests/integration/export.t +++ b/tests/integration/export.t @@ -68,7 +68,7 @@ export_csv($export_args_ref); close($exported_csv); ProductOpener::Test::compare_csv_file_to_expected_results($exported_csv_file, $expected_result_dir, - $update_expected_results); + $update_expected_results, "csv-export"); # Export more fields @@ -84,6 +84,6 @@ export_csv($export_args_ref); close($exported_csv); ProductOpener::Test::compare_csv_file_to_expected_results($exported_csv_file, "${expected_result_dir}_more_fields", - $update_expected_results); + $update_expected_results, "csv-export-more-fields"); done_testing(); diff --git a/tests/unit/expected_test_results/attributes/en-attributes.json b/tests/unit/expected_test_results/attributes/en-attributes.json index 466f6f7c4c8c3..63462d7ef0f44 100644 --- a/tests/unit/expected_test_results/attributes/en-attributes.json +++ b/tests/unit/expected_test_results/attributes/en-attributes.json @@ -30,7 +30,7 @@ "description" : "", "description_short" : "Average nutritional quality", "grade" : "c", - "icon_url" : "https://server_domain/images/attributes/nutriscore-c.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nutriscore-c.svg", "id" : "nutriscore", "match" : 47.3333333333333, "name" : "Nutri-Score", @@ -41,7 +41,7 @@ { "description_short" : "0.25 g / 100 g", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/nutrient-level-salt-low.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nutrient-level-salt-low.svg", "id" : "low_salt", "match" : 83.3333333333333, "name" : "Salt", @@ -51,7 +51,7 @@ { "description_short" : "12 g / 100 g", "grade" : "c", - "icon_url" : "https://server_domain/images/attributes/nutrient-level-fat-medium.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nutrient-level-fat-medium.svg", "id" : "low_fat", "match" : 48.2352941176471, "name" : "Fat", @@ -61,7 +61,7 @@ { "description_short" : "25 g / 100 g", "grade" : "e", - "icon_url" : "https://server_domain/images/attributes/nutrient-level-sugars-high.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nutrient-level-sugars-high.svg", "id" : "low_sugars", "match" : 0, "name" : "Sugars", @@ -71,7 +71,7 @@ { "description_short" : "4 g / 100 g", "grade" : "d", - "icon_url" : "https://server_domain/images/attributes/nutrient-level-saturated-fat-medium.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nutrient-level-saturated-fat-medium.svg", "id" : "low_saturated_fat", "match" : 37.1428571428571, "name" : "Saturated fat", @@ -87,7 +87,7 @@ { "debug" : "en:gluten in allergens", "grade" : "e", - "icon_url" : "https://server_domain/images/attributes/contains-gluten.svg", + "icon_url" : "https://server_domain/images/attributes/dist/contains-gluten.svg", "id" : "allergens_no_gluten", "match" : 0, "name" : "Gluten", @@ -97,7 +97,7 @@ { "debug" : "11 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-milk.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-milk.svg", "id" : "allergens_no_milk", "match" : 100, "name" : "Milk", @@ -107,7 +107,7 @@ { "debug" : "11 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-eggs.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-eggs.svg", "id" : "allergens_no_eggs", "match" : 100, "name" : "Eggs", @@ -117,7 +117,7 @@ { "debug" : "11 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-nuts.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-nuts.svg", "id" : "allergens_no_nuts", "match" : 100, "name" : "Nuts", @@ -127,7 +127,7 @@ { "debug" : "11 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-peanuts.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-peanuts.svg", "id" : "allergens_no_peanuts", "match" : 100, "name" : "Peanuts", @@ -137,7 +137,7 @@ { "debug" : "11 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-sesame-seeds.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-sesame-seeds.svg", "id" : "allergens_no_sesame_seeds", "match" : 100, "name" : "Sesame seeds", @@ -147,7 +147,7 @@ { "debug" : "11 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-soybeans.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-soybeans.svg", "id" : "allergens_no_soybeans", "match" : 100, "name" : "Soybeans", @@ -157,7 +157,7 @@ { "debug" : "11 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-celery.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-celery.svg", "id" : "allergens_no_celery", "match" : 100, "name" : "Celery", @@ -167,7 +167,7 @@ { "debug" : "11 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-mustard.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-mustard.svg", "id" : "allergens_no_mustard", "match" : 100, "name" : "Mustard", @@ -177,7 +177,7 @@ { "debug" : "11 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-lupin.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-lupin.svg", "id" : "allergens_no_lupin", "match" : 100, "name" : "Lupin", @@ -187,7 +187,7 @@ { "debug" : "11 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-fish.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-fish.svg", "id" : "allergens_no_fish", "match" : 100, "name" : "Fish", @@ -197,7 +197,7 @@ { "debug" : "11 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-crustaceans.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-crustaceans.svg", "id" : "allergens_no_crustaceans", "match" : 100, "name" : "Crustaceans", @@ -207,7 +207,7 @@ { "debug" : "11 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-molluscs.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-molluscs.svg", "id" : "allergens_no_molluscs", "match" : 100, "name" : "Molluscs", @@ -217,7 +217,7 @@ { "debug" : "11 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-sulphur-dioxide-and-sulphites.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-sulphur-dioxide-and-sulphites.svg", "id" : "allergens_no_sulphur_dioxide_and_sulphites", "match" : 100, "name" : "Sulphur dioxide and sulphites", @@ -233,7 +233,7 @@ "attributes" : [ { "grade" : "e", - "icon_url" : "https://server_domain/images/attributes/non-vegan.svg", + "icon_url" : "https://server_domain/images/attributes/dist/non-vegan.svg", "id" : "vegan", "match" : 0, "name" : "Vegan", @@ -243,7 +243,7 @@ }, { "grade" : "e", - "icon_url" : "https://server_domain/images/attributes/non-vegetarian.svg", + "icon_url" : "https://server_domain/images/attributes/dist/non-vegetarian.svg", "id" : "vegetarian", "match" : 0, "name" : "Vegetarian", @@ -253,7 +253,7 @@ }, { "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/palm-oil-free.svg", + "icon_url" : "https://server_domain/images/attributes/dist/palm-oil-free.svg", "id" : "palm_oil_free", "match" : 100, "name" : "Palm oil free", @@ -271,7 +271,7 @@ "description" : "", "description_short" : "Ultra processed foods", "grade" : "e", - "icon_url" : "https://server_domain/images/attributes/nova-group-4.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nova-group-4.svg", "id" : "nova", "match" : 0, "name" : "NOVA group", @@ -281,7 +281,7 @@ }, { "grade" : "c", - "icon_url" : "https://server_domain/images/attributes/2-additives.svg", + "icon_url" : "https://server_domain/images/attributes/dist/2-additives.svg", "id" : "additives", "match" : 60, "name" : "Additives", @@ -299,7 +299,7 @@ "description" : "", "description_short" : "Low environmental impact", "grade" : "b", - "icon_url" : "https://server_domain/images/attributes/ecoscore-b.svg", + "icon_url" : "https://server_domain/images/attributes/dist/ecoscore-b.svg", "id" : "ecoscore", "match" : 68, "name" : "Eco-Score", @@ -311,7 +311,7 @@ "description" : "", "description_short" : "Almost no risk of deforestation", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/forest-footprint-a.svg", + "icon_url" : "https://server_domain/images/attributes/dist/forest-footprint-a.svg", "id" : "forest_footprint", "match" : 99.9222222222222, "name" : "Forest footprint", @@ -328,7 +328,7 @@ "description" : "Organic farming aims to protect the environment and to conserve biodiversity by prohibiting or limiting the use of synthetic fertilizers, pesticides and food additives.", "description_short" : "Promotes ecological sustainability and biodiversity.", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/organic.svg", + "icon_url" : "https://server_domain/images/attributes/dist/organic.svg", "id" : "labels_organic", "match" : 100, "name" : "Organic farming", @@ -339,7 +339,7 @@ "description" : "When you buy fair trade products, producers in developing countries are paid an higher and fairer price, which helps them improve and sustain higher social and often environmental standards.", "description_short" : "Helps producers in developing countries.", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/fair-trade.svg", + "icon_url" : "https://server_domain/images/attributes/dist/fair-trade.svg", "id" : "labels_fair_trade", "match" : 100, "name" : "Fair trade", 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 79b7c3d61a78a..050e7d6e603e4 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 @@ -15,7 +15,7 @@ "description" : "", "description_short" : "Missing data to compute the Nutri-Score", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/nutriscore-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nutriscore-unknown.svg", "id" : "nutriscore", "match" : 0, "name" : "Nutri-Score", @@ -25,7 +25,7 @@ }, { "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/nutrient-level-salt-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nutrient-level-salt-unknown.svg", "id" : "low_salt", "missing" : "Missing nutrition facts", "name" : "Salt", @@ -34,7 +34,7 @@ }, { "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/nutrient-level-fat-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nutrient-level-fat-unknown.svg", "id" : "low_fat", "missing" : "Missing nutrition facts", "name" : "Fat", @@ -43,7 +43,7 @@ }, { "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/nutrient-level-sugars-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nutrient-level-sugars-unknown.svg", "id" : "low_sugars", "missing" : "Missing nutrition facts", "name" : "Sugars", @@ -52,7 +52,7 @@ }, { "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/nutrient-level-saturated-fat-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nutrient-level-saturated-fat-unknown.svg", "id" : "low_saturated_fat", "missing" : "Missing nutrition facts", "name" : "Saturated fat", @@ -68,7 +68,7 @@ { "debug" : "missing ingredients list", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/gluten-content-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/gluten-content-unknown.svg", "id" : "allergens_no_gluten", "name" : "Gluten", "panel_id" : "ingredients", @@ -78,7 +78,7 @@ { "debug" : "missing ingredients list", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/milk-content-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/milk-content-unknown.svg", "id" : "allergens_no_milk", "name" : "Milk", "panel_id" : "ingredients", @@ -88,7 +88,7 @@ { "debug" : "missing ingredients list", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/eggs-content-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/eggs-content-unknown.svg", "id" : "allergens_no_eggs", "name" : "Eggs", "panel_id" : "ingredients", @@ -98,7 +98,7 @@ { "debug" : "missing ingredients list", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/nuts-content-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nuts-content-unknown.svg", "id" : "allergens_no_nuts", "name" : "Nuts", "panel_id" : "ingredients", @@ -108,7 +108,7 @@ { "debug" : "missing ingredients list", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/peanuts-content-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/peanuts-content-unknown.svg", "id" : "allergens_no_peanuts", "name" : "Peanuts", "panel_id" : "ingredients", @@ -118,7 +118,7 @@ { "debug" : "missing ingredients list", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/sesame-seeds-content-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/sesame-seeds-content-unknown.svg", "id" : "allergens_no_sesame_seeds", "name" : "Sesame seeds", "panel_id" : "ingredients", @@ -128,7 +128,7 @@ { "debug" : "missing ingredients list", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/soybeans-content-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/soybeans-content-unknown.svg", "id" : "allergens_no_soybeans", "name" : "Soybeans", "panel_id" : "ingredients", @@ -138,7 +138,7 @@ { "debug" : "missing ingredients list", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/celery-content-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/celery-content-unknown.svg", "id" : "allergens_no_celery", "name" : "Celery", "panel_id" : "ingredients", @@ -148,7 +148,7 @@ { "debug" : "missing ingredients list", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/mustard-content-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/mustard-content-unknown.svg", "id" : "allergens_no_mustard", "name" : "Mustard", "panel_id" : "ingredients", @@ -158,7 +158,7 @@ { "debug" : "missing ingredients list", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/lupin-content-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/lupin-content-unknown.svg", "id" : "allergens_no_lupin", "name" : "Lupin", "panel_id" : "ingredients", @@ -168,7 +168,7 @@ { "debug" : "missing ingredients list", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/fish-content-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/fish-content-unknown.svg", "id" : "allergens_no_fish", "name" : "Fish", "panel_id" : "ingredients", @@ -178,7 +178,7 @@ { "debug" : "missing ingredients list", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/crustaceans-content-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/crustaceans-content-unknown.svg", "id" : "allergens_no_crustaceans", "name" : "Crustaceans", "panel_id" : "ingredients", @@ -188,7 +188,7 @@ { "debug" : "missing ingredients list", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/molluscs-content-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/molluscs-content-unknown.svg", "id" : "allergens_no_molluscs", "name" : "Molluscs", "panel_id" : "ingredients", @@ -198,7 +198,7 @@ { "debug" : "missing ingredients list", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/sulphur-dioxide-and-sulphites-content-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/sulphur-dioxide-and-sulphites-content-unknown.svg", "id" : "allergens_no_sulphur_dioxide_and_sulphites", "name" : "Sulphur dioxide and sulphites", "panel_id" : "ingredients", @@ -214,7 +214,7 @@ "attributes" : [ { "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/vegan-status-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/vegan-status-unknown.svg", "id" : "vegan", "name" : "Vegan", "panel_id" : "ingredients", @@ -223,7 +223,7 @@ }, { "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/vegetarian-status-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/vegetarian-status-unknown.svg", "id" : "vegetarian", "name" : "Vegetarian", "panel_id" : "ingredients", @@ -232,7 +232,7 @@ }, { "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/palm-oil-content-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/palm-oil-content-unknown.svg", "id" : "palm_oil_free", "name" : "Palm oil free", "panel_id" : "ingredients", @@ -249,7 +249,7 @@ "description" : "", "description_short" : "Food processing level unknown", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/nova-group-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nova-group-unknown.svg", "id" : "nova", "match" : 0, "name" : "NOVA group", @@ -261,7 +261,7 @@ "description" : "", "description_short" : "", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/additives-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/additives-unknown.svg", "id" : "additives", "match" : 0, "missing" : "Missing ingredients list", @@ -280,7 +280,7 @@ "description" : "", "description_short" : "High environmental impact", "grade" : "d", - "icon_url" : "https://server_domain/images/attributes/ecoscore-d.svg", + "icon_url" : "https://server_domain/images/attributes/dist/ecoscore-d.svg", "id" : "ecoscore", "match" : 31, "name" : "Eco-Score", @@ -292,7 +292,7 @@ "description" : "", "description_short" : "Currently only for products with chicken or eggs", "grade" : "e", - "icon_url" : "https://server_domain/images/attributes/forest-footprint-not-computed.svg", + "icon_url" : "https://server_domain/images/attributes/dist/forest-footprint-not-computed.svg", "id" : "forest_footprint", "match" : 0, "name" : "Forest footprint", @@ -309,7 +309,7 @@ "description" : "Organic farming aims to protect the environment and to conserve biodiversity by prohibiting or limiting the use of synthetic fertilizers, pesticides and food additives.", "description_short" : "Organic products promote ecological sustainability and biodiversity.", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/organic-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/organic-unknown.svg", "id" : "labels_organic", "name" : "Organic farming", "status" : "unknown", @@ -319,7 +319,7 @@ "description" : "When you buy fair trade products, producers in developing countries are paid an higher and fairer price, which helps them improve and sustain higher social and often environmental standards.", "description_short" : "Fair trade products help producers in developing countries.", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/fair-trade-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/fair-trade-unknown.svg", "id" : "labels_fair_trade", "name" : "Fair trade", "status" : "unknown", 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 192b135eeb907..83ae545f0a119 100644 --- a/tests/unit/expected_test_results/attributes/en-maybe-vegan.json +++ b/tests/unit/expected_test_results/attributes/en-maybe-vegan.json @@ -17,7 +17,7 @@ "description" : "", "description_short" : "Missing data to compute the Nutri-Score", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/nutriscore-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nutriscore-unknown.svg", "id" : "nutriscore", "match" : 0, "name" : "Nutri-Score", @@ -27,7 +27,7 @@ }, { "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/nutrient-level-salt-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nutrient-level-salt-unknown.svg", "id" : "low_salt", "missing" : "Missing nutrition facts", "name" : "Salt", @@ -36,7 +36,7 @@ }, { "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/nutrient-level-fat-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nutrient-level-fat-unknown.svg", "id" : "low_fat", "missing" : "Missing nutrition facts", "name" : "Fat", @@ -45,7 +45,7 @@ }, { "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/nutrient-level-sugars-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nutrient-level-sugars-unknown.svg", "id" : "low_sugars", "missing" : "Missing nutrition facts", "name" : "Sugars", @@ -54,7 +54,7 @@ }, { "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/nutrient-level-saturated-fat-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nutrient-level-saturated-fat-unknown.svg", "id" : "low_saturated_fat", "missing" : "Missing nutrition facts", "name" : "Saturated fat", @@ -70,7 +70,7 @@ { "debug" : "3 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-gluten.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-gluten.svg", "id" : "allergens_no_gluten", "match" : 100, "name" : "Gluten", @@ -80,7 +80,7 @@ { "debug" : "3 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-milk.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-milk.svg", "id" : "allergens_no_milk", "match" : 100, "name" : "Milk", @@ -90,7 +90,7 @@ { "debug" : "3 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-eggs.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-eggs.svg", "id" : "allergens_no_eggs", "match" : 100, "name" : "Eggs", @@ -100,7 +100,7 @@ { "debug" : "3 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-nuts.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-nuts.svg", "id" : "allergens_no_nuts", "match" : 100, "name" : "Nuts", @@ -110,7 +110,7 @@ { "debug" : "3 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-peanuts.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-peanuts.svg", "id" : "allergens_no_peanuts", "match" : 100, "name" : "Peanuts", @@ -120,7 +120,7 @@ { "debug" : "3 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-sesame-seeds.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-sesame-seeds.svg", "id" : "allergens_no_sesame_seeds", "match" : 100, "name" : "Sesame seeds", @@ -130,7 +130,7 @@ { "debug" : "3 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-soybeans.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-soybeans.svg", "id" : "allergens_no_soybeans", "match" : 100, "name" : "Soybeans", @@ -140,7 +140,7 @@ { "debug" : "3 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-celery.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-celery.svg", "id" : "allergens_no_celery", "match" : 100, "name" : "Celery", @@ -150,7 +150,7 @@ { "debug" : "3 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-mustard.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-mustard.svg", "id" : "allergens_no_mustard", "match" : 100, "name" : "Mustard", @@ -160,7 +160,7 @@ { "debug" : "3 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-lupin.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-lupin.svg", "id" : "allergens_no_lupin", "match" : 100, "name" : "Lupin", @@ -170,7 +170,7 @@ { "debug" : "3 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-fish.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-fish.svg", "id" : "allergens_no_fish", "match" : 100, "name" : "Fish", @@ -180,7 +180,7 @@ { "debug" : "3 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-crustaceans.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-crustaceans.svg", "id" : "allergens_no_crustaceans", "match" : 100, "name" : "Crustaceans", @@ -190,7 +190,7 @@ { "debug" : "3 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-molluscs.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-molluscs.svg", "id" : "allergens_no_molluscs", "match" : 100, "name" : "Molluscs", @@ -200,7 +200,7 @@ { "debug" : "3 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-sulphur-dioxide-and-sulphites.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-sulphur-dioxide-and-sulphites.svg", "id" : "allergens_no_sulphur_dioxide_and_sulphites", "match" : 100, "name" : "Sulphur dioxide and sulphites", @@ -216,7 +216,7 @@ "attributes" : [ { "grade" : "c", - "icon_url" : "https://server_domain/images/attributes/maybe-vegan.svg", + "icon_url" : "https://server_domain/images/attributes/dist/maybe-vegan.svg", "id" : "vegan", "match" : 50, "name" : "Vegan", @@ -226,7 +226,7 @@ }, { "grade" : "c", - "icon_url" : "https://server_domain/images/attributes/maybe-vegetarian.svg", + "icon_url" : "https://server_domain/images/attributes/dist/maybe-vegetarian.svg", "id" : "vegetarian", "match" : 50, "name" : "Vegetarian", @@ -236,7 +236,7 @@ }, { "grade" : "e", - "icon_url" : "https://server_domain/images/attributes/contains-palm-oil.svg", + "icon_url" : "https://server_domain/images/attributes/dist/contains-palm-oil.svg", "id" : "palm_oil_free", "match" : 0, "name" : "Palm oil free", @@ -254,7 +254,7 @@ "description" : "", "description_short" : "Processed foods", "grade" : "b", - "icon_url" : "https://server_domain/images/attributes/nova-group-3.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nova-group-3.svg", "id" : "nova", "match" : 75, "name" : "NOVA group", @@ -264,7 +264,7 @@ }, { "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/0-additives.svg", + "icon_url" : "https://server_domain/images/attributes/dist/0-additives.svg", "id" : "additives", "match" : 100, "name" : "Additives", @@ -282,7 +282,7 @@ "description" : "", "description_short" : "Unknown environmental impact", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/ecoscore-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/ecoscore-unknown.svg", "id" : "ecoscore", "match" : 0, "name" : "Eco-Score", @@ -294,7 +294,7 @@ "description" : "", "description_short" : "Currently only for products with chicken or eggs", "grade" : "e", - "icon_url" : "https://server_domain/images/attributes/forest-footprint-not-computed.svg", + "icon_url" : "https://server_domain/images/attributes/dist/forest-footprint-not-computed.svg", "id" : "forest_footprint", "match" : 0, "name" : "Forest footprint", @@ -311,7 +311,7 @@ "description" : "Organic farming aims to protect the environment and to conserve biodiversity by prohibiting or limiting the use of synthetic fertilizers, pesticides and food additives.", "description_short" : "Organic products promote ecological sustainability and biodiversity.", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/organic-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/organic-unknown.svg", "id" : "labels_organic", "name" : "Organic farming", "status" : "unknown", @@ -321,7 +321,7 @@ "description" : "When you buy fair trade products, producers in developing countries are paid an higher and fairer price, which helps them improve and sustain higher social and often environmental standards.", "description_short" : "Fair trade products help producers in developing countries.", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/fair-trade-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/fair-trade-unknown.svg", "id" : "labels_fair_trade", "name" : "Fair trade", "status" : "unknown", 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 1bbf8d98128cb..1a6ac972669bd 100644 --- a/tests/unit/expected_test_results/attributes/en-no-ingredients.json +++ b/tests/unit/expected_test_results/attributes/en-no-ingredients.json @@ -11,7 +11,7 @@ "description" : "", "description_short" : "Missing data to compute the Nutri-Score", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/nutriscore-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nutriscore-unknown.svg", "id" : "nutriscore", "match" : 0, "name" : "Nutri-Score", @@ -21,7 +21,7 @@ }, { "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/nutrient-level-salt-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nutrient-level-salt-unknown.svg", "id" : "low_salt", "missing" : "Missing nutrition facts", "name" : "Salt", @@ -30,7 +30,7 @@ }, { "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/nutrient-level-fat-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nutrient-level-fat-unknown.svg", "id" : "low_fat", "missing" : "Missing nutrition facts", "name" : "Fat", @@ -39,7 +39,7 @@ }, { "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/nutrient-level-sugars-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nutrient-level-sugars-unknown.svg", "id" : "low_sugars", "missing" : "Missing nutrition facts", "name" : "Sugars", @@ -48,7 +48,7 @@ }, { "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/nutrient-level-saturated-fat-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nutrient-level-saturated-fat-unknown.svg", "id" : "low_saturated_fat", "missing" : "Missing nutrition facts", "name" : "Saturated fat", @@ -64,7 +64,7 @@ { "debug" : "missing ingredients list", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/gluten-content-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/gluten-content-unknown.svg", "id" : "allergens_no_gluten", "name" : "Gluten", "panel_id" : "ingredients", @@ -74,7 +74,7 @@ { "debug" : "missing ingredients list", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/milk-content-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/milk-content-unknown.svg", "id" : "allergens_no_milk", "name" : "Milk", "panel_id" : "ingredients", @@ -84,7 +84,7 @@ { "debug" : "missing ingredients list", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/eggs-content-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/eggs-content-unknown.svg", "id" : "allergens_no_eggs", "name" : "Eggs", "panel_id" : "ingredients", @@ -94,7 +94,7 @@ { "debug" : "missing ingredients list", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/nuts-content-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nuts-content-unknown.svg", "id" : "allergens_no_nuts", "name" : "Nuts", "panel_id" : "ingredients", @@ -104,7 +104,7 @@ { "debug" : "missing ingredients list", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/peanuts-content-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/peanuts-content-unknown.svg", "id" : "allergens_no_peanuts", "name" : "Peanuts", "panel_id" : "ingredients", @@ -114,7 +114,7 @@ { "debug" : "missing ingredients list", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/sesame-seeds-content-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/sesame-seeds-content-unknown.svg", "id" : "allergens_no_sesame_seeds", "name" : "Sesame seeds", "panel_id" : "ingredients", @@ -124,7 +124,7 @@ { "debug" : "missing ingredients list", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/soybeans-content-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/soybeans-content-unknown.svg", "id" : "allergens_no_soybeans", "name" : "Soybeans", "panel_id" : "ingredients", @@ -134,7 +134,7 @@ { "debug" : "missing ingredients list", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/celery-content-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/celery-content-unknown.svg", "id" : "allergens_no_celery", "name" : "Celery", "panel_id" : "ingredients", @@ -144,7 +144,7 @@ { "debug" : "missing ingredients list", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/mustard-content-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/mustard-content-unknown.svg", "id" : "allergens_no_mustard", "name" : "Mustard", "panel_id" : "ingredients", @@ -154,7 +154,7 @@ { "debug" : "missing ingredients list", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/lupin-content-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/lupin-content-unknown.svg", "id" : "allergens_no_lupin", "name" : "Lupin", "panel_id" : "ingredients", @@ -164,7 +164,7 @@ { "debug" : "missing ingredients list", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/fish-content-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/fish-content-unknown.svg", "id" : "allergens_no_fish", "name" : "Fish", "panel_id" : "ingredients", @@ -174,7 +174,7 @@ { "debug" : "missing ingredients list", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/crustaceans-content-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/crustaceans-content-unknown.svg", "id" : "allergens_no_crustaceans", "name" : "Crustaceans", "panel_id" : "ingredients", @@ -184,7 +184,7 @@ { "debug" : "missing ingredients list", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/molluscs-content-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/molluscs-content-unknown.svg", "id" : "allergens_no_molluscs", "name" : "Molluscs", "panel_id" : "ingredients", @@ -194,7 +194,7 @@ { "debug" : "missing ingredients list", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/sulphur-dioxide-and-sulphites-content-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/sulphur-dioxide-and-sulphites-content-unknown.svg", "id" : "allergens_no_sulphur_dioxide_and_sulphites", "name" : "Sulphur dioxide and sulphites", "panel_id" : "ingredients", @@ -210,7 +210,7 @@ "attributes" : [ { "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/vegan-status-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/vegan-status-unknown.svg", "id" : "vegan", "name" : "Vegan", "panel_id" : "ingredients", @@ -219,7 +219,7 @@ }, { "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/vegetarian-status-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/vegetarian-status-unknown.svg", "id" : "vegetarian", "name" : "Vegetarian", "panel_id" : "ingredients", @@ -228,7 +228,7 @@ }, { "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/palm-oil-content-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/palm-oil-content-unknown.svg", "id" : "palm_oil_free", "name" : "Palm oil free", "panel_id" : "ingredients", @@ -245,7 +245,7 @@ "description" : "", "description_short" : "Food processing level unknown", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/nova-group-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nova-group-unknown.svg", "id" : "nova", "match" : 0, "name" : "NOVA group", @@ -257,7 +257,7 @@ "description" : "", "description_short" : "", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/additives-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/additives-unknown.svg", "id" : "additives", "match" : 0, "missing" : "Missing ingredients list", @@ -276,7 +276,7 @@ "description" : "", "description_short" : "High environmental impact", "grade" : "d", - "icon_url" : "https://server_domain/images/attributes/ecoscore-d.svg", + "icon_url" : "https://server_domain/images/attributes/dist/ecoscore-d.svg", "id" : "ecoscore", "match" : 35, "name" : "Eco-Score", @@ -288,7 +288,7 @@ "description" : "", "description_short" : "Currently only for products with chicken or eggs", "grade" : "e", - "icon_url" : "https://server_domain/images/attributes/forest-footprint-not-computed.svg", + "icon_url" : "https://server_domain/images/attributes/dist/forest-footprint-not-computed.svg", "id" : "forest_footprint", "match" : 0, "name" : "Forest footprint", @@ -305,7 +305,7 @@ "description" : "Organic farming aims to protect the environment and to conserve biodiversity by prohibiting or limiting the use of synthetic fertilizers, pesticides and food additives.", "description_short" : "Organic products promote ecological sustainability and biodiversity.", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/organic-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/organic-unknown.svg", "id" : "labels_organic", "name" : "Organic farming", "status" : "unknown", @@ -315,7 +315,7 @@ "description" : "When you buy fair trade products, producers in developing countries are paid an higher and fairer price, which helps them improve and sustain higher social and often environmental standards.", "description_short" : "Fair trade products help producers in developing countries.", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/fair-trade-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/fair-trade-unknown.svg", "id" : "labels_fair_trade", "name" : "Fair trade", "status" : "unknown", 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 be18158c9cb87..308130a766589 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 @@ -27,7 +27,7 @@ "description" : "", "description_short" : "Missing data to compute the Nutri-Score", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/nutriscore-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nutriscore-unknown.svg", "id" : "nutriscore", "match" : 0, "name" : "Nutri-Score", @@ -37,7 +37,7 @@ }, { "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/nutrient-level-salt-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nutrient-level-salt-unknown.svg", "id" : "low_salt", "missing" : "Missing nutrition facts", "name" : "Salt", @@ -46,7 +46,7 @@ }, { "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/nutrient-level-fat-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nutrient-level-fat-unknown.svg", "id" : "low_fat", "missing" : "Missing nutrition facts", "name" : "Fat", @@ -55,7 +55,7 @@ }, { "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/nutrient-level-sugars-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nutrient-level-sugars-unknown.svg", "id" : "low_sugars", "missing" : "Missing nutrition facts", "name" : "Sugars", @@ -64,7 +64,7 @@ }, { "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/nutrient-level-saturated-fat-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nutrient-level-saturated-fat-unknown.svg", "id" : "low_saturated_fat", "missing" : "Missing nutrition facts", "name" : "Saturated fat", @@ -80,7 +80,7 @@ { "debug" : "7 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-gluten.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-gluten.svg", "id" : "allergens_no_gluten", "match" : 100, "name" : "Gluten", @@ -90,7 +90,7 @@ { "debug" : "en:milk in allergens", "grade" : "e", - "icon_url" : "https://server_domain/images/attributes/contains-milk.svg", + "icon_url" : "https://server_domain/images/attributes/dist/contains-milk.svg", "id" : "allergens_no_milk", "match" : 0, "name" : "Milk", @@ -100,7 +100,7 @@ { "debug" : "7 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-eggs.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-eggs.svg", "id" : "allergens_no_eggs", "match" : 100, "name" : "Eggs", @@ -110,7 +110,7 @@ { "debug" : "7 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-nuts.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-nuts.svg", "id" : "allergens_no_nuts", "match" : 100, "name" : "Nuts", @@ -120,7 +120,7 @@ { "debug" : "7 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-peanuts.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-peanuts.svg", "id" : "allergens_no_peanuts", "match" : 100, "name" : "Peanuts", @@ -130,7 +130,7 @@ { "debug" : "7 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-sesame-seeds.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-sesame-seeds.svg", "id" : "allergens_no_sesame_seeds", "match" : 100, "name" : "Sesame seeds", @@ -140,7 +140,7 @@ { "debug" : "7 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-soybeans.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-soybeans.svg", "id" : "allergens_no_soybeans", "match" : 100, "name" : "Soybeans", @@ -150,7 +150,7 @@ { "debug" : "7 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-celery.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-celery.svg", "id" : "allergens_no_celery", "match" : 100, "name" : "Celery", @@ -160,7 +160,7 @@ { "debug" : "7 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-mustard.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-mustard.svg", "id" : "allergens_no_mustard", "match" : 100, "name" : "Mustard", @@ -170,7 +170,7 @@ { "debug" : "7 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-lupin.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-lupin.svg", "id" : "allergens_no_lupin", "match" : 100, "name" : "Lupin", @@ -180,7 +180,7 @@ { "debug" : "7 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-fish.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-fish.svg", "id" : "allergens_no_fish", "match" : 100, "name" : "Fish", @@ -190,7 +190,7 @@ { "debug" : "7 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-crustaceans.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-crustaceans.svg", "id" : "allergens_no_crustaceans", "match" : 100, "name" : "Crustaceans", @@ -200,7 +200,7 @@ { "debug" : "7 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-molluscs.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-molluscs.svg", "id" : "allergens_no_molluscs", "match" : 100, "name" : "Molluscs", @@ -210,7 +210,7 @@ { "debug" : "7 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-sulphur-dioxide-and-sulphites.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-sulphur-dioxide-and-sulphites.svg", "id" : "allergens_no_sulphur_dioxide_and_sulphites", "match" : 100, "name" : "Sulphur dioxide and sulphites", @@ -226,7 +226,7 @@ "attributes" : [ { "grade" : "e", - "icon_url" : "https://server_domain/images/attributes/non-vegan.svg", + "icon_url" : "https://server_domain/images/attributes/dist/non-vegan.svg", "id" : "vegan", "match" : 0, "name" : "Vegan", @@ -236,7 +236,7 @@ }, { "grade" : "c", - "icon_url" : "https://server_domain/images/attributes/maybe-vegetarian.svg", + "icon_url" : "https://server_domain/images/attributes/dist/maybe-vegetarian.svg", "id" : "vegetarian", "match" : 50, "name" : "Vegetarian", @@ -246,7 +246,7 @@ }, { "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/palm-oil-free.svg", + "icon_url" : "https://server_domain/images/attributes/dist/palm-oil-free.svg", "id" : "palm_oil_free", "match" : 100, "name" : "Palm oil free", @@ -264,7 +264,7 @@ "description" : "", "description_short" : "Ultra processed foods", "grade" : "e", - "icon_url" : "https://server_domain/images/attributes/nova-group-4.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nova-group-4.svg", "id" : "nova", "match" : 0, "name" : "NOVA group", @@ -274,7 +274,7 @@ }, { "grade" : "b", - "icon_url" : "https://server_domain/images/attributes/1-additives.svg", + "icon_url" : "https://server_domain/images/attributes/dist/1-additives.svg", "id" : "additives", "match" : 80, "name" : "Additives", @@ -292,7 +292,7 @@ "description" : "", "description_short" : "High environmental impact", "grade" : "d", - "icon_url" : "https://server_domain/images/attributes/ecoscore-d.svg", + "icon_url" : "https://server_domain/images/attributes/dist/ecoscore-d.svg", "id" : "ecoscore", "match" : 35, "name" : "Eco-Score", @@ -304,7 +304,7 @@ "description" : "", "description_short" : "Currently only for products with chicken or eggs", "grade" : "e", - "icon_url" : "https://server_domain/images/attributes/forest-footprint-not-computed.svg", + "icon_url" : "https://server_domain/images/attributes/dist/forest-footprint-not-computed.svg", "id" : "forest_footprint", "match" : 0, "name" : "Forest footprint", @@ -321,7 +321,7 @@ "description" : "Organic farming aims to protect the environment and to conserve biodiversity by prohibiting or limiting the use of synthetic fertilizers, pesticides and food additives.", "description_short" : "Organic products promote ecological sustainability and biodiversity.", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/organic-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/organic-unknown.svg", "id" : "labels_organic", "name" : "Organic farming", "status" : "unknown", @@ -331,7 +331,7 @@ "description" : "When you buy fair trade products, producers in developing countries are paid an higher and fairer price, which helps them improve and sustain higher social and often environmental standards.", "description_short" : "Fair trade products help producers in developing countries.", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/fair-trade-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/fair-trade-unknown.svg", "id" : "labels_fair_trade", "name" : "Fair trade", "status" : "unknown", diff --git a/tests/unit/expected_test_results/attributes/en-nutriscore.json b/tests/unit/expected_test_results/attributes/en-nutriscore.json index 121316337a853..a93fde76279d9 100644 --- a/tests/unit/expected_test_results/attributes/en-nutriscore.json +++ b/tests/unit/expected_test_results/attributes/en-nutriscore.json @@ -17,7 +17,7 @@ "description" : "", "description_short" : "Good nutritional quality", "grade" : "b", - "icon_url" : "https://server_domain/images/attributes/nutriscore-b.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nutriscore-b.svg", "id" : "nutriscore", "match" : 61, "name" : "Nutri-Score", @@ -28,7 +28,7 @@ { "description_short" : "0 g / 100 g", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/nutrient-level-salt-low.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nutrient-level-salt-low.svg", "id" : "low_salt", "match" : 100, "name" : "Salt", @@ -38,7 +38,7 @@ { "description_short" : "50 g / 100 g", "grade" : "e", - "icon_url" : "https://server_domain/images/attributes/nutrient-level-fat-high.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nutrient-level-fat-high.svg", "id" : "low_fat", "match" : 0, "name" : "Fat", @@ -48,7 +48,7 @@ { "description_short" : "5.1 g / 100 g", "grade" : "b", - "icon_url" : "https://server_domain/images/attributes/nutrient-level-sugars-medium.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nutrient-level-sugars-medium.svg", "id" : "low_sugars", "match" : 79.2, "name" : "Sugars", @@ -58,7 +58,7 @@ { "description_short" : "9.7 g / 100 g", "grade" : "e", - "icon_url" : "https://server_domain/images/attributes/nutrient-level-saturated-fat-high.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nutrient-level-saturated-fat-high.svg", "id" : "low_saturated_fat", "match" : 1.2, "name" : "Saturated fat", @@ -74,7 +74,7 @@ { "debug" : "1 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-gluten.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-gluten.svg", "id" : "allergens_no_gluten", "match" : 100, "name" : "Gluten", @@ -84,7 +84,7 @@ { "debug" : "1 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-milk.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-milk.svg", "id" : "allergens_no_milk", "match" : 100, "name" : "Milk", @@ -94,7 +94,7 @@ { "debug" : "1 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-eggs.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-eggs.svg", "id" : "allergens_no_eggs", "match" : 100, "name" : "Eggs", @@ -104,7 +104,7 @@ { "debug" : "1 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-nuts.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-nuts.svg", "id" : "allergens_no_nuts", "match" : 100, "name" : "Nuts", @@ -114,7 +114,7 @@ { "debug" : "1 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-peanuts.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-peanuts.svg", "id" : "allergens_no_peanuts", "match" : 100, "name" : "Peanuts", @@ -124,7 +124,7 @@ { "debug" : "1 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-sesame-seeds.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-sesame-seeds.svg", "id" : "allergens_no_sesame_seeds", "match" : 100, "name" : "Sesame seeds", @@ -134,7 +134,7 @@ { "debug" : "1 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-soybeans.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-soybeans.svg", "id" : "allergens_no_soybeans", "match" : 100, "name" : "Soybeans", @@ -144,7 +144,7 @@ { "debug" : "1 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-celery.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-celery.svg", "id" : "allergens_no_celery", "match" : 100, "name" : "Celery", @@ -154,7 +154,7 @@ { "debug" : "1 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-mustard.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-mustard.svg", "id" : "allergens_no_mustard", "match" : 100, "name" : "Mustard", @@ -164,7 +164,7 @@ { "debug" : "1 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-lupin.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-lupin.svg", "id" : "allergens_no_lupin", "match" : 100, "name" : "Lupin", @@ -174,7 +174,7 @@ { "debug" : "1 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-fish.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-fish.svg", "id" : "allergens_no_fish", "match" : 100, "name" : "Fish", @@ -184,7 +184,7 @@ { "debug" : "1 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-crustaceans.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-crustaceans.svg", "id" : "allergens_no_crustaceans", "match" : 100, "name" : "Crustaceans", @@ -194,7 +194,7 @@ { "debug" : "1 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-molluscs.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-molluscs.svg", "id" : "allergens_no_molluscs", "match" : 100, "name" : "Molluscs", @@ -204,7 +204,7 @@ { "debug" : "1 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-sulphur-dioxide-and-sulphites.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-sulphur-dioxide-and-sulphites.svg", "id" : "allergens_no_sulphur_dioxide_and_sulphites", "match" : 100, "name" : "Sulphur dioxide and sulphites", @@ -220,7 +220,7 @@ "attributes" : [ { "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/vegan.svg", + "icon_url" : "https://server_domain/images/attributes/dist/vegan.svg", "id" : "vegan", "match" : 100, "name" : "Vegan", @@ -230,7 +230,7 @@ }, { "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/vegetarian.svg", + "icon_url" : "https://server_domain/images/attributes/dist/vegetarian.svg", "id" : "vegetarian", "match" : 100, "name" : "Vegetarian", @@ -240,7 +240,7 @@ }, { "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/palm-oil-free.svg", + "icon_url" : "https://server_domain/images/attributes/dist/palm-oil-free.svg", "id" : "palm_oil_free", "match" : 100, "name" : "Palm oil free", @@ -258,7 +258,7 @@ "description" : "", "description_short" : "Unprocessed or minimally processed foods", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/nova-group-1.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nova-group-1.svg", "id" : "nova", "match" : 100, "name" : "NOVA group", @@ -268,7 +268,7 @@ }, { "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/0-additives.svg", + "icon_url" : "https://server_domain/images/attributes/dist/0-additives.svg", "id" : "additives", "match" : 100, "name" : "Additives", @@ -286,7 +286,7 @@ "description" : "", "description_short" : "Moderate environmental impact", "grade" : "c", - "icon_url" : "https://server_domain/images/attributes/ecoscore-c.svg", + "icon_url" : "https://server_domain/images/attributes/dist/ecoscore-c.svg", "id" : "ecoscore", "match" : 50, "name" : "Eco-Score", @@ -298,7 +298,7 @@ "description" : "", "description_short" : "Currently only for products with chicken or eggs", "grade" : "e", - "icon_url" : "https://server_domain/images/attributes/forest-footprint-not-computed.svg", + "icon_url" : "https://server_domain/images/attributes/dist/forest-footprint-not-computed.svg", "id" : "forest_footprint", "match" : 0, "name" : "Forest footprint", @@ -315,7 +315,7 @@ "description" : "Organic farming aims to protect the environment and to conserve biodiversity by prohibiting or limiting the use of synthetic fertilizers, pesticides and food additives.", "description_short" : "Organic products promote ecological sustainability and biodiversity.", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/organic-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/organic-unknown.svg", "id" : "labels_organic", "name" : "Organic farming", "status" : "unknown", @@ -325,7 +325,7 @@ "description" : "When you buy fair trade products, producers in developing countries are paid an higher and fairer price, which helps them improve and sustain higher social and often environmental standards.", "description_short" : "Fair trade products help producers in developing countries.", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/fair-trade-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/fair-trade-unknown.svg", "id" : "labels_fair_trade", "name" : "Fair trade", "status" : "unknown", 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 d68645eb7d349..366fe5f9f88d4 100644 --- a/tests/unit/expected_test_results/attributes/en-unknown-ingredients.json +++ b/tests/unit/expected_test_results/attributes/en-unknown-ingredients.json @@ -17,7 +17,7 @@ "description" : "", "description_short" : "Missing data to compute the Nutri-Score", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/nutriscore-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nutriscore-unknown.svg", "id" : "nutriscore", "match" : 0, "name" : "Nutri-Score", @@ -27,7 +27,7 @@ }, { "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/nutrient-level-salt-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nutrient-level-salt-unknown.svg", "id" : "low_salt", "missing" : "Missing nutrition facts", "name" : "Salt", @@ -36,7 +36,7 @@ }, { "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/nutrient-level-fat-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nutrient-level-fat-unknown.svg", "id" : "low_fat", "missing" : "Missing nutrition facts", "name" : "Fat", @@ -45,7 +45,7 @@ }, { "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/nutrient-level-sugars-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nutrient-level-sugars-unknown.svg", "id" : "low_sugars", "missing" : "Missing nutrition facts", "name" : "Sugars", @@ -54,7 +54,7 @@ }, { "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/nutrient-level-saturated-fat-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nutrient-level-saturated-fat-unknown.svg", "id" : "low_saturated_fat", "missing" : "Missing nutrition facts", "name" : "Saturated fat", @@ -70,7 +70,7 @@ { "debug" : "too many unknown ingredients: 1 ingredients (1 unknown)", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/gluten-content-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/gluten-content-unknown.svg", "id" : "allergens_no_gluten", "name" : "Gluten", "panel_id" : "ingredients_analysis_details", @@ -80,7 +80,7 @@ { "debug" : "too many unknown ingredients: 1 ingredients (1 unknown)", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/milk-content-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/milk-content-unknown.svg", "id" : "allergens_no_milk", "name" : "Milk", "panel_id" : "ingredients_analysis_details", @@ -90,7 +90,7 @@ { "debug" : "too many unknown ingredients: 1 ingredients (1 unknown)", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/eggs-content-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/eggs-content-unknown.svg", "id" : "allergens_no_eggs", "name" : "Eggs", "panel_id" : "ingredients_analysis_details", @@ -100,7 +100,7 @@ { "debug" : "too many unknown ingredients: 1 ingredients (1 unknown)", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/nuts-content-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nuts-content-unknown.svg", "id" : "allergens_no_nuts", "name" : "Nuts", "panel_id" : "ingredients_analysis_details", @@ -110,7 +110,7 @@ { "debug" : "too many unknown ingredients: 1 ingredients (1 unknown)", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/peanuts-content-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/peanuts-content-unknown.svg", "id" : "allergens_no_peanuts", "name" : "Peanuts", "panel_id" : "ingredients_analysis_details", @@ -120,7 +120,7 @@ { "debug" : "too many unknown ingredients: 1 ingredients (1 unknown)", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/sesame-seeds-content-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/sesame-seeds-content-unknown.svg", "id" : "allergens_no_sesame_seeds", "name" : "Sesame seeds", "panel_id" : "ingredients_analysis_details", @@ -130,7 +130,7 @@ { "debug" : "too many unknown ingredients: 1 ingredients (1 unknown)", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/soybeans-content-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/soybeans-content-unknown.svg", "id" : "allergens_no_soybeans", "name" : "Soybeans", "panel_id" : "ingredients_analysis_details", @@ -140,7 +140,7 @@ { "debug" : "too many unknown ingredients: 1 ingredients (1 unknown)", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/celery-content-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/celery-content-unknown.svg", "id" : "allergens_no_celery", "name" : "Celery", "panel_id" : "ingredients_analysis_details", @@ -150,7 +150,7 @@ { "debug" : "too many unknown ingredients: 1 ingredients (1 unknown)", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/mustard-content-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/mustard-content-unknown.svg", "id" : "allergens_no_mustard", "name" : "Mustard", "panel_id" : "ingredients_analysis_details", @@ -160,7 +160,7 @@ { "debug" : "too many unknown ingredients: 1 ingredients (1 unknown)", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/lupin-content-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/lupin-content-unknown.svg", "id" : "allergens_no_lupin", "name" : "Lupin", "panel_id" : "ingredients_analysis_details", @@ -170,7 +170,7 @@ { "debug" : "too many unknown ingredients: 1 ingredients (1 unknown)", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/fish-content-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/fish-content-unknown.svg", "id" : "allergens_no_fish", "name" : "Fish", "panel_id" : "ingredients_analysis_details", @@ -180,7 +180,7 @@ { "debug" : "too many unknown ingredients: 1 ingredients (1 unknown)", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/crustaceans-content-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/crustaceans-content-unknown.svg", "id" : "allergens_no_crustaceans", "name" : "Crustaceans", "panel_id" : "ingredients_analysis_details", @@ -190,7 +190,7 @@ { "debug" : "too many unknown ingredients: 1 ingredients (1 unknown)", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/molluscs-content-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/molluscs-content-unknown.svg", "id" : "allergens_no_molluscs", "name" : "Molluscs", "panel_id" : "ingredients_analysis_details", @@ -200,7 +200,7 @@ { "debug" : "too many unknown ingredients: 1 ingredients (1 unknown)", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/sulphur-dioxide-and-sulphites-content-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/sulphur-dioxide-and-sulphites-content-unknown.svg", "id" : "allergens_no_sulphur_dioxide_and_sulphites", "name" : "Sulphur dioxide and sulphites", "panel_id" : "ingredients_analysis_details", @@ -216,7 +216,7 @@ "attributes" : [ { "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/vegan-status-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/vegan-status-unknown.svg", "id" : "vegan", "name" : "Vegan", "panel_id" : "ingredients_analysis_en:vegan-status-unknown", @@ -225,7 +225,7 @@ }, { "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/vegetarian-status-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/vegetarian-status-unknown.svg", "id" : "vegetarian", "name" : "Vegetarian", "panel_id" : "ingredients_analysis_en:vegetarian-status-unknown", @@ -234,7 +234,7 @@ }, { "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/palm-oil-content-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/palm-oil-content-unknown.svg", "id" : "palm_oil_free", "name" : "Palm oil free", "panel_id" : "ingredients_analysis_en:palm-oil-content-unknown", @@ -251,7 +251,7 @@ "description" : "", "description_short" : "Food processing level unknown", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/nova-group-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nova-group-unknown.svg", "id" : "nova", "match" : 0, "name" : "NOVA group", @@ -261,7 +261,7 @@ }, { "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/0-additives.svg", + "icon_url" : "https://server_domain/images/attributes/dist/0-additives.svg", "id" : "additives", "match" : 100, "name" : "Additives", @@ -279,7 +279,7 @@ "description" : "", "description_short" : "High environmental impact", "grade" : "d", - "icon_url" : "https://server_domain/images/attributes/ecoscore-d.svg", + "icon_url" : "https://server_domain/images/attributes/dist/ecoscore-d.svg", "id" : "ecoscore", "match" : 35, "name" : "Eco-Score", @@ -291,7 +291,7 @@ "description" : "", "description_short" : "Currently only for products with chicken or eggs", "grade" : "e", - "icon_url" : "https://server_domain/images/attributes/forest-footprint-not-computed.svg", + "icon_url" : "https://server_domain/images/attributes/dist/forest-footprint-not-computed.svg", "id" : "forest_footprint", "match" : 0, "name" : "Forest footprint", @@ -308,7 +308,7 @@ "description" : "Organic farming aims to protect the environment and to conserve biodiversity by prohibiting or limiting the use of synthetic fertilizers, pesticides and food additives.", "description_short" : "Organic products promote ecological sustainability and biodiversity.", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/organic-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/organic-unknown.svg", "id" : "labels_organic", "name" : "Organic farming", "status" : "unknown", @@ -318,7 +318,7 @@ "description" : "When you buy fair trade products, producers in developing countries are paid an higher and fairer price, which helps them improve and sustain higher social and often environmental standards.", "description_short" : "Fair trade products help producers in developing countries.", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/fair-trade-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/fair-trade-unknown.svg", "id" : "labels_fair_trade", "name" : "Fair trade", "status" : "unknown", 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 74d6a6183b57f..7f1043b98cff2 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 @@ -17,7 +17,7 @@ "description" : "", "description_short" : "Données manquantes pour calculer le Nutri-Score", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/nutriscore-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nutriscore-unknown.svg", "id" : "nutriscore", "match" : 0, "name" : "Nutri-Score", @@ -27,7 +27,7 @@ }, { "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/nutrient-level-salt-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nutrient-level-salt-unknown.svg", "id" : "low_salt", "missing" : "Données nutritionnelles manquantes", "name" : "Sel", @@ -36,7 +36,7 @@ }, { "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/nutrient-level-fat-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nutrient-level-fat-unknown.svg", "id" : "low_fat", "missing" : "Données nutritionnelles manquantes", "name" : "Matières grasses", @@ -45,7 +45,7 @@ }, { "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/nutrient-level-sugars-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nutrient-level-sugars-unknown.svg", "id" : "low_sugars", "missing" : "Données nutritionnelles manquantes", "name" : "Sucres", @@ -54,7 +54,7 @@ }, { "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/nutrient-level-saturated-fat-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nutrient-level-saturated-fat-unknown.svg", "id" : "low_saturated_fat", "missing" : "Données nutritionnelles manquantes", "name" : "Acides gras saturés", @@ -70,7 +70,7 @@ { "debug" : "1 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-gluten.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-gluten.svg", "id" : "allergens_no_gluten", "match" : 100, "name" : "Gluten", @@ -80,7 +80,7 @@ { "debug" : "1 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-milk.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-milk.svg", "id" : "allergens_no_milk", "match" : 100, "name" : "Lait", @@ -90,7 +90,7 @@ { "debug" : "1 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-eggs.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-eggs.svg", "id" : "allergens_no_eggs", "match" : 100, "name" : "Œufs", @@ -100,7 +100,7 @@ { "debug" : "1 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-nuts.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-nuts.svg", "id" : "allergens_no_nuts", "match" : 100, "name" : "Fruits à coque", @@ -110,7 +110,7 @@ { "debug" : "1 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-peanuts.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-peanuts.svg", "id" : "allergens_no_peanuts", "match" : 100, "name" : "Arachides", @@ -120,7 +120,7 @@ { "debug" : "1 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-sesame-seeds.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-sesame-seeds.svg", "id" : "allergens_no_sesame_seeds", "match" : 100, "name" : "Graines de sésame", @@ -130,7 +130,7 @@ { "debug" : "1 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-soybeans.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-soybeans.svg", "id" : "allergens_no_soybeans", "match" : 100, "name" : "Soja", @@ -140,7 +140,7 @@ { "debug" : "1 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-celery.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-celery.svg", "id" : "allergens_no_celery", "match" : 100, "name" : "Céleri", @@ -150,7 +150,7 @@ { "debug" : "1 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-mustard.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-mustard.svg", "id" : "allergens_no_mustard", "match" : 100, "name" : "Moutarde", @@ -160,7 +160,7 @@ { "debug" : "1 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-lupin.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-lupin.svg", "id" : "allergens_no_lupin", "match" : 100, "name" : "Lupin", @@ -170,7 +170,7 @@ { "debug" : "1 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-fish.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-fish.svg", "id" : "allergens_no_fish", "match" : 100, "name" : "Poisson", @@ -180,7 +180,7 @@ { "debug" : "1 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-crustaceans.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-crustaceans.svg", "id" : "allergens_no_crustaceans", "match" : 100, "name" : "Crustacés", @@ -190,7 +190,7 @@ { "debug" : "1 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-molluscs.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-molluscs.svg", "id" : "allergens_no_molluscs", "match" : 100, "name" : "Mollusques", @@ -200,7 +200,7 @@ { "debug" : "1 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-sulphur-dioxide-and-sulphites.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-sulphur-dioxide-and-sulphites.svg", "id" : "allergens_no_sulphur_dioxide_and_sulphites", "match" : 100, "name" : "Anhydride sulfureux et sulfites", @@ -216,7 +216,7 @@ "attributes" : [ { "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/vegan.svg", + "icon_url" : "https://server_domain/images/attributes/dist/vegan.svg", "id" : "vegan", "match" : 100, "name" : "Végétalien", @@ -226,7 +226,7 @@ }, { "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/vegetarian.svg", + "icon_url" : "https://server_domain/images/attributes/dist/vegetarian.svg", "id" : "vegetarian", "match" : 100, "name" : "Végétarien", @@ -236,7 +236,7 @@ }, { "grade" : "e", - "icon_url" : "https://server_domain/images/attributes/contains-palm-oil.svg", + "icon_url" : "https://server_domain/images/attributes/dist/contains-palm-oil.svg", "id" : "palm_oil_free", "match" : 0, "name" : "Sans huile de palme", @@ -254,7 +254,7 @@ "description" : "", "description_short" : "Degré de transformation des aliments inconnu", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/nova-group-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nova-group-unknown.svg", "id" : "nova", "match" : 0, "name" : "Groupe NOVA", @@ -264,7 +264,7 @@ }, { "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/0-additives.svg", + "icon_url" : "https://server_domain/images/attributes/dist/0-additives.svg", "id" : "additives", "match" : 100, "name" : "Additifs", @@ -282,7 +282,7 @@ "description" : "", "description_short" : "Impact environnemental inconnu", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/ecoscore-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/ecoscore-unknown.svg", "id" : "ecoscore", "match" : 0, "name" : "Eco-Score", @@ -294,7 +294,7 @@ "description" : "", "description_short" : "Pour l'instant seulement pour les produits avec du poulet ou des oeufs", "grade" : "e", - "icon_url" : "https://server_domain/images/attributes/forest-footprint-not-computed.svg", + "icon_url" : "https://server_domain/images/attributes/dist/forest-footprint-not-computed.svg", "id" : "forest_footprint", "match" : 0, "name" : "Empreinte forêt", @@ -311,7 +311,7 @@ "description" : "L'agriculture biologique vise à protéger l'environnement et à conserver la biodiversité en prohibant ou limitant l'utilisation d'engrais synthétiques, de pesticides et d'additifs alimentaires.", "description_short" : "Les produits bios encouragent la durabilité écologique et la biodiversité.", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/organic-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/organic-unknown.svg", "id" : "labels_organic", "name" : "Agriculture biologique", "status" : "unknown", @@ -321,7 +321,7 @@ "description" : "Quand vous achetez des produits du commerce équitable, les producteurs dans les pays en développement sont payés un prix plus haut et plus équitable, ce qui les aide à atteindre des plus hauts standards sociaux et environnementaux et à les conserver.", "description_short" : "Les produits du commerce équitable aident les producteurs des pays en voie de développement.", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/fair-trade-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/fair-trade-unknown.svg", "id" : "labels_fair_trade", "name" : "Commerce équitable", "status" : "unknown", 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 f31bf7733f010..d64e60136460a 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 @@ -17,7 +17,7 @@ "description" : "", "description_short" : "Données manquantes pour calculer le Nutri-Score", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/nutriscore-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nutriscore-unknown.svg", "id" : "nutriscore", "match" : 0, "name" : "Nutri-Score", @@ -27,7 +27,7 @@ }, { "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/nutrient-level-salt-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nutrient-level-salt-unknown.svg", "id" : "low_salt", "missing" : "Données nutritionnelles manquantes", "name" : "Sel", @@ -36,7 +36,7 @@ }, { "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/nutrient-level-fat-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nutrient-level-fat-unknown.svg", "id" : "low_fat", "missing" : "Données nutritionnelles manquantes", "name" : "Matières grasses", @@ -45,7 +45,7 @@ }, { "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/nutrient-level-sugars-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nutrient-level-sugars-unknown.svg", "id" : "low_sugars", "missing" : "Données nutritionnelles manquantes", "name" : "Sucres", @@ -54,7 +54,7 @@ }, { "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/nutrient-level-saturated-fat-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nutrient-level-saturated-fat-unknown.svg", "id" : "low_saturated_fat", "missing" : "Données nutritionnelles manquantes", "name" : "Acides gras saturés", @@ -70,7 +70,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-gluten.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-gluten.svg", "id" : "allergens_no_gluten", "match" : 100, "name" : "Gluten", @@ -80,7 +80,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-milk.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-milk.svg", "id" : "allergens_no_milk", "match" : 100, "name" : "Lait", @@ -90,7 +90,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-eggs.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-eggs.svg", "id" : "allergens_no_eggs", "match" : 100, "name" : "Œufs", @@ -100,7 +100,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-nuts.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-nuts.svg", "id" : "allergens_no_nuts", "match" : 100, "name" : "Fruits à coque", @@ -110,7 +110,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-peanuts.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-peanuts.svg", "id" : "allergens_no_peanuts", "match" : 100, "name" : "Arachides", @@ -120,7 +120,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-sesame-seeds.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-sesame-seeds.svg", "id" : "allergens_no_sesame_seeds", "match" : 100, "name" : "Graines de sésame", @@ -130,7 +130,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-soybeans.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-soybeans.svg", "id" : "allergens_no_soybeans", "match" : 100, "name" : "Soja", @@ -140,7 +140,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-celery.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-celery.svg", "id" : "allergens_no_celery", "match" : 100, "name" : "Céleri", @@ -150,7 +150,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-mustard.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-mustard.svg", "id" : "allergens_no_mustard", "match" : 100, "name" : "Moutarde", @@ -160,7 +160,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-lupin.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-lupin.svg", "id" : "allergens_no_lupin", "match" : 100, "name" : "Lupin", @@ -170,7 +170,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-fish.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-fish.svg", "id" : "allergens_no_fish", "match" : 100, "name" : "Poisson", @@ -180,7 +180,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-crustaceans.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-crustaceans.svg", "id" : "allergens_no_crustaceans", "match" : 100, "name" : "Crustacés", @@ -190,7 +190,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-molluscs.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-molluscs.svg", "id" : "allergens_no_molluscs", "match" : 100, "name" : "Mollusques", @@ -200,7 +200,7 @@ { "debug" : "4 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-sulphur-dioxide-and-sulphites.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-sulphur-dioxide-and-sulphites.svg", "id" : "allergens_no_sulphur_dioxide_and_sulphites", "match" : 100, "name" : "Anhydride sulfureux et sulfites", @@ -216,7 +216,7 @@ "attributes" : [ { "grade" : "c", - "icon_url" : "https://server_domain/images/attributes/maybe-vegan.svg", + "icon_url" : "https://server_domain/images/attributes/dist/maybe-vegan.svg", "id" : "vegan", "match" : 50, "name" : "Végétalien", @@ -226,7 +226,7 @@ }, { "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/vegetarian.svg", + "icon_url" : "https://server_domain/images/attributes/dist/vegetarian.svg", "id" : "vegetarian", "match" : 100, "name" : "Végétarien", @@ -236,7 +236,7 @@ }, { "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/palm-oil-free.svg", + "icon_url" : "https://server_domain/images/attributes/dist/palm-oil-free.svg", "id" : "palm_oil_free", "match" : 100, "name" : "Sans huile de palme", @@ -254,7 +254,7 @@ "description" : "", "description_short" : "Degré de transformation des aliments inconnu", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/nova-group-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nova-group-unknown.svg", "id" : "nova", "match" : 0, "name" : "Groupe NOVA", @@ -264,7 +264,7 @@ }, { "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/0-additives.svg", + "icon_url" : "https://server_domain/images/attributes/dist/0-additives.svg", "id" : "additives", "match" : 100, "name" : "Additifs", @@ -282,7 +282,7 @@ "description" : "", "description_short" : "Impact environnemental inconnu", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/ecoscore-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/ecoscore-unknown.svg", "id" : "ecoscore", "match" : 0, "name" : "Eco-Score", @@ -294,7 +294,7 @@ "description" : "", "description_short" : "Pour l'instant seulement pour les produits avec du poulet ou des oeufs", "grade" : "e", - "icon_url" : "https://server_domain/images/attributes/forest-footprint-not-computed.svg", + "icon_url" : "https://server_domain/images/attributes/dist/forest-footprint-not-computed.svg", "id" : "forest_footprint", "match" : 0, "name" : "Empreinte forêt", @@ -311,7 +311,7 @@ "description" : "L'agriculture biologique vise à protéger l'environnement et à conserver la biodiversité en prohibant ou limitant l'utilisation d'engrais synthétiques, de pesticides et d'additifs alimentaires.", "description_short" : "Les produits bios encouragent la durabilité écologique et la biodiversité.", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/organic-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/organic-unknown.svg", "id" : "labels_organic", "name" : "Agriculture biologique", "status" : "unknown", @@ -321,7 +321,7 @@ "description" : "Quand vous achetez des produits du commerce équitable, les producteurs dans les pays en développement sont payés un prix plus haut et plus équitable, ce qui les aide à atteindre des plus hauts standards sociaux et environnementaux et à les conserver.", "description_short" : "Les produits du commerce équitable aident les producteurs des pays en voie de développement.", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/fair-trade-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/fair-trade-unknown.svg", "id" : "labels_fair_trade", "name" : "Commerce équitable", "status" : "unknown", 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 f4f9fe2f83b58..6058610c9d7a8 100644 --- a/tests/unit/expected_test_results/attributes/fr-palm-oil.json +++ b/tests/unit/expected_test_results/attributes/fr-palm-oil.json @@ -17,7 +17,7 @@ "description" : "", "description_short" : "Données manquantes pour calculer le Nutri-Score", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/nutriscore-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nutriscore-unknown.svg", "id" : "nutriscore", "match" : 0, "name" : "Nutri-Score", @@ -27,7 +27,7 @@ }, { "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/nutrient-level-salt-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nutrient-level-salt-unknown.svg", "id" : "low_salt", "missing" : "Données nutritionnelles manquantes", "name" : "Sel", @@ -36,7 +36,7 @@ }, { "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/nutrient-level-fat-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nutrient-level-fat-unknown.svg", "id" : "low_fat", "missing" : "Données nutritionnelles manquantes", "name" : "Matières grasses", @@ -45,7 +45,7 @@ }, { "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/nutrient-level-sugars-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nutrient-level-sugars-unknown.svg", "id" : "low_sugars", "missing" : "Données nutritionnelles manquantes", "name" : "Sucres", @@ -54,7 +54,7 @@ }, { "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/nutrient-level-saturated-fat-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nutrient-level-saturated-fat-unknown.svg", "id" : "low_saturated_fat", "missing" : "Données nutritionnelles manquantes", "name" : "Acides gras saturés", @@ -70,7 +70,7 @@ { "debug" : "2 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-gluten.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-gluten.svg", "id" : "allergens_no_gluten", "match" : 100, "name" : "Gluten", @@ -80,7 +80,7 @@ { "debug" : "2 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-milk.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-milk.svg", "id" : "allergens_no_milk", "match" : 100, "name" : "Lait", @@ -90,7 +90,7 @@ { "debug" : "2 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-eggs.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-eggs.svg", "id" : "allergens_no_eggs", "match" : 100, "name" : "Œufs", @@ -100,7 +100,7 @@ { "debug" : "2 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-nuts.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-nuts.svg", "id" : "allergens_no_nuts", "match" : 100, "name" : "Fruits à coque", @@ -110,7 +110,7 @@ { "debug" : "2 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-peanuts.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-peanuts.svg", "id" : "allergens_no_peanuts", "match" : 100, "name" : "Arachides", @@ -120,7 +120,7 @@ { "debug" : "2 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-sesame-seeds.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-sesame-seeds.svg", "id" : "allergens_no_sesame_seeds", "match" : 100, "name" : "Graines de sésame", @@ -130,7 +130,7 @@ { "debug" : "2 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-soybeans.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-soybeans.svg", "id" : "allergens_no_soybeans", "match" : 100, "name" : "Soja", @@ -140,7 +140,7 @@ { "debug" : "2 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-celery.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-celery.svg", "id" : "allergens_no_celery", "match" : 100, "name" : "Céleri", @@ -150,7 +150,7 @@ { "debug" : "2 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-mustard.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-mustard.svg", "id" : "allergens_no_mustard", "match" : 100, "name" : "Moutarde", @@ -160,7 +160,7 @@ { "debug" : "2 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-lupin.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-lupin.svg", "id" : "allergens_no_lupin", "match" : 100, "name" : "Lupin", @@ -170,7 +170,7 @@ { "debug" : "2 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-fish.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-fish.svg", "id" : "allergens_no_fish", "match" : 100, "name" : "Poisson", @@ -180,7 +180,7 @@ { "debug" : "2 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-crustaceans.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-crustaceans.svg", "id" : "allergens_no_crustaceans", "match" : 100, "name" : "Crustacés", @@ -190,7 +190,7 @@ { "debug" : "2 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-molluscs.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-molluscs.svg", "id" : "allergens_no_molluscs", "match" : 100, "name" : "Mollusques", @@ -200,7 +200,7 @@ { "debug" : "2 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-sulphur-dioxide-and-sulphites.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-sulphur-dioxide-and-sulphites.svg", "id" : "allergens_no_sulphur_dioxide_and_sulphites", "match" : 100, "name" : "Anhydride sulfureux et sulfites", @@ -216,7 +216,7 @@ "attributes" : [ { "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/vegan.svg", + "icon_url" : "https://server_domain/images/attributes/dist/vegan.svg", "id" : "vegan", "match" : 100, "name" : "Végétalien", @@ -226,7 +226,7 @@ }, { "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/vegetarian.svg", + "icon_url" : "https://server_domain/images/attributes/dist/vegetarian.svg", "id" : "vegetarian", "match" : 100, "name" : "Végétarien", @@ -236,7 +236,7 @@ }, { "grade" : "e", - "icon_url" : "https://server_domain/images/attributes/contains-palm-oil.svg", + "icon_url" : "https://server_domain/images/attributes/dist/contains-palm-oil.svg", "id" : "palm_oil_free", "match" : 0, "name" : "Sans huile de palme", @@ -254,7 +254,7 @@ "description" : "", "description_short" : "Degré de transformation des aliments inconnu", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/nova-group-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nova-group-unknown.svg", "id" : "nova", "match" : 0, "name" : "Groupe NOVA", @@ -264,7 +264,7 @@ }, { "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/0-additives.svg", + "icon_url" : "https://server_domain/images/attributes/dist/0-additives.svg", "id" : "additives", "match" : 100, "name" : "Additifs", @@ -282,7 +282,7 @@ "description" : "", "description_short" : "Impact environnemental inconnu", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/ecoscore-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/ecoscore-unknown.svg", "id" : "ecoscore", "match" : 0, "name" : "Eco-Score", @@ -294,7 +294,7 @@ "description" : "", "description_short" : "Pour l'instant seulement pour les produits avec du poulet ou des oeufs", "grade" : "e", - "icon_url" : "https://server_domain/images/attributes/forest-footprint-not-computed.svg", + "icon_url" : "https://server_domain/images/attributes/dist/forest-footprint-not-computed.svg", "id" : "forest_footprint", "match" : 0, "name" : "Empreinte forêt", @@ -311,7 +311,7 @@ "description" : "L'agriculture biologique vise à protéger l'environnement et à conserver la biodiversité en prohibant ou limitant l'utilisation d'engrais synthétiques, de pesticides et d'additifs alimentaires.", "description_short" : "Les produits bios encouragent la durabilité écologique et la biodiversité.", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/organic-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/organic-unknown.svg", "id" : "labels_organic", "name" : "Agriculture biologique", "status" : "unknown", @@ -321,7 +321,7 @@ "description" : "Quand vous achetez des produits du commerce équitable, les producteurs dans les pays en développement sont payés un prix plus haut et plus équitable, ce qui les aide à atteindre des plus hauts standards sociaux et environnementaux et à les conserver.", "description_short" : "Les produits du commerce équitable aident les producteurs des pays en voie de développement.", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/fair-trade-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/fair-trade-unknown.svg", "id" : "labels_fair_trade", "name" : "Commerce équitable", "status" : "unknown", 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 8d865bbd5f5bf..6fb44adeb8b5a 100644 --- a/tests/unit/expected_test_results/attributes/fr-vegetable-oils.json +++ b/tests/unit/expected_test_results/attributes/fr-vegetable-oils.json @@ -17,7 +17,7 @@ "description" : "", "description_short" : "Données manquantes pour calculer le Nutri-Score", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/nutriscore-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nutriscore-unknown.svg", "id" : "nutriscore", "match" : 0, "name" : "Nutri-Score", @@ -27,7 +27,7 @@ }, { "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/nutrient-level-salt-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nutrient-level-salt-unknown.svg", "id" : "low_salt", "missing" : "Données nutritionnelles manquantes", "name" : "Sel", @@ -36,7 +36,7 @@ }, { "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/nutrient-level-fat-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nutrient-level-fat-unknown.svg", "id" : "low_fat", "missing" : "Données nutritionnelles manquantes", "name" : "Matières grasses", @@ -45,7 +45,7 @@ }, { "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/nutrient-level-sugars-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nutrient-level-sugars-unknown.svg", "id" : "low_sugars", "missing" : "Données nutritionnelles manquantes", "name" : "Sucres", @@ -54,7 +54,7 @@ }, { "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/nutrient-level-saturated-fat-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nutrient-level-saturated-fat-unknown.svg", "id" : "low_saturated_fat", "missing" : "Données nutritionnelles manquantes", "name" : "Acides gras saturés", @@ -70,7 +70,7 @@ { "debug" : "3 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-gluten.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-gluten.svg", "id" : "allergens_no_gluten", "match" : 100, "name" : "Gluten", @@ -80,7 +80,7 @@ { "debug" : "3 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-milk.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-milk.svg", "id" : "allergens_no_milk", "match" : 100, "name" : "Lait", @@ -90,7 +90,7 @@ { "debug" : "3 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-eggs.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-eggs.svg", "id" : "allergens_no_eggs", "match" : 100, "name" : "Œufs", @@ -100,7 +100,7 @@ { "debug" : "3 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-nuts.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-nuts.svg", "id" : "allergens_no_nuts", "match" : 100, "name" : "Fruits à coque", @@ -110,7 +110,7 @@ { "debug" : "3 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-peanuts.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-peanuts.svg", "id" : "allergens_no_peanuts", "match" : 100, "name" : "Arachides", @@ -120,7 +120,7 @@ { "debug" : "3 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-sesame-seeds.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-sesame-seeds.svg", "id" : "allergens_no_sesame_seeds", "match" : 100, "name" : "Graines de sésame", @@ -130,7 +130,7 @@ { "debug" : "3 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-soybeans.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-soybeans.svg", "id" : "allergens_no_soybeans", "match" : 100, "name" : "Soja", @@ -140,7 +140,7 @@ { "debug" : "3 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-celery.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-celery.svg", "id" : "allergens_no_celery", "match" : 100, "name" : "Céleri", @@ -150,7 +150,7 @@ { "debug" : "3 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-mustard.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-mustard.svg", "id" : "allergens_no_mustard", "match" : 100, "name" : "Moutarde", @@ -160,7 +160,7 @@ { "debug" : "3 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-lupin.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-lupin.svg", "id" : "allergens_no_lupin", "match" : 100, "name" : "Lupin", @@ -170,7 +170,7 @@ { "debug" : "3 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-fish.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-fish.svg", "id" : "allergens_no_fish", "match" : 100, "name" : "Poisson", @@ -180,7 +180,7 @@ { "debug" : "3 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-crustaceans.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-crustaceans.svg", "id" : "allergens_no_crustaceans", "match" : 100, "name" : "Crustacés", @@ -190,7 +190,7 @@ { "debug" : "3 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-molluscs.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-molluscs.svg", "id" : "allergens_no_molluscs", "match" : 100, "name" : "Mollusques", @@ -200,7 +200,7 @@ { "debug" : "3 ingredients (0 unknown)", "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/no-sulphur-dioxide-and-sulphites.svg", + "icon_url" : "https://server_domain/images/attributes/dist/no-sulphur-dioxide-and-sulphites.svg", "id" : "allergens_no_sulphur_dioxide_and_sulphites", "match" : 100, "name" : "Anhydride sulfureux et sulfites", @@ -216,7 +216,7 @@ "attributes" : [ { "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/vegan.svg", + "icon_url" : "https://server_domain/images/attributes/dist/vegan.svg", "id" : "vegan", "match" : 100, "name" : "Végétalien", @@ -226,7 +226,7 @@ }, { "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/vegetarian.svg", + "icon_url" : "https://server_domain/images/attributes/dist/vegetarian.svg", "id" : "vegetarian", "match" : 100, "name" : "Végétarien", @@ -236,7 +236,7 @@ }, { "grade" : "c", - "icon_url" : "https://server_domain/images/attributes/may-contain-palm-oil.svg", + "icon_url" : "https://server_domain/images/attributes/dist/may-contain-palm-oil.svg", "id" : "palm_oil_free", "match" : 50, "name" : "Sans huile de palme", @@ -254,7 +254,7 @@ "description" : "", "description_short" : "Degré de transformation des aliments inconnu", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/nova-group-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/nova-group-unknown.svg", "id" : "nova", "match" : 0, "name" : "Groupe NOVA", @@ -264,7 +264,7 @@ }, { "grade" : "a", - "icon_url" : "https://server_domain/images/attributes/0-additives.svg", + "icon_url" : "https://server_domain/images/attributes/dist/0-additives.svg", "id" : "additives", "match" : 100, "name" : "Additifs", @@ -282,7 +282,7 @@ "description" : "", "description_short" : "Impact environnemental inconnu", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/ecoscore-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/ecoscore-unknown.svg", "id" : "ecoscore", "match" : 0, "name" : "Eco-Score", @@ -294,7 +294,7 @@ "description" : "", "description_short" : "Pour l'instant seulement pour les produits avec du poulet ou des oeufs", "grade" : "e", - "icon_url" : "https://server_domain/images/attributes/forest-footprint-not-computed.svg", + "icon_url" : "https://server_domain/images/attributes/dist/forest-footprint-not-computed.svg", "id" : "forest_footprint", "match" : 0, "name" : "Empreinte forêt", @@ -311,7 +311,7 @@ "description" : "L'agriculture biologique vise à protéger l'environnement et à conserver la biodiversité en prohibant ou limitant l'utilisation d'engrais synthétiques, de pesticides et d'additifs alimentaires.", "description_short" : "Les produits bios encouragent la durabilité écologique et la biodiversité.", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/organic-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/organic-unknown.svg", "id" : "labels_organic", "name" : "Agriculture biologique", "status" : "unknown", @@ -321,7 +321,7 @@ "description" : "Quand vous achetez des produits du commerce équitable, les producteurs dans les pays en développement sont payés un prix plus haut et plus équitable, ce qui les aide à atteindre des plus hauts standards sociaux et environnementaux et à les conserver.", "description_short" : "Les produits du commerce équitable aident les producteurs des pays en voie de développement.", "grade" : "unknown", - "icon_url" : "https://server_domain/images/attributes/fair-trade-unknown.svg", + "icon_url" : "https://server_domain/images/attributes/dist/fair-trade-unknown.svg", "id" : "labels_fair_trade", "name" : "Commerce équitable", "status" : "unknown", diff --git a/tests/unit/import_convert_carrefour_france.t b/tests/unit/import_convert_carrefour_france.t index 396bc32ec2a77..6d5fcceca205d 100644 --- a/tests/unit/import_convert_carrefour_france.t +++ b/tests/unit/import_convert_carrefour_france.t @@ -86,6 +86,6 @@ export_csv($export_args_ref); close($exported_csv); ProductOpener::Test::compare_csv_file_to_expected_results($exported_csv_file, $expected_result_dir, - $update_expected_results); + $update_expected_results, "carrefour-france"); done_testing(); diff --git a/tests/unit/paths.t b/tests/unit/paths.t new file mode 100644 index 0000000000000..5482d3a2a1514 --- /dev/null +++ b/tests/unit/paths.t @@ -0,0 +1,68 @@ +#!/usr/bin/perl -w + +use ProductOpener::PerlStandards; + +use Test::More; + +use ProductOpener::Config qw/:all/; +use ProductOpener::Paths qw/:all/; +use File::Path qw/remove_tree/; + +my $EXPECTED_BASE_PATHS = { + CACHE_BUILD => "$data_root/build-cache", + CACHE_DEBUG => "$data_root/debug", + CACHE_NEW_IMAGES => "$data_root/new_images", + CACHE_TMP => "$data_root/tmp", + DELETED_IMAGES => "$data_root/deleted.images", + DELETED_PRIVATE_PRODUCTS => "$data_root/deleted_private_products", + DELETED_PRODUCTS => "$data_root/deleted_products", + DELETED_PRODUCTS_IMAGES => "$data_root/deleted_products_images", + EXPORT_FILES => "$data_root/export_files", + FILES_DEBUG => "$www_root/files/debug", + IMPORT_FILES => "$data_root/import_files", + LANG => "$data_root/lang", + LOGS => "$data_root/logs", + ORGS => "$data_root/orgs", + PRIVATE_DATA => "$data_root/data", + PRODUCTS => "$data_root/products", + PRODUCTS_IMAGES => "$www_root/images/products", + PUBLIC_DATA => "$www_root/data", + PUBLIC_DUMP => "$www_root/dump", + PUBLIC_EXPORTS => "$www_root/exports", + PUBLIC_FILES => "$www_root/files", + REVERTED_PRODUCTS => "$data_root/reverted_products", + USERS => "$data_root/users", + USERS_TRANSLATIONS => "$data_root/translate", +}; +my $EXPECTED_FOREIGN_PATHS = { + OBF_PRODUCTS_DIR => '/srv/obf/products', + OBF_PRODUCTS_IMAGES_DIR => '/srv/obf/html/images/products', + OPFF_PRODUCTS_DIR => '/srv/opff/products', + OPFF_PRODUCTS_IMAGES_DIR => '/srv/opff/html/images/products', + OPF_PRODUCTS_DIR => '/srv/opf/products', + OPF_PRODUCTS_IMAGES_DIR => '/srv/opf/html/images/products', +}; +my %EXPECTED_OFF_PATHS = (%{$EXPECTED_BASE_PATHS}, %{$EXPECTED_FOREIGN_PATHS},); +is_deeply(base_paths(), \%EXPECTED_OFF_PATHS, "base_paths content for off"); + +ok(ensure_dir_created("$BASE_DIRS{CACHE_TMP}"), "cache tmp directory exists"); +remove_tree("$BASE_DIRS{CACHE_TMP}/test-unit-xxx"); +ok(ensure_dir_created("$BASE_DIRS{CACHE_TMP}/test-unit-xxx/some/path"), "we can create a path in cache tmp directory"); +remove_tree("$BASE_DIRS{CACHE_TMP}/test-unit-xxx"); +ok( + ensure_dir_created_or_die("$BASE_DIRS{CACHE_TMP}/test-unit-xxx/some/path"), + "we can create a path in cache tmp directory without dying" +); + +ok(!ensure_dir_created("$data_root/doesnotexists"), "We do not create a path that's not under a know folder"); + +# pro instances +my %EXPECTED_OFF_PRO_PATHS = (%{$EXPECTED_BASE_PATHS}, "SFTP_HOME" => "/mnt/podata/sftp"); +my $producers_platform_previous = $server_options{producers_platform}; +{ + $server_options{producers_platform} = 1; + is_deeply(base_paths(), \%EXPECTED_OFF_PRO_PATHS, "base_paths content for off pro"); +} +$server_options{producers_platform} = $producers_platform_previous; + +done_testing()