Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update of Magento stock quantity: reduced the memory footprint and improved #1

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 71 additions & 14 deletions magentoerpconnect/product.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import base64
import xmlrpclib
import sys
from collections import defaultdict
from openerp.osv import orm, fields
from openerp.tools.translate import _
from openerp.addons.connector.queue.job import job, related_action
Expand Down Expand Up @@ -54,6 +55,11 @@
_logger = logging.getLogger(__name__)


def chunks(items, length):
for index in xrange(0, len(items), length):
yield items[index:index + length]


class magento_product_product(orm.Model):
_name = 'magento.product.product'
_inherit = 'magento.binding'
Expand Down Expand Up @@ -123,35 +129,86 @@ def _product_type_get(self, cr, uid, context=None):
"A product with the same ID on Magento already exists")
]

RECOMPUTE_QTY_STEP = 1000 # products at a time

def recompute_magento_qty(self, cr, uid, ids, context=None):
""" Check if the quantity in the stock location configured
on the backend has changed since the last export.

If it has changed, write the updated quantity on `magento_qty`.
The write on `magento_qty` will trigger an `on_record_write`
event that will create an export job.

It groups the products by backend to avoid to read the backend
informations for each product.
"""
if not hasattr(ids, '__iter__'):
ids = [ids]

for product in self.browse(cr, uid, ids, context=context):
new_qty = self._magento_qty(cr, uid, product, context=context)
if new_qty != product.magento_qty:
self.write(cr, uid, product.id,
{'magento_qty': new_qty},
context=context)
# group products by backend
backends = defaultdict(list)
for product in self.read(cr, uid, ids, ['backend_id', 'magento_qty'],
context=context):
backends[product['backend_id'][0]].append(product)

for backend_id, products in backends.iteritems():
backend_obj = self.pool['magento.backend']
backend = backend_obj.browse(cr, uid, backend_id, context=context)
self._recompute_magento_qty_backend(cr, uid, backend, products,
context=context)
return True

def _magento_qty(self, cr, uid, product, context=None):
def _recompute_magento_qty_backend(self, cr, uid, backend, products,
read_fields=None, context=None):
""" Recompute the products quantity for one backend.

If field names are passed in ``read_fields`` (as a list), they
will be read in the product that is used in
:meth:`~._magento_qty`.

"""
if context is None:
context = {}
backend = product.backend_id
stock = backend.warehouse_id.lot_stock_id

if backend.product_stock_field_id:
stock_field = backend.product_stock_field_id.name
else:
stock_field = 'virtual_available'

location = backend.warehouse_id.lot_stock_id
location_ctx = context.copy()
location_ctx['location'] = stock.id
product_stk = self.read(cr, uid, product.id,
[stock_field],
context=location_ctx)
return product_stk[stock_field]
location_ctx['location'] = location.id

product_fields = ['magento_qty', stock_field]
if read_fields:
product_fields += read_fields

product_ids = [product['id'] for product in products]
for chunk_ids in chunks(product_ids, self.RECOMPUTE_QTY_STEP):
for product in self.read(cr, uid, chunk_ids, product_fields,
context=location_ctx):
new_qty = self._magento_qty(cr, uid, product,
backend,
location,
stock_field,
context=location_ctx)
if new_qty != product['magento_qty']:
self.write(cr, uid, product['id'],
{'magento_qty': new_qty},
context=context)

def _magento_qty(self, cr, uid, product, backend, location,
stock_field, context=None):
""" Return the current quantity for one product.

Can be inherited to change the way the quantity is computed,
according to a backend / location.

If you need to read additional fields on the product, see the
``read_fields`` argument of :meth:`~._recompute_magento_qty_backend`

"""
return product[stock_field]


class product_product(orm.Model):
Expand Down