diff --git a/addons/mrp/procurement.py b/addons/mrp/procurement.py index 9ee58752bfe..c1519ea1b88 100644 --- a/addons/mrp/procurement.py +++ b/addons/mrp/procurement.py @@ -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, diff --git a/addons/procurement/__init__.py b/addons/procurement/__init__.py index 56295645128..a46f8a0cc66 100644 --- a/addons/procurement/__init__.py +++ b/addons/procurement/__init__.py @@ -21,5 +21,4 @@ import procurement import wizard -import company diff --git a/addons/procurement/__openerp__.py b/addons/procurement/__openerp__.py index ca2ae09504b..76fab3b20f4 100644 --- a/addons/procurement/__openerp__.py +++ b/addons/procurement/__openerp__.py @@ -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'], diff --git a/addons/procurement/company.py b/addons/procurement/company.py deleted file mode 100644 index 1fd08d967f1..00000000000 --- a/addons/procurement/company.py +++ /dev/null @@ -1,37 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 2004-2010 Tiny SPRL (). -# -# 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 . -# -############################################################################## - -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: diff --git a/addons/procurement/company_view.xml b/addons/procurement/company_view.xml deleted file mode 100644 index dadd24a0860..00000000000 --- a/addons/procurement/company_view.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - res.company.mrp.config - res.company - 17 - - - - - - - - - - - - diff --git a/addons/procurement/procurement.py b/addons/procurement/procurement.py index b35a7755b28..1439b323173 100644 --- a/addons/procurement/procurement.py +++ b/addons/procurement/procurement.py @@ -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() diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py index a0d21807039..df516b20587 100644 --- a/addons/purchase/purchase.py +++ b/addons/purchase/purchase.py @@ -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 diff --git a/addons/sale_stock/sale_stock.py b/addons/sale_stock/sale_stock.py index c7afb693710..65727c264aa 100644 --- a/addons/sale_stock/sale_stock.py +++ b/addons/sale_stock/sale_stock.py @@ -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) diff --git a/addons/stock/procurement.py b/addons/stock/procurement.py index cb19c3b058e..cdcb86427ae 100644 --- a/addons/stock/procurement.py +++ b/addons/stock/procurement.py @@ -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()