Skip to content

Commit

Permalink
[IMP] product_import: import products by batch
Browse files Browse the repository at this point in the history
  • Loading branch information
florentx committed Jan 27, 2025
1 parent 33bbb3a commit 348cbad
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 11 deletions.
4 changes: 2 additions & 2 deletions product_import/data/job_function.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
<field name="parent_id" ref="queue_job.channel_root" />
</record>

<record id="job_create_update_product" model="queue.job.function">
<record id="job_create_update_products" model="queue.job.function">
<field name="model_id" ref="model_product_import" />
<field name="method">_create_update_product</field>
<field name="method">_create_update_products</field>
<field name="channel_id" ref="channel_product_import" />
</record>

Expand Down
45 changes: 36 additions & 9 deletions product_import/wizard/product_import.py
Original file line number Diff line number Diff line change
Expand Up @@ -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__)


Expand Down Expand Up @@ -197,17 +200,33 @@ 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:
product.write(product_vals)
Expand All @@ -222,22 +241,30 @@ def _create_update_product(self, parsed_product, seller_id):
product.action_archive()
logger.debug("Product %s created", product.default_code)

# Archive product template, if product is archived
if product.active != product.product_tmpl_id.active:
product.product_tmpl_id.toggle_active()

Check warning on line 246 in product_import/wizard/product_import.py

View check run for this annotation

Codecov / codecov/patch

product_import/wizard/product_import.py#L246

Added line #L246 was not covered by tests
log_msg = f"Product created/updated {product.id}\n" + "\n".join(chatter_msg)
return log_msg

def import_button(self):
def import_button(self, chunk_size=CHUNK_SIZE):
self.ensure_one()
file_content = b64decode(self.product_file)
# 1st step: Parse the (UBL) document --> get a "catalogue" dictionary
catalogue = self.parse_product_catalogue(file_content, self.product_filename)
if not catalogue.get("products"):
raise UserError(_("This catalogue doesn't have any product!"))
company_id = self._get_company_id(catalogue)
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)
# 2nd step: Prepare values and create the "product.product" records in Odoo
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
Expand Down

0 comments on commit 348cbad

Please sign in to comment.