From dfe81583c2a7fd75b3fa14d76d071f48ff3a1608 Mon Sep 17 00:00:00 2001 From: sygel Date: Fri, 3 Oct 2025 15:31:27 +0200 Subject: [PATCH 1/3] [ADD] website_sale_cart_add_product_xlsx_csv --- requirements.txt | 2 + .../README.rst | 124 +++++ .../__init__.py | 4 + .../__manifest__.py | 21 + .../controllers/__init__.py | 3 + .../controllers/main.py | 178 +++++++ .../data/import_file_example.xml | 16 + .../i18n/es.po | 156 ++++++ .../models/__init__.py | 4 + .../models/res_config_settings.py | 20 + .../models/website.py | 21 + .../pyproject.toml | 3 + .../readme/CONFIGURE.md | 4 + .../readme/CONTRIBUTORS.md | 4 + .../readme/DESCRIPTION.md | 3 + .../readme/ROADMAP.md | 1 + .../readme/USAGE.md | 9 + .../static/description/icon.png | Bin 0 -> 9455 bytes .../static/description/icon.svg | 79 +++ .../static/description/index.html | 477 ++++++++++++++++++ .../static/xlsx/import_example.xlsx | Bin 0 -> 5281 bytes .../static/xlsx/import_unit_test.csv | 7 + .../static/xlsx/import_unit_test.error | 7 + .../static/xlsx/import_unit_test.xlsx | Bin 0 -> 5319 bytes .../tests/__init__.py | 3 + ..._website_sale_cart_add_product_xlsx_csv.py | 95 ++++ .../views/cart_templates.xml | 89 ++++ .../views/res_config_settings.xml | 28 + 28 files changed, 1358 insertions(+) create mode 100644 requirements.txt create mode 100644 website_sale_cart_add_product_xlsx_csv/README.rst create mode 100644 website_sale_cart_add_product_xlsx_csv/__init__.py create mode 100644 website_sale_cart_add_product_xlsx_csv/__manifest__.py create mode 100644 website_sale_cart_add_product_xlsx_csv/controllers/__init__.py create mode 100644 website_sale_cart_add_product_xlsx_csv/controllers/main.py create mode 100644 website_sale_cart_add_product_xlsx_csv/data/import_file_example.xml create mode 100644 website_sale_cart_add_product_xlsx_csv/i18n/es.po create mode 100644 website_sale_cart_add_product_xlsx_csv/models/__init__.py create mode 100644 website_sale_cart_add_product_xlsx_csv/models/res_config_settings.py create mode 100644 website_sale_cart_add_product_xlsx_csv/models/website.py create mode 100644 website_sale_cart_add_product_xlsx_csv/pyproject.toml create mode 100755 website_sale_cart_add_product_xlsx_csv/readme/CONFIGURE.md create mode 100755 website_sale_cart_add_product_xlsx_csv/readme/CONTRIBUTORS.md create mode 100755 website_sale_cart_add_product_xlsx_csv/readme/DESCRIPTION.md create mode 100644 website_sale_cart_add_product_xlsx_csv/readme/ROADMAP.md create mode 100755 website_sale_cart_add_product_xlsx_csv/readme/USAGE.md create mode 100644 website_sale_cart_add_product_xlsx_csv/static/description/icon.png create mode 100644 website_sale_cart_add_product_xlsx_csv/static/description/icon.svg create mode 100644 website_sale_cart_add_product_xlsx_csv/static/description/index.html create mode 100644 website_sale_cart_add_product_xlsx_csv/static/xlsx/import_example.xlsx create mode 100644 website_sale_cart_add_product_xlsx_csv/static/xlsx/import_unit_test.csv create mode 100644 website_sale_cart_add_product_xlsx_csv/static/xlsx/import_unit_test.error create mode 100644 website_sale_cart_add_product_xlsx_csv/static/xlsx/import_unit_test.xlsx create mode 100644 website_sale_cart_add_product_xlsx_csv/tests/__init__.py create mode 100644 website_sale_cart_add_product_xlsx_csv/tests/test_website_sale_cart_add_product_xlsx_csv.py create mode 100644 website_sale_cart_add_product_xlsx_csv/views/cart_templates.xml create mode 100644 website_sale_cart_add_product_xlsx_csv/views/res_config_settings.xml diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000000..bf99963586 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +# generated from manifests external_dependencies +openpyxl diff --git a/website_sale_cart_add_product_xlsx_csv/README.rst b/website_sale_cart_add_product_xlsx_csv/README.rst new file mode 100644 index 0000000000..bcae50e009 --- /dev/null +++ b/website_sale_cart_add_product_xlsx_csv/README.rst @@ -0,0 +1,124 @@ +.. image:: https://odoo-community.org/readme-banner-image + :target: https://odoo-community.org/get-involved?utm_source=readme + :alt: Odoo Community Association + +====================================== +Website Sale Cart Add Product Xlsx Csv +====================================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:67f5bf0329604338a76994d610ad17d19826201b76ac05d7f91f2d2e27960b6e + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/license-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fe--commerce-lightgray.png?logo=github + :target: https://github.com/OCA/e-commerce/tree/17.0/website_sale_cart_add_product_xlsx_csv + :alt: OCA/e-commerce +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/e-commerce-17-0/e-commerce-17-0-website_sale_cart_add_product_xlsx_csv + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/e-commerce&target_branch=17.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module adds a button in the website cart that let users import a +xlsx or csv file with the products and quantities that he wants to add. + +This button is only shown on empty carts, and the file must contain the +product's internal reference and the quantity to buy. + +**Table of contents** + +.. contents:: + :local: + +Configuration +============= + +To configure this module, you need to: + +- To enable the cart import button, go to Website / Configuration / + Settings. Then search the "Cart Import Button" and set its value. +- To edit the maximum file size, go to Website / Configuration / + Settings. Then search the "Cart import button file size limit" and + edit its value. + +Usage +===== + +To use this module, you need to: + +1. Go to the "/shop/cart" path of your server website. Example: + "http://localhost:8069/shop/cart" +2. You will see your cart. Empty it if it has products. +3. Click on "Download example file". Fill the xlsx file rows: 3.1. The + "default_code" column is the internal reference of the product that + you are going to add to your cart 3.2. The "product_uom_qty" is the + qty of the product that you are going to add to your cart +4. Select the filled file, and click the "Import" button +5. You will see the cart with the imported products. If some error + hapened or there are products that could not be imported, the system + will show a message + +Known issues / Roadmap +====================== + +- Despithe the fact that the cart button is enabled by default, some + Odoo instances have the website configured to hide it if it is empty. + If the shopping cart button is hidden without anything in it, the + functionality cannot be used until something is added to the cart. + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +------- + +* Sygel + +Contributors +------------ + +- `Sygel `__: + + - Alberto Martínez + - Valentin Vinagre + - Harald Panten + +Maintainers +----------- + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +This module is part of the `OCA/e-commerce `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/website_sale_cart_add_product_xlsx_csv/__init__.py b/website_sale_cart_add_product_xlsx_csv/__init__.py new file mode 100644 index 0000000000..5c2bd8c997 --- /dev/null +++ b/website_sale_cart_add_product_xlsx_csv/__init__.py @@ -0,0 +1,4 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from . import controllers +from . import models diff --git a/website_sale_cart_add_product_xlsx_csv/__manifest__.py b/website_sale_cart_add_product_xlsx_csv/__manifest__.py new file mode 100644 index 0000000000..333e31a00b --- /dev/null +++ b/website_sale_cart_add_product_xlsx_csv/__manifest__.py @@ -0,0 +1,21 @@ +# Copyright 2025 Alberto Martínez +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +{ + "name": "Website Sale Cart Add Product Xlsx Csv", + "summary": "Adds button to import xlsx or csv in website cart", + "version": "17.0.1.0.0", + "website": "https://github.com/OCA/e-commerce", + "author": "Sygel, Odoo Community Association (OCA)", + "license": "AGPL-3", + "application": False, + "installable": True, + "depends": [ + "website_sale_stock", + ], + "external_dependencies": {"python": ["openpyxl"]}, + "data": [ + "data/import_file_example.xml", + "views/cart_templates.xml", + "views/res_config_settings.xml", + ], +} diff --git a/website_sale_cart_add_product_xlsx_csv/controllers/__init__.py b/website_sale_cart_add_product_xlsx_csv/controllers/__init__.py new file mode 100644 index 0000000000..f43232f012 --- /dev/null +++ b/website_sale_cart_add_product_xlsx_csv/controllers/__init__.py @@ -0,0 +1,3 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from . import main diff --git a/website_sale_cart_add_product_xlsx_csv/controllers/main.py b/website_sale_cart_add_product_xlsx_csv/controllers/main.py new file mode 100644 index 0000000000..c767b61f2b --- /dev/null +++ b/website_sale_cart_add_product_xlsx_csv/controllers/main.py @@ -0,0 +1,178 @@ +# Copyright 2025 Alberto Martínez +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +import base64 +import csv +import io +import math + +from openpyxl import load_workbook + +from odoo import _, http +from odoo.exceptions import UserError +from odoo.http import content_disposition, request + +from odoo.addons.website_sale.controllers.main import WebsiteSale + + +class WebsiteSaleAddProductXlsxCsv(WebsiteSale): + def _parse_file(self, file): + headers = False + data = False + if file.filename.endswith(".csv"): + file.stream.seek(0) + text_stream = io.StringIO(file.read().decode("utf-8")) + reader = csv.DictReader(text_stream) + headers = reader.fieldnames + rows = [row for row in reader if any(row.values())] + data = enumerate(rows, start=2) + data = rows + + elif file.filename.endswith(".xlsx"): + file.stream.seek(0) + wb = load_workbook(io.BytesIO(file.read()), data_only=True) + sheet = wb.active + rows = list(sheet.iter_rows(values_only=True)) + headers = [str(h).strip() for h in rows[0]] + rows = rows[1:] + data = [dict(zip(headers, row, strict=True)) for row in rows if any(row)] + + return headers, data + + def _can_be_imported(self, product, qty, sale): + can_be_imported = True + error_reason = "" + try: + qty = float(qty) + except ValueError: + can_be_imported = False + error_reason = _("The quantity is not a number") + if not isinstance(qty, int | float) or math.isnan(qty) or qty <= 0: + can_be_imported = False + error_reason = _("The quantity should be a positive number") + if len(product) != 1: + can_be_imported = False + error_reason = _("The product was not found") + elif not product.active: + can_be_imported = False + error_reason = _("The product is archived") + elif not product.sale_ok: + can_be_imported = False + error_reason = _("Product can not be sold") + elif not product.website_published: + can_be_imported = False + error_reason = _("Product is not published on the website") + elif ( + not product.allow_out_of_stock_order + and qty > product.with_context(warehouse=sale.warehouse_id.id).free_qty + ): + can_be_imported = False + qty = product.with_context(warehouse=sale.warehouse_id.id).free_qty + error_reason = _("Product max saleable qty is {}").format(qty) + return can_be_imported, error_reason + + def _check_file_size(self, file): + file_limit_mb = request.website.cart_import_button_file_limit + file_size_bytes = file.stream.seek(0, 2) + file_size_ok = file_size_bytes / 1024**2 <= file_limit_mb + file.stream.seek(0) + return file_size_ok + + def import_file(self, sale_order, file): + import_status = "sucess" + import_msg = "" + headers = data = False + failed_products = [] + if not self._check_file_size(file): + import_status = "error" + import_msg = _( + "The file size is greater than the maximum allowed, {} MB" + ).format(request.website.cart_import_button_file_limit) + + if import_status != "error" and not ( + file.filename.endswith(".csv") or file.filename.endswith(".xlsx") + ): + import_status = "error" + import_msg = _("Incorrect file format, it must me a .xlsx or a .csv") + else: + headers, data = self._parse_file(file) + + if import_status != "error" and headers != ["default_code", "product_uom_qty"]: + import_status = "error" + import_msg = _( + "Incorrect file format, " + "the columns should be 'default_code' and 'product_uom_qty'" + ) + + if import_status != "error": + for index, row in enumerate(data, start=2): + default_code = str(row["default_code"]).strip() + qty = row["product_uom_qty"] + product = ( + request.env["product.product"] + .with_context(active_test=False) + .search([("default_code", "=", default_code)]) + ) + can_be_imported, warn_msg = self._can_be_imported( + product, qty, sale_order + ) + if not can_be_imported: + import_status = "warn" + failed_products.append( + f"Line {index}. {row['default_code']}: {warn_msg}" + ) + else: + try: + sale_order._cart_update( + product_id=product.id, set_qty=float(qty) + ) + except UserError as e: + import_status = "warn" + failed_products.append( + f"Line {index}. {row['default_code']}: {str(e)}" + ) + + return import_status, import_msg, failed_products + + @http.route("/shop/cart", type="http", auth="public", website=True, sitemap=False) + def cart(self, access_token=None, revive="", **post): + file = post.get("cart_file") + if file: + sale_order = request.website.sale_get_order(force_create=True) + import_status, import_msg, failed_products = self.import_file( + sale_order, file + ) + post.update( + { + "import_status": import_status, + "import_msg": import_msg, + "failed_products": failed_products, + } + ) + return super().cart(access_token, revive, **post) + + def _cart_values(self, **post): + res = super()._cart_values(**post) + if "import_status" in post: + res["import_status"] = post.get("import_status") + if "import_msg" in post: + res["import_msg"] = post.get("import_msg") + if "failed_products" in post: + res["failed_products"] = post.get("failed_products") + return res + + @http.route("/shop/cart/import/example", auth="public") + def cart_import_example(self): + attachment = request.env.ref( + "website_sale_cart_add_product_xlsx_csv.cart_import_example" + ).sudo() + filecontent = base64.b64decode(attachment.datas) + filename = f"{attachment.name}.xlsx" + + return request.make_response( + filecontent, + [ + ("Content-Type", attachment.mimetype), + ("Content-Disposition", content_disposition(filename)), + ], + ) diff --git a/website_sale_cart_add_product_xlsx_csv/data/import_file_example.xml b/website_sale_cart_add_product_xlsx_csv/data/import_file_example.xml new file mode 100644 index 0000000000..3424866b18 --- /dev/null +++ b/website_sale_cart_add_product_xlsx_csv/data/import_file_example.xml @@ -0,0 +1,16 @@ + + + + application/vnd.ms-excel + cart_import_example + binary + + website_sale_cart_add_product_xlsx_csv/static/xlsx/import_example.xlsx + + diff --git a/website_sale_cart_add_product_xlsx_csv/i18n/es.po b/website_sale_cart_add_product_xlsx_csv/i18n/es.po new file mode 100644 index 0000000000..4a86296b8a --- /dev/null +++ b/website_sale_cart_add_product_xlsx_csv/i18n/es.po @@ -0,0 +1,156 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * website_sale_cart_add_product_xlsx_csv +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 17.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2025-10-23 10:44+0000\n" +"PO-Revision-Date: 2025-10-23 12:46+0200\n" +"Last-Translator: \n" +"Language-Team: \n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: \n" +"X-Generator: Poedit 3.0.1\n" + +#. module: website_sale_cart_add_product_xlsx_csv +#: model_terms:ir.ui.view,arch_db:website_sale_cart_add_product_xlsx_csv.cart_lines_import +msgid "" +"You can import the " +"cart with a xlsx/csv file" +msgstr "" +"Puedes importar el " +"carrito con un archivo xlsx o csv" + +#. module: website_sale_cart_add_product_xlsx_csv +#: model_terms:ir.ui.view,arch_db:website_sale_cart_add_product_xlsx_csv.cart_lines_import +msgid "Download example file" +msgstr "Descargar archivo de ejemplo" + +#. module: website_sale_cart_add_product_xlsx_csv +#: model_terms:ir.ui.view,arch_db:website_sale_cart_add_product_xlsx_csv.res_config_settings_view_form +msgid "Cart Import Button" +msgstr "Botón de importación de carrito" + +#. module: website_sale_cart_add_product_xlsx_csv +#: model_terms:ir.ui.view,arch_db:website_sale_cart_add_product_xlsx_csv.res_config_settings_view_form +msgid "Cart Import Button File Size Limit (MB)" +msgstr "Límite de tamaño de archivo (MB) del botón de importación de carrito" + +#. module: website_sale_cart_add_product_xlsx_csv +#: model:ir.model.fields,field_description:website_sale_cart_add_product_xlsx_csv.field_res_config_settings__cart_import_button_file_limit +#: model:ir.model.fields,field_description:website_sale_cart_add_product_xlsx_csv.field_website__cart_import_button_file_limit +msgid "Cart import button file size limit (MB)" +msgstr "Límite de tamaño de archivo (MB) del botón de importación de carrito" + +#. module: website_sale_cart_add_product_xlsx_csv +#: model:ir.model,name:website_sale_cart_add_product_xlsx_csv.model_res_config_settings +msgid "Config Settings" +msgstr "Ajustes de configuración" + +#. module: website_sale_cart_add_product_xlsx_csv +#: model_terms:ir.ui.view,arch_db:website_sale_cart_add_product_xlsx_csv.res_config_settings_view_form +msgid "Enable or disable the cart import button" +msgstr "Habilitar o deshabilitar el botón de importación de carrito" + +#. module: website_sale_cart_add_product_xlsx_csv +#: model_terms:ir.ui.view,arch_db:website_sale_cart_add_product_xlsx_csv.cart_lines_import +msgid "Import success" +msgstr "Importación exitosa" + +#. module: website_sale_cart_add_product_xlsx_csv +#: model_terms:ir.ui.view,arch_db:website_sale_cart_add_product_xlsx_csv.cart_lines_import +msgid "Importation error." +msgstr "Error de importación." + +#. module: website_sale_cart_add_product_xlsx_csv +#. odoo-python +#: code:addons/website_sale_cart_add_product_xlsx_csv/controllers/main.py:0 +#, python-format +msgid "Incorrect file format, it must me a .xlsx or a .csv" +msgstr "Formato de archivo incorrecto, debe ser un .xlsx o un csv" + +#. module: website_sale_cart_add_product_xlsx_csv +#. odoo-python +#: code:addons/website_sale_cart_add_product_xlsx_csv/controllers/main.py:0 +#, python-format +msgid "" +"Incorrect file format, the columns should be 'default_code' and " +"'product_uom_qty'" +msgstr "" +"Formato de archivo incorrecto, las columnas deben ser 'default_code' y " +"'product_uom_qty'" + +#. module: website_sale_cart_add_product_xlsx_csv +#: model:ir.model.fields,field_description:website_sale_cart_add_product_xlsx_csv.field_res_config_settings__cart_import_button +#: model:ir.model.fields,field_description:website_sale_cart_add_product_xlsx_csv.field_website__cart_import_button +msgid "Is the cart import button enabled?" +msgstr "¿Está el botón de importar carrito habilitado?" + +#. module: website_sale_cart_add_product_xlsx_csv +#: model_terms:ir.ui.view,arch_db:website_sale_cart_add_product_xlsx_csv.cart_lines_import +msgid "Partial import. The following products had errors:" +msgstr "Importación parcial. Los siguientes productos tienen errores:" + +#. module: website_sale_cart_add_product_xlsx_csv +#. odoo-python +#: code:addons/website_sale_cart_add_product_xlsx_csv/controllers/main.py:0 +#, python-format +msgid "Product can not be sold" +msgstr "El producto no puede ser vendido" + +#. module: website_sale_cart_add_product_xlsx_csv +#. odoo-python +#: code:addons/website_sale_cart_add_product_xlsx_csv/controllers/main.py:0 +#, python-format +msgid "Product is not published on the website" +msgstr "El producto no está publicado en el sitio web" + +#. module: website_sale_cart_add_product_xlsx_csv +#. odoo-python +#: code:addons/website_sale_cart_add_product_xlsx_csv/controllers/main.py:0 +#, python-format +msgid "Product max saleable qty is {}" +msgstr "La cantidad máxima que se puede vender es: {}" + +#. module: website_sale_cart_add_product_xlsx_csv +#. odoo-python +#: code:addons/website_sale_cart_add_product_xlsx_csv/controllers/main.py:0 +#, python-format +msgid "The file size is greater than the maximum allowed, {} MB" +msgstr "El tamaño de archivo es más grande que el máximo permitido, {} MB" + +#. module: website_sale_cart_add_product_xlsx_csv +#: model:ir.model.constraint,message:website_sale_cart_add_product_xlsx_csv.constraint_website_cart_import_button_file_limit_min +msgid "The file size limit must be positive" +msgstr "El tamaño limite debe ser positivo" + +#. module: website_sale_cart_add_product_xlsx_csv +#. odoo-python +#: code:addons/website_sale_cart_add_product_xlsx_csv/controllers/main.py:0 +#, python-format +msgid "The product is archived" +msgstr "El producto está archivado" + +#. module: website_sale_cart_add_product_xlsx_csv +#. odoo-python +#: code:addons/website_sale_cart_add_product_xlsx_csv/controllers/main.py:0 +#, python-format +msgid "The product was not found" +msgstr "El producto no fue encontrado" + +#. module: website_sale_cart_add_product_xlsx_csv +#. odoo-python +#: code:addons/website_sale_cart_add_product_xlsx_csv/controllers/main.py:0 +#, python-format +msgid "The quantity should be a positive number" +msgstr "La cantidad debe der un número positivo" + +#. module: website_sale_cart_add_product_xlsx_csv +#: model:ir.model,name:website_sale_cart_add_product_xlsx_csv.model_website +msgid "Website" +msgstr "Sitio web" diff --git a/website_sale_cart_add_product_xlsx_csv/models/__init__.py b/website_sale_cart_add_product_xlsx_csv/models/__init__.py new file mode 100644 index 0000000000..a424e440f1 --- /dev/null +++ b/website_sale_cart_add_product_xlsx_csv/models/__init__.py @@ -0,0 +1,4 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from . import res_config_settings +from . import website diff --git a/website_sale_cart_add_product_xlsx_csv/models/res_config_settings.py b/website_sale_cart_add_product_xlsx_csv/models/res_config_settings.py new file mode 100644 index 0000000000..350f6ddcbc --- /dev/null +++ b/website_sale_cart_add_product_xlsx_csv/models/res_config_settings.py @@ -0,0 +1,20 @@ +# Copyright 2025 Alberto Martínez +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import fields, models + + +class ResConfigSettings(models.TransientModel): + _inherit = "res.config.settings" + + cart_import_button = fields.Boolean( + string="Is the cart import button enabled?", + related="website_id.cart_import_button", + readonly=False, + ) + + cart_import_button_file_limit = fields.Float( + string="Cart import button file size limit (MB)", + related="website_id.cart_import_button_file_limit", + readonly=False, + ) diff --git a/website_sale_cart_add_product_xlsx_csv/models/website.py b/website_sale_cart_add_product_xlsx_csv/models/website.py new file mode 100644 index 0000000000..9c7907c910 --- /dev/null +++ b/website_sale_cart_add_product_xlsx_csv/models/website.py @@ -0,0 +1,21 @@ +# Copyright 2025 Alberto Martínez +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import fields, models + + +class Website(models.Model): + _inherit = "website" + + cart_import_button = fields.Boolean(string="Is the cart import button enabled?") + cart_import_button_file_limit = fields.Float( + string="Cart import button file size limit (MB)", default=2 + ) + + _sql_constraints = [ + ( + "cart_import_button_file_limit_min", + "CHECK (vat_prorate > 0)", + "The file size limit must be positive", + ), + ] diff --git a/website_sale_cart_add_product_xlsx_csv/pyproject.toml b/website_sale_cart_add_product_xlsx_csv/pyproject.toml new file mode 100644 index 0000000000..4231d0cccb --- /dev/null +++ b/website_sale_cart_add_product_xlsx_csv/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/website_sale_cart_add_product_xlsx_csv/readme/CONFIGURE.md b/website_sale_cart_add_product_xlsx_csv/readme/CONFIGURE.md new file mode 100755 index 0000000000..4d151b0761 --- /dev/null +++ b/website_sale_cart_add_product_xlsx_csv/readme/CONFIGURE.md @@ -0,0 +1,4 @@ +To configure this module, you need to: + +- To enable the cart import button, go to Website / Configuration / Settings. Then search the "Cart Import Button" and set its value. +- To edit the maximum file size, go to Website / Configuration / Settings. Then search the "Cart import button file size limit" and edit its value. diff --git a/website_sale_cart_add_product_xlsx_csv/readme/CONTRIBUTORS.md b/website_sale_cart_add_product_xlsx_csv/readme/CONTRIBUTORS.md new file mode 100755 index 0000000000..f566245042 --- /dev/null +++ b/website_sale_cart_add_product_xlsx_csv/readme/CONTRIBUTORS.md @@ -0,0 +1,4 @@ +- [Sygel](https://www.sygel.es): + - Alberto Martínez + - Valentin Vinagre + - Harald Panten diff --git a/website_sale_cart_add_product_xlsx_csv/readme/DESCRIPTION.md b/website_sale_cart_add_product_xlsx_csv/readme/DESCRIPTION.md new file mode 100755 index 0000000000..bfdf7150fb --- /dev/null +++ b/website_sale_cart_add_product_xlsx_csv/readme/DESCRIPTION.md @@ -0,0 +1,3 @@ +This module adds a button in the website cart that let users import a xlsx or csv file with the products and quantities that he wants to add. + +This button is only shown on empty carts, and the file must contain the product's internal reference and the quantity to buy. diff --git a/website_sale_cart_add_product_xlsx_csv/readme/ROADMAP.md b/website_sale_cart_add_product_xlsx_csv/readme/ROADMAP.md new file mode 100644 index 0000000000..0de6f3436d --- /dev/null +++ b/website_sale_cart_add_product_xlsx_csv/readme/ROADMAP.md @@ -0,0 +1 @@ +- Despithe the fact that the cart button is enabled by default, some Odoo instances have the website configured to hide it if it is empty. If the shopping cart button is hidden without anything in it, the functionality cannot be used until something is added to the cart. diff --git a/website_sale_cart_add_product_xlsx_csv/readme/USAGE.md b/website_sale_cart_add_product_xlsx_csv/readme/USAGE.md new file mode 100755 index 0000000000..b50ab614c8 --- /dev/null +++ b/website_sale_cart_add_product_xlsx_csv/readme/USAGE.md @@ -0,0 +1,9 @@ +To use this module, you need to: + +1. Go to the "/shop/cart" path of your server website. Example: "http://localhost:8069/shop/cart" +2. You will see your cart. Empty it if it has products. +3. Click on "Download example file". Fill the xlsx file rows: + 3.1. The "default_code" column is the internal reference of the product that you are going to add to your cart + 3.2. The "product_uom_qty" is the qty of the product that you are going to add to your cart +4. Select the filled file, and click the "Import" button +5. You will see the cart with the imported products. If some error hapened or there are products that could not be imported, the system will show a message diff --git a/website_sale_cart_add_product_xlsx_csv/static/description/icon.png b/website_sale_cart_add_product_xlsx_csv/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..3a0328b516c4980e8e44cdb63fd945757ddd132d GIT binary patch literal 9455 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 z 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 Xviia!U7SGha1wx#SCgwmn*{w2TRX*I literal 0 HcmV?d00001 diff --git a/website_sale_cart_add_product_xlsx_csv/static/description/icon.svg b/website_sale_cart_add_product_xlsx_csv/static/description/icon.svg new file mode 100644 index 0000000000..a7a26d0932 --- /dev/null +++ b/website_sale_cart_add_product_xlsx_csv/static/description/icon.svg @@ -0,0 +1,79 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/website_sale_cart_add_product_xlsx_csv/static/description/index.html b/website_sale_cart_add_product_xlsx_csv/static/description/index.html new file mode 100644 index 0000000000..f38e9d07b1 --- /dev/null +++ b/website_sale_cart_add_product_xlsx_csv/static/description/index.html @@ -0,0 +1,477 @@ + + + + + +README.rst + + + +
+ + + +Odoo Community Association + +
+

