Skip to content

Commit

Permalink
[FIX+IMP] connector_prestashop: Several things
Browse files Browse the repository at this point in the history
* [FIX] Fix export when no location has flag prestashop_synchronized

  When there is no location with the flag prestashop_synchronized in the
  location tree,

  Current behavior:

  The `location` key in the context is empty then the qty_available is
  computed for *every* locations/warehouses.

  Expected behavior:

  If there is at least one location flagged, use it, otherwise, use all
  the locations of the tree, starting from the selected location or
  selected warehouse location.

  When no location can be found (for instance because user selected a
  location with a usage different than 'internal'), then it should just
  fail and not return the stock of all warehouses.

  Being able to synchronize without activating 'prestashop_synchronized'
  is important: when used, this feature will trigger an export every time
  a quant is changed or created, on a large catalog, we might prefer only
  using the cron to have less frequent updates and less jobs.

  A second fix is that when a stock_location_id is set on the backend, it
  should be used, it was only used for the import of stock.

* [FIX] Exclude children from qty computation

  We already pass the children in 'location', if we don't disable
  'compute_child', the qty computation will try to get the children of
  each child and generates query of 1mio chars.

* [IMP] Group computation of qty_available

  Stats with 6700 products:

  Before: 570s
  After: 28s

* [FIX] Apply filter on locations for variants quantities

  It was only applied on export of template quantities.

* [IMP] Improve performance on prestashop qty recompute

  The add/union operation between recordsets is slow, aggregate the ids in
  a set and call the browse only once on the complete set is dramatically
  faster. See guewen/connector-magento#9
  • Loading branch information
guewen authored and flachica committed Aug 17, 2022
1 parent 11df186 commit d91ff02
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 45 deletions.
26 changes: 26 additions & 0 deletions connector_prestashop/models/prestashop_backend/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,32 @@ def import_record(self, model_name, ext_id):
import_record(session, model_name, self.id, ext_id)
return True

@api.multi
def _get_locations_for_stock_quantities(self):
root_location = (self.stock_location_id or
self.warehouse_id.lot_stock_id)
locations = self.env['stock.location'].search([
('id', 'child_of', root_location.id),
('prestashop_synchronized', '=', True),
('usage', '=', 'internal'),
])
# if we choosed a location but none where flagged
# 'prestashop_synchronized', consider we want all of them in the tree
if not locations:
locations = self.env['stock.location'].search([
('id', 'child_of', root_location.id),
('usage', '=', 'internal'),
])
if not locations:
# we must not pass an empty location or we would have the
# stock for every warehouse, which is the last thing we
# expect
raise exceptions.UserError(
_('No internal location found to compute the product '
'quantity.')
)
return locations


class PrestashopShopGroup(models.Model):
_name = 'prestashop.shop.group'
Expand Down
29 changes: 23 additions & 6 deletions connector_prestashop/models/product_product/common.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# -*- coding: utf-8 -*-
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from collections import defaultdict

from odoo import api, fields, models
from odoo.addons import decimal_precision as dp

Expand Down Expand Up @@ -152,14 +154,29 @@ class PrestashopProductCombination(models.Model):

@api.multi
def recompute_prestashop_qty(self):
for product_binding in self:
if product_binding.quantity != product_binding.qty_available:
product_binding.quantity = product_binding.qty_available
# group products by backend
backends = defaultdict(set)
for product in self:
backends[product.backend_id].add(product.id)

for backend, product_ids in backends.iteritems():
products = self.browse(product_ids)
products._recompute_prestashop_qty_backend(backend)
return True

@api.model
def _prestashop_qty(self, product):
return product.qty_available
@api.multi
def _recompute_prestashop_qty_backend(self, backend):
locations = backend._get_locations_for_stock_quantities()
self_loc = self.with_context(location=locations.ids,
compute_child=False)
for product_binding in self_loc:
new_qty = product_binding._prestashop_qty()
if product_binding.quantity != new_qty:
product_binding.quantity = new_qty
return True

def _prestashop_qty(self):
return self.qty_available

@job(default_channel='root.prestashop')
def export_inventory(self, backend, fields=None, **kwargs):
Expand Down
61 changes: 22 additions & 39 deletions connector_prestashop/models/product_template/common.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# -*- coding: utf-8 -*-
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)

from odoo import api, fields, models
from collections import defaultdict

from odoo import _, api, exceptions, fields, models
from odoo.addons import decimal_precision as dp

from odoo.addons.queue_job.job import job
Expand Down Expand Up @@ -113,48 +115,29 @@ class PrestashopProductTemplate(models.Model):

@api.multi
def recompute_prestashop_qty(self):
for product_binding in self:
new_qty = product_binding._prestashop_qty()
if product_binding.quantity != new_qty:
product_binding.quantity = new_qty
# group products by backend
backends = defaultdict(set)
for product in self:
backends[product.backend_id].add(product.id)

for backend, product_ids in backends.iteritems():
products = self.browse(product_ids)
products._recompute_prestashop_qty_backend(backend)
return True

def _prestashop_qty(self):
locations = self.env['stock.location'].search([
('id', 'child_of', self.backend_id.warehouse_id.lot_stock_id.id),
('prestashop_synchronized', '=', True),
('usage', '=', 'internal'),
])
return self.with_context(location=locations.ids).qty_available

@job(default_channel='root.prestashop')
def import_products(self, backend, since_date=None, **kwargs):
filters = None
if since_date:
filters = {'date': '1', 'filter[date_upd]': '>[%s]' % (since_date)}
now_fmt = fields.Datetime.now()
self.env['prestashop.product.category'].with_delay(
priority=15
).import_batch(backend=backend, filters=filters, **kwargs)
self.env['prestashop.product.template'].with_delay(
priority=15
).import_batch(backend, filters, **kwargs)
backend.import_products_since = now_fmt
@api.multi
def _recompute_prestashop_qty_backend(self, backend):
locations = backend._get_locations_for_stock_quantities()
self_loc = self.with_context(location=locations.ids,
compute_child=False)
for product in self_loc:
new_qty = product._prestashop_qty()
if product.quantity != new_qty:
product.quantity = new_qty
return True

@job(default_channel='root.prestashop')
def export_inventory(self, backend, fields=None, **kwargs):
""" Export the inventory configuration and quantity of a product. """
env = backend.get_environment(self._name)
inventory_exporter = env.get_connector_unit(ProductInventoryExporter)
return inventory_exporter.run(self.id, fields, **kwargs)

@api.model
@job(default_channel='root.prestashop')
def export_product_quantities(self, backend):
self.search([
('backend_id', 'in', self.env.backend.ids),
]).recompute_prestashop_qty()
def _prestashop_qty(self):
return self.qty_available


@prestashop
Expand Down

0 comments on commit d91ff02

Please sign in to comment.