[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:
parent
5b980f2b29
commit
fe0e95d29b
|
@ -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,
|
||||
|
|
|
@ -21,5 +21,4 @@
|
|||
|
||||
import procurement
|
||||
import wizard
|
||||
import company
|
||||
|
||||
|
|
|
@ -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'],
|
||||
|
|
|
@ -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:
|
|
@ -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>
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
Loading…
Reference in New Issue