Website Sale Cart Add Product Xlsx Csv

+ +

Beta License: AGPL-3 OCA/e-commerce Translate me on Weblate Try me on Runboat

+

This module adds a button in the website cart that let users import a +xlsx or csv file with the products and quantities that he wants to add.

+

This button is only shown on empty carts, and the file must contain the +product’s internal reference and the quantity to buy.

+

Table of contents

+ +
+

Configuration

+

To configure this module, you need to:

+
    +
  • To enable the cart import button, go to Website / Configuration / +Settings. Then search the “Cart Import Button” and set its value.
  • +
  • To edit the maximum file size, go to Website / Configuration / +Settings. Then search the “Cart import button file size limit” and +edit its value.
  • +
+
+
+

Usage

+

To use this module, you need to:

+
    +
  1. Go to the “/shop/cart” path of your server website. Example: +“http://localhost:8069/shop/cart
  2. +
  3. You will see your cart. Empty it if it has products.
  4. +
  5. Click on “Download example file”. Fill the xlsx file rows: 3.1. The +“default_code” column is the internal reference of the product that +you are going to add to your cart 3.2. The “product_uom_qty” is the +qty of the product that you are going to add to your cart
  6. +
  7. Select the filled file, and click the “Import” button
  8. +
  9. You will see the cart with the imported products. If some error +hapened or there are products that could not be imported, the system +will show a message
  10. +
