[FIX] procurement: refactor scheduler so it continues even if a procurement failed

If the mrp scheduler fails during the treatment of a procurement (due to a postgresql error, like an update lock), we let it try the other procurements, instead of stopping at the first procurement which fails.
Besides, we retry to treat the procurements which failed, until the list of the remaining procurements is always the same (meaning something is wrong and block the procurements treatment).
This commit is contained in:
Denis Ledoux 2014-08-12 11:02:15 +02:00
parent 3632949cff
commit 3609ba10f2
1 changed files with 86 additions and 82 deletions

View File

@ -28,6 +28,7 @@ from openerp.osv import fields
from openerp.tools.translate import _ from openerp.tools.translate import _
from openerp.tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FORMAT from openerp.tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FORMAT
from openerp import tools from openerp import tools
from psycopg2 import OperationalError
class procurement_order(osv.osv): class procurement_order(osv.osv):
_inherit = 'procurement.order' _inherit = 'procurement.order'
@ -70,56 +71,45 @@ class procurement_order(osv.osv):
cr.commit() cr.commit()
company = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id company = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id
maxdate = (datetime.today() + relativedelta(days=company.schedule_range)).strftime(tools.DEFAULT_SERVER_DATE_FORMAT) maxdate = (datetime.today() + relativedelta(days=company.schedule_range)).strftime(tools.DEFAULT_SERVER_DATE_FORMAT)
start_date = fields.datetime.now() prev_ids = []
offset = 0
report = []
report_total = 0
report_except = 0
report_later = 0
while True: while True:
ids = procurement_obj.search(cr, uid, [('state', '=', 'confirmed'), ('procure_method', '=', 'make_to_order')], offset=offset, limit=500, order='priority, date_planned', context=context) ids = procurement_obj.search(cr, uid, [('state', '=', 'confirmed'), ('procure_method', '=', 'make_to_order'), ('date_planned', '<', maxdate)], limit=500, order='priority, date_planned', context=context)
for proc in procurement_obj.browse(cr, uid, ids, context=context): for proc in procurement_obj.browse(cr, uid, ids, context=context):
if maxdate >= proc.date_planned: try:
wf_service.trg_validate(uid, 'procurement.order', proc.id, 'button_check', cr) wf_service.trg_validate(uid, 'procurement.order', proc.id, 'button_check', cr)
else:
offset += 1
report_later += 1
if proc.state == 'exception': if use_new_cursor:
report.append(_('PROC %d: on order - %3.2f %-5s - %s') % \ cr.commit()
(proc.id, proc.product_qty, proc.product_uom.name, except OperationalError:
proc.product_id.name)) if use_new_cursor:
report_except += 1 cr.rollback()
report_total += 1 continue
if use_new_cursor: else:
cr.commit() raise
if not ids: if not ids or prev_ids == ids:
break break
offset = 0 else:
prev_ids = ids
ids = [] ids = []
prev_ids = []
while True: while True:
report_ids = [] ids = procurement_obj.search(cr, uid, [('state', '=', 'confirmed'), ('procure_method', '=', 'make_to_stock'), ('date_planned', '<', maxdate)], limit=500)
ids = procurement_obj.search(cr, uid, [('state', '=', 'confirmed'), ('procure_method', '=', 'make_to_stock')], offset=offset)
for proc in procurement_obj.browse(cr, uid, ids): for proc in procurement_obj.browse(cr, uid, ids):
if maxdate >= proc.date_planned: try:
wf_service.trg_validate(uid, 'procurement.order', proc.id, 'button_check', cr) wf_service.trg_validate(uid, 'procurement.order', proc.id, 'button_check', cr)
report_ids.append(proc.id)
else:
report_later += 1
report_total += 1
if proc.state == 'exception': if use_new_cursor:
report.append(_('PROC %d: from stock - %3.2f %-5s - %s') % \ cr.commit()
(proc.id, proc.product_qty, proc.product_uom.name, except OperationalError:
proc.product_id.name,)) if use_new_cursor:
report_except += 1 cr.rollback()
continue
else:
if use_new_cursor: raise
cr.commit() if not ids or prev_ids == ids:
offset += len(ids) break
if not ids: break else:
end_date = fields.datetime.now() prev_ids = ids
if use_new_cursor: if use_new_cursor:
cr.commit() cr.commit()
@ -228,54 +218,68 @@ class procurement_order(osv.osv):
procurement_obj = self.pool.get('procurement.order') procurement_obj = self.pool.get('procurement.order')
wf_service = netsvc.LocalService("workflow") wf_service = netsvc.LocalService("workflow")
offset = 0
ids = [1] ids = [1]
prev_ids = []
if automatic: if automatic:
self.create_automatic_op(cr, uid, context=context) self.create_automatic_op(cr, uid, context=context)
while ids: orderpoint_ids = orderpoint_obj.search(cr, uid, [])
ids = orderpoint_obj.search(cr, uid, [], offset=offset, limit=100) while orderpoint_ids:
ids = orderpoint_ids[:100]
del orderpoint_ids[:100]
for op in orderpoint_obj.browse(cr, uid, ids, context=context): for op in orderpoint_obj.browse(cr, uid, ids, context=context):
prods = self._product_virtual_get(cr, uid, op) try:
if prods is None: prods = self._product_virtual_get(cr, uid, op)
continue if prods is None:
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:
continue continue
if op.product_id.type not in ('consu'): if prods < op.product_min_qty:
if op.procurement_draft_ids: qty = max(op.product_min_qty, op.product_max_qty)-prods
# Check draft procurement related to this order point
pro_ids = [x.id for x in op.procurement_draft_ids] reste = qty % op.qty_multiple
procure_datas = procurement_obj.read( if reste > 0:
cr, uid, pro_ids, ['id', 'product_qty'], context=context) qty += op.qty_multiple - reste
to_generate = qty
for proc_data in procure_datas: if qty <= 0:
if to_generate >= proc_data['product_qty']: continue
wf_service.trg_validate(uid, 'procurement.order', proc_data['id'], 'button_confirm', cr) if op.product_id.type not in ('consu'):
procurement_obj.write(cr, uid, [proc_data['id']], {'origin': op.name}, context=context) if op.procurement_draft_ids:
to_generate -= proc_data['product_qty'] # Check draft procurement related to this order point
if not to_generate: pro_ids = [x.id for x in op.procurement_draft_ids]
break procure_datas = procurement_obj.read(
qty = to_generate cr, uid, pro_ids, ['id', 'product_qty'], context=context)
to_generate = qty
for proc_data in procure_datas:
if to_generate >= proc_data['product_qty']:
wf_service.trg_validate(uid, 'procurement.order', proc_data['id'], 'button_confirm', cr)
procurement_obj.write(cr, uid, [proc_data['id']], {'origin': op.name}, context=context)
to_generate -= proc_data['product_qty']
if not to_generate:
break
qty = to_generate
if qty:
proc_id = procurement_obj.create(cr, uid,
self._prepare_orderpoint_procurement(cr, uid, op, qty, context=context),
context=context)
wf_service.trg_validate(uid, 'procurement.order', proc_id,
'button_confirm', cr)
wf_service.trg_validate(uid, 'procurement.order', proc_id,
'button_check', cr)
orderpoint_obj.write(cr, uid, [op.id],
{'procurement_id': proc_id}, context=context)
if use_new_cursor:
cr.commit()
except OperationalError:
if use_new_cursor:
orderpoint_ids.append(op.id)
cr.rollback()
continue
else:
raise
if prev_ids == ids:
break
else:
prev_ids = ids
if qty:
proc_id = procurement_obj.create(cr, uid,
self._prepare_orderpoint_procurement(cr, uid, op, qty, context=context),
context=context)
wf_service.trg_validate(uid, 'procurement.order', proc_id,
'button_confirm', cr)
wf_service.trg_validate(uid, 'procurement.order', proc_id,
'button_check', cr)
orderpoint_obj.write(cr, uid, [op.id],
{'procurement_id': proc_id}, context=context)
offset += len(ids)
if use_new_cursor:
cr.commit()
if use_new_cursor: if use_new_cursor:
cr.commit() cr.commit()
cr.close() cr.close()