[FIX] procurement, stock: forward port of bug fix 3609ba10f2

This commit is contained in:
Denis Ledoux 2014-08-13 12:00:38 +02:00
parent fe83c11301
commit ca55a24374
2 changed files with 84 additions and 45 deletions

View File

@ -20,6 +20,7 @@
##############################################################################
import time
from psycopg2 import OperationalError
from openerp import SUPERUSER_ID
from openerp.osv import fields, osv
@ -193,31 +194,49 @@ class procurement_order(osv.osv):
def reset_to_confirmed(self, cr, uid, ids, context=None):
return self.write(cr, uid, ids, {'state': 'confirmed'}, context=context)
def run(self, cr, uid, ids, context=None):
def run(self, cr, uid, ids, autocommit=False, context=None):
for procurement_id in ids:
#we intentionnaly do the browse under the for loop to avoid caching all ids which would be ressource greedy
#and useless as we'll make a refresh later that will invalidate all the cache (and thus the next iteration
#will fetch all the ids again)
procurement = self.browse(cr, uid, procurement_id, context=context)
if procurement.state not in ("running", "done"):
if self._assign(cr, uid, procurement, context=context):
procurement.refresh()
res = self._run(cr, uid, procurement, context=context or {})
if res:
self.write(cr, uid, [procurement.id], {'state': 'running'}, context=context)
try:
if self._assign(cr, uid, procurement, context=context):
procurement.refresh()
res = self._run(cr, uid, procurement, context=context or {})
if res:
self.write(cr, uid, [procurement.id], {'state': 'running'}, context=context)
else:
self.write(cr, uid, [procurement.id], {'state': 'exception'}, context=context)
else:
self.message_post(cr, uid, [procurement.id], body=_('No rule matching this procurement'), context=context)
self.write(cr, uid, [procurement.id], {'state': 'exception'}, context=context)
else:
self.message_post(cr, uid, [procurement.id], body=_('No rule matching this procurement'), context=context)
self.write(cr, uid, [procurement.id], {'state': 'exception'}, context=context)
if autocommit:
cr.commit()
except OperationalError:
if autocommit:
cr.rollback()
continue
else:
raise
return True
def check(self, cr, uid, ids, context=None):
def check(self, cr, uid, ids, autocommit=False, context=None):
done_ids = []
for procurement in self.browse(cr, uid, ids, context=context):
result = self._check(cr, uid, procurement, context=context)
if result:
done_ids.append(procurement.id)
try:
result = self._check(cr, uid, procurement, context=context)
if result:
done_ids.append(procurement.id)
if autocommit:
cr.commit()
except OperationalError:
if autocommit:
cr.rollback()
continue
else:
raise
if done_ids:
self.write(cr, uid, done_ids, {'state': 'done'}, context=context)
return done_ids
@ -288,22 +307,26 @@ class procurement_order(osv.osv):
cr = openerp.registry(cr.dbname).cursor()
# Run confirmed procurements
prev_ids = []
while True:
ids = self.search(cr, SUPERUSER_ID, [('state', '=', 'confirmed')], context=context)
if not ids:
if not ids or prev_ids == ids:
break
self.run(cr, SUPERUSER_ID, ids, context=context)
else:
prev_ids = ids
self.run(cr, SUPERUSER_ID, ids, autocommit=use_new_cursor, context=context)
if use_new_cursor:
cr.commit()
# Check if running procurements are done
offset = 0
prev_ids = []
while True:
ids = self.search(cr, SUPERUSER_ID, [('state', '=', 'running')], offset=offset, context=context)
if not ids:
ids = self.search(cr, SUPERUSER_ID, [('state', '=', 'running')], context=context)
if not ids or prev_ids == ids:
break
done = self.check(cr, SUPERUSER_ID, ids, context=context)
offset += len(ids) - len(done)
else:
prev_ids = ids
self.check(cr, SUPERUSER_ID, ids, autocommit=use_new_cursor, context=context)
if use_new_cursor:
cr.commit()

View File

@ -26,6 +26,7 @@ from openerp.tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FO
from openerp import SUPERUSER_ID
from dateutil.relativedelta import relativedelta
from datetime import datetime
from psycopg2 import OperationalError
import openerp
class procurement_group(osv.osv):
@ -204,8 +205,8 @@ class procurement_order(osv.osv):
return True
return super(procurement_order, self)._run(cr, uid, procurement, context=context)
def run(self, cr, uid, ids, context=None):
res = super(procurement_order, self).run(cr, uid, ids, context=context)
def run(self, cr, uid, ids, autocommit=False, context=None):
res = super(procurement_order, self).run(cr, uid, ids, autocommit=autocommit, context=context)
#after all the procurements are run, check if some created a draft stock move that needs to be confirmed
#(we do that in batch because it fasts the picking assignation and the picking state computation)
move_to_confirm_ids = []
@ -345,35 +346,50 @@ class procurement_order(osv.osv):
orderpoint_obj = self.pool.get('stock.warehouse.orderpoint')
procurement_obj = self.pool.get('procurement.order')
offset = 0
ids = [1]
while ids:
ids = orderpoint_obj.search(cr, uid, [('company_id', '=', company_id)], offset=offset, limit=100)
orderpoint_ids = orderpoint_obj.search(cr, uid, [('company_id', '=', company_id)])
prev_ids = []
while orderpoint_ids:
ids = orderpoint_ids[:100]
del orderpoint_ids[:100]
for op in orderpoint_obj.browse(cr, uid, ids, context=context):
prods = self._product_virtual_get(cr, uid, op)
if prods is None:
continue
if prods < op.product_min_qty:
qty = max(op.product_min_qty, op.product_max_qty) - prods
reste = qty % op.qty_multiple
if reste > 0:
qty += op.qty_multiple - reste
if qty <= 0:
try:
prods = self._product_virtual_get(cr, uid, op)
if prods is None:
continue
if prods < op.product_min_qty:
qty = max(op.product_min_qty, op.product_max_qty) - prods
qty -= orderpoint_obj.subtract_procurements(cr, uid, op, context=context)
reste = qty % op.qty_multiple
if reste > 0:
qty += op.qty_multiple - reste
if qty > 0:
proc_id = procurement_obj.create(cr, uid,
self._prepare_orderpoint_procurement(cr, uid, op, qty, context=context),
context=context)
self.check(cr, uid, [proc_id])
self.run(cr, uid, [proc_id])
offset += len(ids)
if qty <= 0:
continue
qty -= orderpoint_obj.subtract_procurements(cr, uid, op, context=context)
if qty > 0:
proc_id = procurement_obj.create(cr, uid,
self._prepare_orderpoint_procurement(cr, uid, op, qty, context=context),
context=context)
self.check(cr, uid, [proc_id])
self.run(cr, uid, [proc_id])
if use_new_cursor:
cr.commit()
except OperationalError:
if use_new_cursor:
orderpoint_ids.append(op.id)
cr.rollback()
continue
else:
raise
if use_new_cursor:
cr.commit()
if prev_ids == ids:
break
else:
prev_ids = ids
if use_new_cursor:
cr.commit()
cr.close()