From d8c35a9b459d328b01038fdeed9fb38c6a51a7fc Mon Sep 17 00:00:00 2001 From: Florent Xicluna Date: Mon, 9 Dec 2024 08:56:06 +0100 Subject: [PATCH] [IMP] product_import: import products by batch --- product_import/data/job_function.xml | 4 +-- product_import/wizard/product_import.py | 45 ++++++++++++++++++++----- 2 files changed, 39 insertions(+), 10 deletions(-) diff --git a/product_import/data/job_function.xml b/product_import/data/job_function.xml index f41529062d..c1f59aa69a 100644 --- a/product_import/data/job_function.xml +++ b/product_import/data/job_function.xml @@ -5,9 +5,9 @@ - + - _create_update_product + _create_update_products diff --git a/product_import/wizard/product_import.py b/product_import/wizard/product_import.py index cd18533aa4..f1389039ba 100644 --- a/product_import/wizard/product_import.py +++ b/product_import/wizard/product_import.py @@ -4,12 +4,15 @@ import logging from base64 import b64decode, b64encode from datetime import date, timedelta +from itertools import zip_longest from lxml import etree from odoo import _, api, fields, models from odoo.exceptions import UserError +CHUNK_SIZE = 40 + logger = logging.getLogger(__name__) @@ -195,19 +198,42 @@ def _prepare_product(self, parsed_product, chatter_msg, seller=None): return product_vals @api.model - def _create_update_product(self, parsed_product, seller_id): + def _create_update_products(self, products, seller_id): """Create / Update a product. This method is called from a queue job. """ - chatter_msg = [] seller = self.env["res.partner"].browse(seller_id) - product_vals = self._prepare_product(parsed_product, chatter_msg, seller=seller) - if not product_vals: - return False + + log_msgs = [] + for parsed_product in products: + product_vals = self._prepare_product(parsed_product, log_msgs, seller=seller) + if product_vals: + msg = self._create_update_product(product_vals) + log_msgs.append(msg) + + return "\n".join(log_msgs) + + @api.model + def _create_update_product(self, product_vals): + """Create / Update a product. + + This method is called from a queue job. + """ + chatter_msg = [] + product = product_vals.pop("recordset", None) if product: + supplierinfo = product_vals.pop("seller_ids", ()) + supplierinfo_obj = self.env["product.supplierinfo"] + for (command, line_id, values) in supplierinfo: + if command == 1: + supplierinfo_obj.browse(line_id).write(values) + elif command == 0: + supplierinfo_obj.create({**values, "product_id": product.id}) + else: + raise RuntimeError(f"Command {command} not supported") product.write(product_vals) logger.debug("Product %s updated", product.default_code) else: @@ -233,9 +259,12 @@ def import_button(self): seller = self._get_seller(catalogue) wiz = self.with_context(product_company_id=company_id) # Create products asynchronously - for product_vals in catalogue["products"]: - # One job per product - wiz.with_delay()._create_update_product(product_vals, seller.id) + iterators = [iter(catalogue["products"])] * chunk_size + for products in zip_longest(*iterators): + if products[-1] is None: + products = [product for product in products if product] + # One job for x products (chunk of 40) + wiz.with_delay()._create_update_products(products, seller.id) # Save imported file as attachment self._bdimport.post_create_or_update( catalogue, seller, doc_filename=self.product_filename