+
+
+

Known issues / Roadmap

+
    +
  • Despithe the fact that the cart button is enabled by default, some +Odoo instances have the website configured to hide it if it is empty. +If the shopping cart button is hidden without anything in it, the +functionality cannot be used until something is added to the cart.
  • +
+
+
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • Sygel
  • +
+
+
+

Contributors

+
    +
  • Sygel:
      +
    • Alberto Martínez
    • +
    • Valentin Vinagre
    • +
    • Harald Panten
    • +
    +
  • +
+
+
+

Maintainers

+

This module is maintained by the OCA.

+ +Odoo Community Association + +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

This module is part of the OCA/e-commerce project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+
+ + diff --git a/website_sale_cart_add_product_xlsx_csv/static/xlsx/import_example.xlsx b/website_sale_cart_add_product_xlsx_csv/static/xlsx/import_example.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..5bb8476702dd3914772491583c04de8ed1247fa3 GIT binary patch literal 5281 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 literal 0 HcmV?d00001 diff --git a/website_sale_cart_add_product_xlsx_csv/static/xlsx/import_unit_test.csv b/website_sale_cart_add_product_xlsx_csv/static/xlsx/import_unit_test.csv new file mode 100644 index 0000000000..9627408dca --- /dev/null +++ b/website_sale_cart_add_product_xlsx_csv/static/xlsx/import_unit_test.csv @@ -0,0 +1,7 @@ +default_code,product_uom_qty +E-COM12,2 +FURN_0097,1 +FURN_8900,1 +FURN_7800,-1 +FURN_9001,1 +Inexistent,1 diff --git a/website_sale_cart_add_product_xlsx_csv/static/xlsx/import_unit_test.error b/website_sale_cart_add_product_xlsx_csv/static/xlsx/import_unit_test.error new file mode 100644 index 0000000000..9627408dca --- /dev/null +++ b/website_sale_cart_add_product_xlsx_csv/static/xlsx/import_unit_test.error @@ -0,0 +1,7 @@ +default_code,product_uom_qty +E-COM12,2 +FURN_0097,1 +FURN_8900,1 +FURN_7800,-1 +FURN_9001,1 +Inexistent,1 diff --git a/website_sale_cart_add_product_xlsx_csv/static/xlsx/import_unit_test.xlsx b/website_sale_cart_add_product_xlsx_csv/static/xlsx/import_unit_test.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..58d358fa54eab101a78dd6daee81f9ed08c07012 GIT binary patch literal 5319 zcmaJ_2RK}N^WIh0>Rqm~N{A9AqHOdMqOGzz(W3WQOTy|UNCY9Gcj1!gL=RRcL`l@> zU9=!dqI@g&`+t1-fA`LLPI;blX3qJ|%z5XX(Nx98p#p$FAVBKv{Y9YD)DiLQKuqUFfSKa@vA-5AIS@5Irw%jdJtz zKYQ?cTFvF=v;c>yX@ss}1Xd%5rEh*)@0ptyzer!UUk5q#9^6%)8xgIcvj1UDwkH>b zj8Orv?!ii!y}4Tk7__ zK5HC{XP1gvj!!UnkaCH>R>C4`=#6-%v z+GWJU2m5$^4HO{)wn!9=%~wfnD}$QxwwcN^qx6&BWlBv|d{AhzQ1TYW3H?|Afac%2 zi4^n1V<-Mct_a5muC9)JkDZ;KYj?X$3XnA(^59H6^O~;Hy~5UyngvXe<##8=D$-a! zrRw@Nl6^i+ZvC2TLY_1hN;uPy5@>2oXN(HdK7itxI&XxhR@35MU zerS=YohB2ui-pu4Lx@aXv4&OklL~Wg$Pg(-wN2|~mpRpPhKA%9vqX#b*_u*rhV-T$ z_v%lWJx}=N<8KG=i8Abdjq6Z3l+Qm-xTwVF#+9W1Fl2{=?vTr0#x7TlTfTqf+x1y1 z|4!p!7MDu$nJPKH>e@kg2T|Xg(ev=^u5;?~cfsC^Nt+C;ntb1W1BCQihLkgR)NULa1(mj8*V@H0qec zsk2NLO6qGT9Amm776d?O8k+v2!R()=q1T1e&MD%kk^A_n%1^15ov z<-;I@GpviO$vDac2 zS{JjP=+h}G(6OHgCB%FC1Aknd{>T2$NP@uJ@jT=(oJ;>5>C7D|26~HdKANDMdxgZ> zh#>rXEQ&fD+}45_vye|tl_yKg z%?wIp(}ff03%L&o98&|RAdcGS#X9twI+BlrF|77NN` zvA9&M1J;w$Ru-OvhUa9Ghv%qu$M=I!%uye1dtYa`E2qyFk?H4Ckfh%gZr-pvI{;Lc ztqiQ+tMsPeuL?G=5#6tIyLGF7GV#e6wwn%xW5FwJy39Q3H!595=y_C9-InO*T8_`= zkB3-35r06HAi*g`^#e?DTx_+mAv3QiQ^{R8U9vRRmHAqr^FkHOZw*arMhXQVvW{>A z)7U#v24zu1>EHDk{;h?taxjh z)TDeu&^IvNZVgW2wej?OM`H7To9C_DV$=DeOLnFDE{donn;H$5{_~2YOq9=I*zwjK zzfsE*)=A{__dS)buA6G-$zx|eE!95wr_TmXbo|9DGROVWqI*1fqTKKmw)T92n(Cx! z8z?7FQ{8%VA-E|aJnT4zBc$ryAqzz~`;sSvu^o~_M+!st9l7HQmr@U)Ic9F&?rGm2 z=ktFnE>JfoHtO+;p7*DHiws?hUO=g^MUhjc z-aKK`I;%fQSY=*}>j4ci;mkVB*&5M`%4Wt!E-DeudJB60FKynk{c@Za^ z0{iR=YUE=)15r-lXYeuKQ%z3DjnKR@;v4&`}!Nobvv&2M7LKuTE$M3yJf5V zP~4PZ)I0G+1!AefXM9}m^HT$Kd&>p=Xu@8bLu5cT6%+LS{1#S~kCqytaw4a{o{rBn%W#*6Oa54M56`97vM!`?xGxk-@1r+G7Q5diERJj?RGJ zY$<0@{Y&VFivs9tnL{U3l@JWv@WQ_Io!l;2j}M91%L41 z%%P(^>#G#8jY;KZ*!75PUr;7|Jf z9rS7zE`3!qn#6ldZiO*ge{}(prGZzm_R$7%IM&H{;1+!Nk*o;DVd zQGUULN6DOZG>J~hqqQ;n3J;%;QEZiVF{ zCqAh{i#MSR=sL zzG#Ecvyqr@TZ~sp$y(Mbt9vfYXY2Eko}XcFDx{l88jLzf zgC_(^ozB|Y&Vd(Yb05_kLx%$ZfH0Nu@5$C5f1%4?wDc`2wQA0NFj*m`3iZeVopz0&t}q37%2ZSq8Th1ocvE$yD5 z#=z69&ADrOec98qcI?rm5Q;Yqlw$$3%KSzZdr(8Z2k01aliY3<^@7pvy5LPM{@z{X z;Z$HBwRVv)cBKoCX1zQ5ywq}(n8Yjxl_AhYOwfm5dU1OY9{pgJhhGqX-}!h+a!Hz% zag42}Bsc>u@`&KGnGMsnH=!%RWRa%d#>w@)-RdNTqLS$;pI?MRW9Qg=2(xbXf25&Q z|0Wc676@xAZ6w0p#r7Akh=0-I&?-Q7cl#8agJQiC)4rDaMhBPq>mQy+j|JyWw)*2em32bdM;iHAoE8boKWTPnIJtaYvO zUptVVu-jGi*LSin_qFG{hO-7nL!sjm2>ods-f_EQ+;fXWII?zyuXDiUNUC?Qa;&NG z(;LH$xudfQt}4Ti`6TpzmgTe>2we-U z?^t#YJt!#bdb6t2(!OoE$O`c6}e5*mtJ%p0MuB3Z}c>3MGlgp#yg zD{h9X^R^ddl_=grmM=P0>WG_o;-y+}W?|VAM+Jd0s%Vhb#Zs$@gx2gES}nS3GEwWn ztqR8V zmiZ-~bF!!01PS9rQ4a;J;F7BH)1D?X05NnS?sUT2smV&xA)c`r-yRm6rw}11@C9t| zN&LfMW{z90gX9=nFdQ)n5h^&Od|E3Sy_q+( zUAl?tp6lC{4UVYc?){^ct_4I^TaPsuS|iqWFAKdp>}xT}WHPTc6y*6-Aroh2Xhbp3 zs35RE&WE?_nY#*tCXNls<}cxssz0l6i-$%*cwFgr$ zby!P4@59o%CZByq{H|&Bh9aY!n zB?2npE%w0~`*McL`fQz4tB0ZSCex6k zP)byJ`$&MQTnXY%VS}h>2vjdHm&6g9TL-j#^^|Y)%WZlGIJT31d2QDJP)0;K-l&n~RDKt4R;fY_Po!)?dOnBo z@QmTie!n=I=BT22&X-gw(05A;0+gM< z_!9G`?vmCYyQxAh-z9ym&RK6(;dM;a&s@h(!gs92s4ml3a|8{#&jL zkbYOZ+9+QPQ7+{M=2gFqRDM^!+KgQE(wAa_>ANw?m!0+Rs#lrDMYnP(B6$CK@Biyv zez$V9DqpaYOL+ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from io import BytesIO + +from werkzeug.datastructures import FileStorage + +from odoo.tests.common import tagged +from odoo.tools.misc import file_path + +from odoo.addons.website.tools import MockRequest +from odoo.addons.website_sale.tests.test_website_sale_cart import WebsiteSaleCart +from odoo.addons.website_sale_cart_add_product_xlsx_csv.controllers.main import ( + WebsiteSaleAddProductXlsxCsv, +) + + +@tagged("post_install", "-at_install") +class TestWebsiteSaleCartAddProductXlsxCsv(WebsiteSaleCart): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.WebsiteSaleControllerAddProductXlsxCsv = WebsiteSaleAddProductXlsxCsv() + cls.file_route_csv = file_path( + "website_sale_cart_add_product_xlsx_csv/static/xlsx/import_unit_test.csv" + ) + cls.file_route_xlsx = file_path( + "website_sale_cart_add_product_xlsx_csv/static/xlsx/import_unit_test.xlsx" + ) + cls.error_file_route_csv = file_path( + "website_sale_cart_add_product_xlsx_csv/static/xlsx/import_unit_test.error" + ) + + def read_file(self, path): + with open(path, "rb") as f: + file = FileStorage(stream=BytesIO(f.read()), filename=path.split("/")[-1]) + return file + + def _test_import(self, file_route): + website = self.website.with_user(self.public_user) + with MockRequest(self.product.with_user(self.public_user).env, website=website): + sale_order = website.sale_get_order(force_create=True) + self.assertFalse(sale_order.order_line) + self.WebsiteSaleControllerAddProductXlsxCsv.cart( + cart_file=self.read_file(file_route) + ) + self.assertTrue(sale_order.order_line) + + def test_import_csv(self): + self._test_import(self.file_route_csv) + + def test_import_xlsx(self): + self._test_import(self.file_route_xlsx) + + def test_import_vals(self): + website = self.website.with_user(self.public_user) + with MockRequest(self.product.with_user(self.public_user).env, website=website): + sale_order = website.sale_get_order(force_create=True) + self.assertFalse(sale_order.order_line) + ( + import_status, + _, + failed_products, + ) = self.WebsiteSaleControllerAddProductXlsxCsv.import_file( + sale_order, self.read_file(self.file_route_csv) + ) + self.assertEqual(import_status, "warn") + product_to_fail = ["FURN_7800", "FURN_9001", "Inexistent"] + failed_products = "\n".join(failed_products) + for p in product_to_fail: + self.assertIn(p, failed_products) + + def test_import_error(self): + website = self.website.with_user(self.public_user) + with MockRequest(self.product.with_user(self.public_user).env, website=website): + sale_order = website.sale_get_order(force_create=True) + self.assertFalse(sale_order.order_line) + self.WebsiteSaleControllerAddProductXlsxCsv.cart( + cart_file=self.read_file(self.error_file_route_csv) + ) + self.assertFalse(sale_order.order_line) + + def test_import_error_vals(self): + website = self.website.with_user(self.public_user) + with MockRequest(self.product.with_user(self.public_user).env, website=website): + sale_order = website.sale_get_order(force_create=True) + self.assertFalse(sale_order.order_line) + ( + import_status, + _, + _, + ) = self.WebsiteSaleControllerAddProductXlsxCsv.import_file( + sale_order, self.read_file(self.error_file_route_csv) + ) + self.assertEqual(import_status, "error") diff --git a/website_sale_cart_add_product_xlsx_csv/views/cart_templates.xml b/website_sale_cart_add_product_xlsx_csv/views/cart_templates.xml new file mode 100644 index 0000000000..ecd08714e4 --- /dev/null +++ b/website_sale_cart_add_product_xlsx_csv/views/cart_templates.xml @@ -0,0 +1,89 @@ + + + + + + + diff --git a/website_sale_cart_add_product_xlsx_csv/views/res_config_settings.xml b/website_sale_cart_add_product_xlsx_csv/views/res_config_settings.xml new file mode 100644 index 0000000000..58290d87a4 --- /dev/null +++ b/website_sale_cart_add_product_xlsx_csv/views/res_config_settings.xml @@ -0,0 +1,28 @@ + + + + + res.config.settings.view.form.inherit.website.sale + res.config.settings + + + + + + + + + + + + + From c477fee14d0421f261152e51d76634b2f6645f4a Mon Sep 17 00:00:00 2001 From: oca-ci Date: Fri, 20 Mar 2026 12:17:38 +0000 Subject: [PATCH 2/3] [UPD] Update website_sale_cart_add_product_xlsx_csv.pot --- .../i18n/es.po | 11 +- ...website_sale_cart_add_product_xlsx_csv.pot | 155 ++++++++++++++++++ 2 files changed, 164 insertions(+), 2 deletions(-) create mode 100644 website_sale_cart_add_product_xlsx_csv/i18n/website_sale_cart_add_product_xlsx_csv.pot diff --git a/website_sale_cart_add_product_xlsx_csv/i18n/es.po b/website_sale_cart_add_product_xlsx_csv/i18n/es.po index 4a86296b8a..fadf1c9a68 100644 --- a/website_sale_cart_add_product_xlsx_csv/i18n/es.po +++ b/website_sale_cart_add_product_xlsx_csv/i18n/es.po @@ -20,8 +20,8 @@ msgstr "" #. module: website_sale_cart_add_product_xlsx_csv #: model_terms:ir.ui.view,arch_db:website_sale_cart_add_product_xlsx_csv.cart_lines_import msgid "" -"You can import the " -"cart with a xlsx/csv file" +"You can import the cart " +"with a xlsx/csv file" msgstr "" "Puedes importar el " "carrito con un archivo xlsx o csv" @@ -143,6 +143,13 @@ msgstr "El producto está archivado" msgid "The product was not found" msgstr "El producto no fue encontrado" +#. module: website_sale_cart_add_product_xlsx_csv +#. odoo-python +#: code:addons/website_sale_cart_add_product_xlsx_csv/controllers/main.py:0 +#, fuzzy, python-format +msgid "The quantity is not a number" +msgstr "La cantidad debe der un número positivo" + #. module: website_sale_cart_add_product_xlsx_csv #. odoo-python #: code:addons/website_sale_cart_add_product_xlsx_csv/controllers/main.py:0 diff --git a/website_sale_cart_add_product_xlsx_csv/i18n/website_sale_cart_add_product_xlsx_csv.pot b/website_sale_cart_add_product_xlsx_csv/i18n/website_sale_cart_add_product_xlsx_csv.pot new file mode 100644 index 0000000000..437fe206fc --- /dev/null +++ b/website_sale_cart_add_product_xlsx_csv/i18n/website_sale_cart_add_product_xlsx_csv.pot @@ -0,0 +1,155 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * website_sale_cart_add_product_xlsx_csv +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 17.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: website_sale_cart_add_product_xlsx_csv +#: model_terms:ir.ui.view,arch_db:website_sale_cart_add_product_xlsx_csv.cart_lines_import +msgid "" +"You can import the cart" +" with a xlsx/csv file" +msgstr "" + +#. module: website_sale_cart_add_product_xlsx_csv +#: model_terms:ir.ui.view,arch_db:website_sale_cart_add_product_xlsx_csv.cart_lines_import +msgid "Download example file" +msgstr "" + +#. module: website_sale_cart_add_product_xlsx_csv +#: model_terms:ir.ui.view,arch_db:website_sale_cart_add_product_xlsx_csv.res_config_settings_view_form +msgid "Cart Import Button" +msgstr "" + +#. module: website_sale_cart_add_product_xlsx_csv +#: model_terms:ir.ui.view,arch_db:website_sale_cart_add_product_xlsx_csv.res_config_settings_view_form +msgid "Cart Import Button File Size Limit (MB)" +msgstr "" + +#. module: website_sale_cart_add_product_xlsx_csv +#: model:ir.model.fields,field_description:website_sale_cart_add_product_xlsx_csv.field_res_config_settings__cart_import_button_file_limit +#: model:ir.model.fields,field_description:website_sale_cart_add_product_xlsx_csv.field_website__cart_import_button_file_limit +msgid "Cart import button file size limit (MB)" +msgstr "" + +#. module: website_sale_cart_add_product_xlsx_csv +#: model:ir.model,name:website_sale_cart_add_product_xlsx_csv.model_res_config_settings +msgid "Config Settings" +msgstr "" + +#. module: website_sale_cart_add_product_xlsx_csv +#: model_terms:ir.ui.view,arch_db:website_sale_cart_add_product_xlsx_csv.res_config_settings_view_form +msgid "Enable or disable the cart import button" +msgstr "" + +#. module: website_sale_cart_add_product_xlsx_csv +#: model_terms:ir.ui.view,arch_db:website_sale_cart_add_product_xlsx_csv.cart_lines_import +msgid "Import success" +msgstr "" + +#. module: website_sale_cart_add_product_xlsx_csv +#: model_terms:ir.ui.view,arch_db:website_sale_cart_add_product_xlsx_csv.cart_lines_import +msgid "Importation error." +msgstr "" + +#. module: website_sale_cart_add_product_xlsx_csv +#. odoo-python +#: code:addons/website_sale_cart_add_product_xlsx_csv/controllers/main.py:0 +#, python-format +msgid "Incorrect file format, it must me a .xlsx or a .csv" +msgstr "" + +#. module: website_sale_cart_add_product_xlsx_csv +#. odoo-python +#: code:addons/website_sale_cart_add_product_xlsx_csv/controllers/main.py:0 +#, python-format +msgid "" +"Incorrect file format, the columns should be 'default_code' and " +"'product_uom_qty'" +msgstr "" + +#. module: website_sale_cart_add_product_xlsx_csv +#: model:ir.model.fields,field_description:website_sale_cart_add_product_xlsx_csv.field_res_config_settings__cart_import_button +#: model:ir.model.fields,field_description:website_sale_cart_add_product_xlsx_csv.field_website__cart_import_button +msgid "Is the cart import button enabled?" +msgstr "" + +#. module: website_sale_cart_add_product_xlsx_csv +#: model_terms:ir.ui.view,arch_db:website_sale_cart_add_product_xlsx_csv.cart_lines_import +msgid "Partial import. The following products had errors:" +msgstr "" + +#. module: website_sale_cart_add_product_xlsx_csv +#. odoo-python +#: code:addons/website_sale_cart_add_product_xlsx_csv/controllers/main.py:0 +#, python-format +msgid "Product can not be sold" +msgstr "" + +#. module: website_sale_cart_add_product_xlsx_csv +#. odoo-python +#: code:addons/website_sale_cart_add_product_xlsx_csv/controllers/main.py:0 +#, python-format +msgid "Product is not published on the website" +msgstr "" + +#. module: website_sale_cart_add_product_xlsx_csv +#. odoo-python +#: code:addons/website_sale_cart_add_product_xlsx_csv/controllers/main.py:0 +#, python-format +msgid "Product max saleable qty is {}" +msgstr "" + +#. module: website_sale_cart_add_product_xlsx_csv +#. odoo-python +#: code:addons/website_sale_cart_add_product_xlsx_csv/controllers/main.py:0 +#, python-format +msgid "The file size is greater than the maximum allowed, {} MB" +msgstr "" + +#. module: website_sale_cart_add_product_xlsx_csv +#: model:ir.model.constraint,message:website_sale_cart_add_product_xlsx_csv.constraint_website_cart_import_button_file_limit_min +msgid "The file size limit must be positive" +msgstr "" + +#. module: website_sale_cart_add_product_xlsx_csv +#. odoo-python +#: code:addons/website_sale_cart_add_product_xlsx_csv/controllers/main.py:0 +#, python-format +msgid "The product is archived" +msgstr "" + +#. module: website_sale_cart_add_product_xlsx_csv +#. odoo-python +#: code:addons/website_sale_cart_add_product_xlsx_csv/controllers/main.py:0 +#, python-format +msgid "The product was not found" +msgstr "" + +#. module: website_sale_cart_add_product_xlsx_csv +#. odoo-python +#: code:addons/website_sale_cart_add_product_xlsx_csv/controllers/main.py:0 +#, python-format +msgid "The quantity is not a number" +msgstr "" + +#. module: website_sale_cart_add_product_xlsx_csv +#. odoo-python +#: code:addons/website_sale_cart_add_product_xlsx_csv/controllers/main.py:0 +#, python-format +msgid "The quantity should be a positive number" +msgstr "" + +#. module: website_sale_cart_add_product_xlsx_csv +#: model:ir.model,name:website_sale_cart_add_product_xlsx_csv.model_website +msgid "Website" +msgstr "" From d6d8cac18b3b792340f6605fd151fca3b873bacc Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Fri, 20 Mar 2026 12:25:14 +0000 Subject: [PATCH 3/3] [BOT] post-merge updates --- README.md | 1 + setup/_metapackage/pyproject.toml | 3 +- .../README.rst | 28 +++++++++---------- .../static/description/index.html | 2 +- 4 files changed, 18 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 542a1dec12..30b643cda1 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,7 @@ Available addons addon | version | maintainers | summary --- | --- | --- | --- [website_sale_b2x_alt_price](website_sale_b2x_alt_price/) | 17.0.1.0.0 | Yajo | Display prices with(out) taxes in eCommerce, complementing normal mode +[website_sale_cart_add_product_xlsx_csv](website_sale_cart_add_product_xlsx_csv/) | 17.0.1.0.0 | | Adds button to import xlsx or csv in website cart [website_sale_checkout_skip_payment](website_sale_checkout_skip_payment/) | 17.0.1.0.1 | | Skip payment for logged users in checkout process [website_sale_empty_cart](website_sale_empty_cart/) | 17.0.1.0.0 | | Adds a button in the website cart to empty all [website_sale_hide_empty_category](website_sale_hide_empty_category/) | 17.0.1.0.0 | | Hide any Product Categories that are empty diff --git a/setup/_metapackage/pyproject.toml b/setup/_metapackage/pyproject.toml index 60d4c5ca63..6e2efb33bd 100644 --- a/setup/_metapackage/pyproject.toml +++ b/setup/_metapackage/pyproject.toml @@ -1,8 +1,9 @@ [project] name = "odoo-addons-oca-e-commerce" -version = "17.0.20251124.0" +version = "17.0.20260320.0" dependencies = [ "odoo-addon-website_sale_b2x_alt_price>=17.0dev,<17.1dev", + "odoo-addon-website_sale_cart_add_product_xlsx_csv>=17.0dev,<17.1dev", "odoo-addon-website_sale_checkout_skip_payment>=17.0dev,<17.1dev", "odoo-addon-website_sale_empty_cart>=17.0dev,<17.1dev", "odoo-addon-website_sale_hide_empty_category>=17.0dev,<17.1dev", diff --git a/website_sale_cart_add_product_xlsx_csv/README.rst b/website_sale_cart_add_product_xlsx_csv/README.rst index bcae50e009..3de984e64b 100644 --- a/website_sale_cart_add_product_xlsx_csv/README.rst +++ b/website_sale_cart_add_product_xlsx_csv/README.rst @@ -11,7 +11,7 @@ Website Sale Cart Add Product Xlsx Csv !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:67f5bf0329604338a76994d610ad17d19826201b76ac05d7f91f2d2e27960b6e + !! source digest: sha256:79fce4d16c2c43bfb7623e87685ea7b9d1385305f4a70f4cf365bc2ccea0ebb8 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png @@ -48,11 +48,11 @@ Configuration To configure this module, you need to: -- To enable the cart import button, go to Website / Configuration / - Settings. Then search the "Cart Import Button" and set its value. -- To edit the maximum file size, go to Website / Configuration / - Settings. Then search the "Cart import button file size limit" and - edit its value. +- To enable the cart import button, go to Website / Configuration / + Settings. Then search the "Cart Import Button" and set its value. +- To edit the maximum file size, go to Website / Configuration / + Settings. Then search the "Cart import button file size limit" and + edit its value. Usage ===== @@ -74,10 +74,10 @@ To use this module, you need to: Known issues / Roadmap ====================== -- Despithe the fact that the cart button is enabled by default, some - Odoo instances have the website configured to hide it if it is empty. - If the shopping cart button is hidden without anything in it, the - functionality cannot be used until something is added to the cart. +- Despithe the fact that the cart button is enabled by default, some + Odoo instances have the website configured to hide it if it is empty. + If the shopping cart button is hidden without anything in it, the + functionality cannot be used until something is added to the cart. Bug Tracker =========== @@ -100,11 +100,11 @@ Authors Contributors ------------ -- `Sygel `__: +- `Sygel `__: - - Alberto Martínez - - Valentin Vinagre - - Harald Panten + - Alberto Martínez + - Valentin Vinagre + - Harald Panten Maintainers ----------- diff --git a/website_sale_cart_add_product_xlsx_csv/static/description/index.html b/website_sale_cart_add_product_xlsx_csv/static/description/index.html index f38e9d07b1..f26610ac87 100644 --- a/website_sale_cart_add_product_xlsx_csv/static/description/index.html +++ b/website_sale_cart_add_product_xlsx_csv/static/description/index.html @@ -372,7 +372,7 @@

Website Sale Cart Add Product Xlsx Csv

!! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -!! source digest: sha256:67f5bf0329604338a76994d610ad17d19826201b76ac05d7f91f2d2e27960b6e +!! source digest: sha256:79fce4d16c2c43bfb7623e87685ea7b9d1385305f4a70f4cf365bc2ccea0ebb8 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->

Beta License: AGPL-3 OCA/e-commerce Translate me on Weblate Try me on Runboat

This module adds a button in the website cart that let users import a