trytond-patches/issue6626_improve_performan...

177 lines
6.6 KiB
Diff

# TODO: Remove on version 4.6
# http://hg.tryton.org/modules/stock/rev/9b49590277df
diff -r 99021dd6717a move.py
--- a/trytond/trytond/modules/stock/move.py Wed Oct 25 09:54:30 2017 +0200
+++ b/trytond/trytond/modules/stock/move.py Wed Oct 25 16:43:23 2017 +0200
@@ -1,3 +1,4 @@
+
#This file is part of Tryton. The COPYRIGHT file at the top level of
#this repository contains the full copyright notices and license terms.
import datetime
@@ -540,29 +541,21 @@
Uom = pool.get('product.uom')
Product = pool.get('product.product')
ProductTemplate = pool.get('product.template')
- Location = pool.get('stock.location')
Currency = pool.get('currency.currency')
- Date = pool.get('ir.date')
if direction == 'in':
quantity = self.quantity
elif direction == 'out':
quantity = -self.quantity
- context = {}
- locations = Location.search([
- ('type', '=', 'storage'),
- ])
- context['locations'] = [l.id for l in locations]
- context['stock_date_end'] = Date.today()
- with Transaction().set_context(context):
- product = Product(self.product.id)
- qty = Uom.compute_qty(self.uom, quantity, product.default_uom)
+
+ qty = Uom.compute_qty(self.uom, quantity, self.product.default_uom)
qty = Decimal(str(qty))
if hasattr(Product, 'cost_price'):
- product_qty = product.quantity
+ product_qty = self.product.quantity
else:
- product_qty = product.template.quantity
+ product_qty = self.product.template.quantity
+
product_qty = Decimal(str(max(product_qty, 0)))
# convert wrt currency
with Transaction().set_context(date=self.effective_date):
@@ -570,26 +563,45 @@
self.company.currency, round=False)
# convert wrt to the uom
unit_price = Uom.compute_price(self.uom, unit_price,
- product.default_uom)
+ self.product.default_uom)
+
+ cost_price = self.product.cost_price
if product_qty + qty != Decimal('0.0'):
new_cost_price = (
- (product.cost_price * product_qty) + (unit_price * qty)
+ (cost_price * product_qty) + (unit_price * qty)
) / (product_qty + qty)
else:
- new_cost_price = product.cost_price
+ new_cost_price = cost_price
if hasattr(Product, 'cost_price'):
digits = Product.cost_price.digits
- write = partial(Product.write, [product])
else:
digits = ProductTemplate.cost_price.digits
- write = partial(ProductTemplate.write, [product.template])
+
new_cost_price = new_cost_price.quantize(
Decimal(str(10.0 ** -digits[1])))
- write({
- 'cost_price': new_cost_price,
- })
+ return new_cost_price
+
+ def _cost_price_key(self):
+ return (
+ ('company', self.company.id),
+ )
+
+ @classmethod
+ def _cost_price_context(cls, moves):
+ pool = Pool()
+ Location = pool.get('stock.location')
+ Date = pool.get('ir.date')
+ context = {}
+ locations = Location.search([
+ ('type', '=', 'storage'),
+ ])
+ context['with_childs'] = False
+ context['locations'] = [l.id for l in locations]
+ context['stock_date_end'] = Date.today()
+
+ return context
@staticmethod
def _get_internal_quantity(quantity, uom, product):
@@ -625,28 +637,64 @@
@ModelView.button
@Workflow.transition('done')
def do(cls, moves):
+ pool = Pool()
+ Product = pool.get('product.template')
+
+ def set_cost_values(cost_values):
+ values = []
+ for product, cost_price in cost_values:
+ values.extend(([product.template], {'cost_price': cost_price}))
+
+ if values:
+ Product.write(*values)
+
cls.check_origin(moves)
- to_write = []
- for move in moves:
- move.set_effective_date()
- move._do()
- to_write.extend(([move], move._save_values))
- if to_write:
- cls.write(*to_write)
+ for key, grouped_moves in groupby(moves, key=cls._cost_price_key):
+ to_save = []
+ cost_values = []
+ products = set()
+ grouped_moves = list(grouped_moves)
+ context = dict(key)
+ context.update(cls._cost_price_context(grouped_moves))
+ with Transaction().set_context(context):
+ grouped_moves = cls.browse(grouped_moves)
+ for move in grouped_moves:
+ if move.product in products:
+ # The average computation of product cost price
+ # requires each previous move of the same product to be
+ # saved
+ cls.write(*to_save)
+ set_cost_values(cost_values)
+ del to_save[:]
+ del cost_values[:]
+ products.clear()
+ move.set_effective_date()
+ cost_price = move._do()
+ if cost_price is not None:
+ cost_values.append(
+ (move.product, cost_price))
+ if move.cost_price is None:
+ if cost_price is None:
+ cost_price = move.product.cost_price
+ move.cost_price = cost_price
+ to_save.extend(([move], move._save_values))
+ products.add(move.product)
+ if to_save:
+ cls.write(*to_save)
+ if cost_values:
+ set_cost_values(cost_values)
def _do(self):
if (self.from_location.type in ('supplier', 'production')
and self.to_location.type == 'storage'
and self.product.cost_price_method == 'average'):
- self._update_product_cost_price('in')
+ return self._update_product_cost_price('in')
elif (self.to_location.type == 'supplier'
and self.from_location.type == 'storage'
and self.product.cost_price_method == 'average'):
- self._update_product_cost_price('out')
- if self.cost_price is None:
- self.cost_price = self.product.cost_price
+ return self._update_product_cost_price('out')
@classmethod
@ModelView.button