[IMP] procurement: removed the schedule_range field on res.company which was error prone and not really usefull + made the scheduler run in SUPERUSER to avoid intercompany and access rights issues + made the run of procurement as SUPERUSER too for the same reasons

bzr revid: qdp-launchpad@openerp.com-20140403071010-5mrox75rkufur2nw
This commit is contained in:
Quentin (OpenERP) 2014-04-03 09:10:10 +02:00
parent 5b980f2b29
commit fe0e95d29b
9 changed files with 38 additions and 117 deletions

View File

@ -21,9 +21,9 @@
from datetime import datetime
from dateutil.relativedelta import relativedelta
from openerp.osv import fields
from openerp.osv import osv
from openerp.osv import osv, fields
from openerp.tools.translate import _
from openerp import SUPERUSER_ID
class procurement_rule(osv.osv):
_inherit = 'procurement.rule'
@ -75,7 +75,6 @@ class procurement_order(osv.osv):
company = self.pool.get('res.users').browse(cr, uid, uid, context).company_id
production_obj = self.pool.get('mrp.production')
bom_obj = self.pool.get('mrp.bom')
move_obj = self.pool.get('stock.move')
procurement_obj = self.pool.get('procurement.order')
for procurement in procurement_obj.browse(cr, uid, ids, context=context):
if self.check_bom_exists(cr, uid, [procurement.id], context=context):
@ -91,7 +90,8 @@ class procurement_order(osv.osv):
res_id = procurement.move_dest_id and procurement.move_dest_id.id or False
newdate = datetime.strptime(procurement.date_planned, '%Y-%m-%d %H:%M:%S') - relativedelta(days=procurement.product_id.produce_delay or 0.0)
newdate = newdate - relativedelta(days=company.manufacturing_lead)
produce_id = production_obj.create(cr, uid, {
#create the MO as SUPERUSER because the current user may not have the rights to do it (mto product launched by a sale for example)
produce_id = production_obj.create(cr, SUPERUSER_ID, {
'origin': procurement.origin,
'product_id': procurement.product_id.id,
'product_qty': procurement.product_qty,

View File

@ -21,5 +21,4 @@
import procurement
import wizard
import company

View File

@ -49,7 +49,6 @@ depending on the product's configuration.
'procurement_data.xml',
'wizard/schedulers_all_view.xml',
'procurement_view.xml',
'company_view.xml',
],
'demo': [],
'test': ['test/procurement.yml'],

View File

@ -1,37 +0,0 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from openerp.osv import osv,fields
class company(osv.osv):
_inherit = 'res.company'
_columns = {
'schedule_range': fields.float('Scheduler Range Days', required=True,
help="This is the time frame analysed by the scheduler when "\
"computing procurements. All procurements that are not between "\
"today and today+range are skipped for future computation."),
}
_defaults = {
'schedule_range': 730.0,
}
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -1,20 +0,0 @@
<?xml version="1.0" ?>
<openerp>
<data>
<record id="mrp_company" model="ir.ui.view">
<field name="name">res.company.mrp.config</field>
<field name="model">res.company</field>
<field name="priority">17</field>
<field name="inherit_id" ref="base.view_company_form"/>
<field name="arch" type="xml">
<xpath expr="//group[@name='account_grp']" position="after">
<group name="logistics_grp" string="Logistics">
<field name="schedule_range"/>
</group>
</xpath>
</field>
</record>
</data>
</openerp>

View File

@ -21,9 +21,7 @@
import time
from datetime import datetime
from dateutil.relativedelta import relativedelta
from openerp import SUPERUSER_ID
from openerp.osv import fields, osv
import openerp.addons.decimal_precision as dp
from openerp.tools.translate import _
@ -31,7 +29,7 @@ import openerp
class procurement_group(osv.osv):
'''
The procurement requirement class is used to group products together
The procurement group class is used to group products together
when computing procurements. (tasks, physical products, ...)
The goal is that when you have one sale order of several products
@ -56,12 +54,11 @@ class procurement_group(osv.osv):
_description = 'Procurement Requisition'
_order = "id desc"
_columns = {
'name': fields.char('Reference', required=True),
'name': fields.char('Reference', required=True),
'move_type': fields.selection([
('direct', 'Partial'), ('one', 'All at once')],
'Delivery Method', required=True),
'partner_id': fields.many2one('res.partner', string = 'Partner'), #Sale should pass it here
'procurement_ids': fields.one2many('procurement.order', 'group_id', 'Procurements'),
'procurement_ids': fields.one2many('procurement.order', 'group_id', 'Procurements'),
}
_defaults = {
'name': lambda self, cr, uid, c: self.pool.get('ir.sequence').get(cr, uid, 'procurement.group') or '',
@ -266,7 +263,8 @@ class procurement_order(osv.osv):
#
def run_scheduler(self, cr, uid, use_new_cursor=False, context=None):
'''
Call the scheduler to check the procurement order
Call the scheduler to check the procurement order. This is intented to be done for all existing companies at
the same time, so we're running all the methods as SUPERUSER to avoid intercompany and access rights issues.
@param self: The object pointer
@param cr: The current row, from the database cursor,
@ -282,25 +280,22 @@ class procurement_order(osv.osv):
if use_new_cursor:
cr = openerp.registry(use_new_cursor).db.cursor()
company = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id
maxdate = (datetime.today() + relativedelta(days=company.schedule_range)).strftime('%Y-%m-%d %H:%M:%S')
# Run confirmed procurements
while True:
ids = self.search(cr, uid, [('state', '=', 'confirmed'), ('date_planned', '<=', maxdate)], context=context)
ids = self.search(cr, SUPERUSER_ID, [('state', '=', 'confirmed')], context=context)
if not ids:
break
self.run(cr, uid, ids, context=context)
self.run(cr, SUPERUSER_ID, ids, context=context)
if use_new_cursor:
cr.commit()
# Check if running procurements are done
offset = 0
while True:
ids = self.search(cr, uid, [('state', '=', 'running'), ('date_planned', '<=', maxdate)], offset=offset, context=context)
ids = self.search(cr, SUPERUSER_ID, [('state', '=', 'running')], offset=offset, context=context)
if not ids:
break
done = self.check(cr, uid, ids, context=context)
done = self.check(cr, SUPERUSER_ID, ids, context=context)
offset += len(ids) - len(done)
if use_new_cursor:
cr.commit()

View File

@ -1262,8 +1262,10 @@ class procurement_order(osv.osv):
}
def make_po(self, cr, uid, ids, context=None):
""" Make purchase order from procurement
@return: New created Purchase Orders procurement wise
""" Resolve the purchase from procurement, which may result in a new PO creation, a new PO line creation or a quantity change on existing PO line.
Note that some operations (as the PO creation) are made as SUPERUSER because the current user may not have rights to do it (mto product launched by a sale for example)
@return: dictionary giving for each procurement its related resolving PO line.
"""
res = {}
company = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id
@ -1291,12 +1293,12 @@ class procurement_order(osv.osv):
available_po_line_ids = po_line_obj.search(cr, uid, [('order_id', '=', po_id), ('product_id', '=', line_vals['product_id']), ('product_uom', '=', line_vals['product_uom'])], context=context)
if available_po_line_ids:
po_line = po_line_obj.browse(cr, uid, available_po_line_ids[0], context=context)
po_line_obj.write(cr, uid, po_line.id, {'product_qty': po_line.product_qty + line_vals['product_qty']}, context=context)
po_line_obj.write(cr, SUPERUSER_ID, po_line.id, {'product_qty': po_line.product_qty + line_vals['product_qty']}, context=context)
po_line_id = po_line.id
sum_po_line_ids.append(procurement.id)
else:
line_vals.update(order_id=po_id)
po_line_id = po_line_obj.create(cr, uid, line_vals, context=context)
po_line_id = po_line_obj.create(cr, SUPERUSER_ID, line_vals, context=context)
linked_po_ids.append(procurement.id)
else:
purchase_date = self._get_purchase_order_date(cr, uid, procurement, company, schedule_date, context=context)
@ -1314,7 +1316,7 @@ class procurement_order(osv.osv):
'payment_term_id': partner.property_supplier_payment_term.id or False,
'dest_address_id': procurement.partner_dest_id.id,
}
po_id = self.create_procurement_purchase_order(cr, uid, procurement, po_vals, line_vals, context=context)
po_id = self.create_procurement_purchase_order(cr, SUPERUSER_ID, procurement, po_vals, line_vals, context=context)
po_line_id = po_obj.browse(cr, uid, po_id, context=context).order_line[0].id
pass_ids.append(procurement.id)
res[procurement.id] = po_line_id

View File

@ -176,12 +176,6 @@ class sale_order(osv.osv):
raise osv.except_osv(
_('Cannot cancel sales order!'),
_('You must first cancel all delivery order(s) attached to this sales order.'))
# FP Note: not sure we need this
#if pick.state == 'cancel':
# for mov in pick.move_lines:
# proc_ids = proc_obj.search(cr, uid, [('move_id', '=', mov.id)])
# if proc_ids:
# proc_obj.signal_button_check(cr, uid, proc_ids)
stock_obj.signal_button_cancel(cr, uid, [p.id for p in sale.picking_ids])
return super(sale_order, self).action_cancel(cr, uid, ids, context=context)

View File

@ -23,6 +23,7 @@ from openerp.osv import fields, osv
from openerp.tools.translate import _
from openerp.tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FORMAT
from openerp import SUPERUSER_ID
from dateutil.relativedelta import relativedelta
from datetime import datetime
import openerp
@ -216,7 +217,8 @@ class procurement_order(osv.osv):
return False
move_obj = self.pool.get('stock.move')
move_dict = self._run_move_create(cr, uid, procurement, context=context)
move_obj.create(cr, uid, move_dict, context=context)
#create the move as SUPERUSER because the current user may not have the rights to do it (mto product launched by a sale for example)
move_obj.create(cr, SUPERUSER_ID, move_dict, context=context)
self.message_post(cr, uid, [procurement.id], body=_("Supply Move created"), context=context)
return True
return super(procurement_order, self)._run(cr, uid, procurement, context=context)
@ -278,15 +280,11 @@ class procurement_order(osv.osv):
result['domain'] = "[('group_id','in',[" + ','.join(map(str, list(group_ids))) + "])]"
return result
#
# Scheduler
# When stock is installed, it should also check for the different confirmed stock moves
# if they can not be installed
#
#
def run_scheduler(self, cr, uid, use_new_cursor=False, context=None):
'''
Call the scheduler in order to
Call the scheduler in order to check the running procurements (super method), to check the minimum stock rules
and the availability of moves. This function is intended to be run for all the companies at the same time, so
we run functions as SUPERUSER to avoid intercompanies and access rights issues.
@param self: The object pointer
@param cr: The current row, from the database cursor,
@ -296,7 +294,6 @@ class procurement_order(osv.osv):
@param context: A standard dictionary for contextual values
@return: Dictionary of values
'''
super(procurement_order, self).run_scheduler(cr, uid, use_new_cursor=use_new_cursor, context=context)
if context is None:
context = {}
@ -304,19 +301,19 @@ class procurement_order(osv.osv):
if use_new_cursor:
cr = openerp.registry(use_new_cursor).db.cursor()
company = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id
move_obj = self.pool.get('stock.move')
#Minimum stock rules
self. _procure_orderpoint_confirm(cr, uid, use_new_cursor=False, context=context, user_id=False)
company = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id
self._procure_orderpoint_confirm(cr, SUPERUSER_ID, use_new_cursor=False, company_id=company.id, context=context)
#Search all confirmed stock_moves and try to assign them
confirmed_ids = move_obj.search(cr, uid, [('state', '=', 'confirmed'), ('company_id','=', company.id)], limit=None, order='picking_priority desc, date_expected asc', context=context)
confirmed_ids = move_obj.search(cr, uid, [('state', '=', 'confirmed')], limit=None, order='picking_priority desc, date_expected asc', context=context)
for x in xrange(0, len(confirmed_ids), 100):
move_obj.action_assign(cr, uid, confirmed_ids[x:x+100], context=context)
move_obj.action_assign(cr, uid, confirmed_ids[x:x + 100], context=context)
if use_new_cursor:
cr.commit()
if use_new_cursor:
cr.commit()
finally:
@ -327,7 +324,6 @@ class procurement_order(osv.osv):
pass
return {}
def _get_orderpoint_date_planned(self, cr, uid, orderpoint, start_date, context=None):
date_planned = start_date
return date_planned.strftime(DEFAULT_SERVER_DATE_FORMAT)
@ -349,17 +345,11 @@ class procurement_order(osv.osv):
[order_point.product_id.id],
{'location': order_point.location_id.id})[order_point.product_id.id]['virtual_available']
def _procure_orderpoint_confirm(self, cr, uid, \
use_new_cursor=False, context=None, user_id=False):
def _procure_orderpoint_confirm(self, cr, uid, use_new_cursor=False, company_id=False, context=None):
'''
Create procurement based on Orderpoint
use_new_cursor: False or the dbname
@param self: The object pointer
@param cr: The current row, from the database cursor,
@param user_id: The current user ID for security checks
@param context: A standard dictionary for contextual values
@param param: False or the dbname
@return: Dictionary of values
"""
'''
@ -368,18 +358,18 @@ class procurement_order(osv.osv):
if use_new_cursor:
cr = openerp.registry(use_new_cursor).db.cursor()
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, [], offset=offset, limit=100)
ids = orderpoint_obj.search(cr, uid, [('company_id', '=', company_id)], offset=offset, limit=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
qty = max(op.product_min_qty, op.product_max_qty) - prods
reste = qty % op.qty_multiple
if reste > 0:
@ -409,8 +399,7 @@ class procurement_order(osv.osv):
context=context)
self.check(cr, uid, [proc_id])
self.run(cr, uid, [proc_id])
orderpoint_obj.write(cr, uid, [op.id],
{'procurement_id': proc_id}, context=context)
orderpoint_obj.write(cr, uid, [op.id], {'procurement_id': proc_id}, context=context)
offset += len(ids)
if use_new_cursor:
cr.commit()