[WIP] procurement, project_mrp

bzr revid: qdp-launchpad@openerp.com-20130710150042-djynhii0hrib2rlk
This commit is contained in:
Quentin (OpenERP) 2013-07-10 17:00:42 +02:00
parent 9f4d4d28a8
commit af7cf8a226
6 changed files with 83 additions and 129 deletions

View File

@ -142,10 +142,8 @@ class procurement_order(osv.osv):
return {}
def run(self, cr, uid, ids, context=None):
for procurement in self.browse(cr, uid, ids, context=context or {}):
rule = self.pool.get("procurement.rule").browse(cr, uid, self._assign(cr, uid, procurement, context=context), context=context)
if rule:
self.write(cr, uid, [procurement.id], {'rule_id': rule.id}, context=context)
for procurement in self.browse(cr, uid, ids, context=context):
if self._assign(cr, uid, procurement, context=context):
procurement.refresh()
self._run(cr, uid, procurement, context=context or {})
self.write(cr, uid, [procurement.id], {'state': 'running'}, context=context)
@ -166,14 +164,27 @@ class procurement_order(osv.osv):
#
# Method to overwrite in different procurement modules
#
def _assign(self, cr, uid, procurement, context=None):
'''This method returns a procurement.rule that depicts what to go with the given procurement
def _find_suitable_rule(self, cr, uid, procurement, context=None):
'''This method returns a procurement.rule that depicts what to do with the given procurement
in order to complete its needs. It returns False if no suiting rule is found.
:param procurement: browse record
:rtype: int or False
'''
return False
def _assign(self, cr, uid, procurement, context=None):
'''This method check what to do with the given procurement in order to complete its needs.
It returns False if no solution is found, otherwise it stores the matching rule (if any) and
returns True.
:param procurement: browse record
:rtype: boolean
'''
rule_id = self._find_suitable_rule(cr, uid, procurement, context=context)
if rule_id:
self.write(cr, uid, [procurement.id], {'rule_id': rule_id}, context=context)
return True
return False
def _run(self, cr, uid, procurement, context=None):
'''This method implements the resolution of the given procurement
:param procurement: browse record

View File

@ -19,7 +19,6 @@
#
##############################################################################
import project_procurement
import project_mrp
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -21,6 +21,56 @@
from openerp.osv import fields, osv
from openerp import netsvc
from openerp.tools.translate import _
class procurement_order(osv.osv):
_name = "procurement.order"
_inherit = "procurement.order"
_columns = {
'task_id': fields.many2one('project.task', 'Task'),
'sale_line_id': fields.many2one('sale.order.line', 'Sales order line')
}
def _is_procurement_task(self, cr, uid, procurement, context=None):
return procurement.product_id.type == 'service' and procurement.product_it.auto_create_task or False
def _assign(self, cr, uid, procurement, context=None):
res = super(procurement_order, self)._assign(cr, uid, procurement, context=context)
if not res:
#if there isn't any specific procurement.rule defined for the product, we may want to create a task
if self._is_procurement_task(cr, uid, procurement, context=context):
return True
return res
def _run(self, cr, uid, procurement, context=None):
if self._is_procurement_task(cr, uid, procurement, context=context) and not procurement.task_id:
#create a task for the procurement
return self._create_service_task(cr, uid, procurement, context=context)
return super(procurement_order, self)._run(cr, uid, procurement, context=context)
def _check(self, cr, uid, procurement, context=None):
if self._is_procurement_task(cr, uid, procurement, context=context) and procurement.task_id and procurement.task_id.state == 'done':
return True
return super(procurement_order, self)._check(cr, uid, procurement, context=context)
def _convert_qty_company_hours(self, cr, uid, procurement, context=None):
product_uom = self.pool.get('product.uom')
company_time_uom_id = self.pool.get('res.users').browse(cr, uid, uid).company_id.project_time_mode_id
if procurement.product_uom.id != company_time_uom_id.id and procurement.product_uom.category_id.id == company_time_uom_id.category_id.id:
planned_hours = product_uom._compute_qty(cr, uid, procurement.product_uom.id, procurement.product_qty, company_time_uom_id.id)
else:
planned_hours = procurement.product_qty
return planned_hours
def _get_project(self, cr, uid, procurement, context=None):
project_project = self.pool.get('project.project')
project = procurement.product_id.project_id
if not project and procurement.sale_line_id:
# find the project corresponding to the analytic account of the sales order
account = procurement.sale_line_id.order_id.project_id
project_ids = project_project.search(cr, uid, [('analytic_account_id', '=', account.id)])
projects = project_project.browse(cr, uid, project_ids, context=context)
class project_task(osv.osv):
_name = "project.task"
@ -30,30 +80,21 @@ class project_task(osv.osv):
'sale_line_id': fields.related('procurement_id', 'sale_line_id', type='many2one', relation='sale.order.line', store=True, string='Sales Order Line'),
}
def _validate_subflows(self, cr, uid, ids):
wf_service = netsvc.LocalService("workflow")
for task in self.browse(cr, uid, ids):
if task.procurement_id:
wf_service.trg_write(uid, 'procurement.order', task.procurement_id.id, cr)
def do_close(self, cr, uid, ids, *args, **kwargs):
res = super(project_task, self).do_close(cr, uid, ids, *args, **kwargs)
self._validate_subflows(cr, uid, ids)
return res
def do_cancel(self, cr, uid, ids, *args, **kwargs):
res = super(project_task, self).do_cancel(cr, uid, ids, *args, **kwargs)
self._validate_subflows(cr, uid, ids)
return res
#TODO handle the task cancellation
#def do_cancel(self, cr, uid, ids, *args, **kwargs):
# res = super(project_task, self).do_cancel(cr, uid, ids, *args, **kwargs)
# self._validate_subflows(cr, uid, ids)
# return res
class product_product(osv.osv):
_inherit = "product.product"
_columns = {
'project_id': fields.many2one('project.project', 'Project', ondelete='set null',)
'project_id': fields.many2one('project.project', 'Project', ondelete='set null',),
'auto_create_task': fields.boolean('Create Task Automatically', help="Thick this option if you want to create a task automatically each time this product is sold"),
}
class sale_order(osv.osv):
_inherit ='sale.order'
_inherit = 'sale.order'
def _prepare_order_line_procurement(self, cr, uid, order, line, move_id, date_planned, context=None):
proc_data = super(sale_order, self)._prepare_order_line_procurement(cr,

View File

@ -1,98 +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 fields, osv
from openerp.tools.translate import _
class procurement_order(osv.osv):
_name = "procurement.order"
_inherit = "procurement.order"
_columns = {
'task_id': fields.many2one('project.task', 'Task'),
'sale_line_id': fields.many2one('sale.order.line', 'Sales order line')
}
def action_check_finished(self, cr, uid, ids):
res = super(procurement_order, self).action_check_finished(cr, uid, ids)
return res and self.check_task_done(cr, uid, ids)
def check_task_done(self, cr, uid, ids, context=None):
""" Checks if task is done or not.
@return: True or False.
"""
for p in self.browse(cr, uid, ids, context=context):
if (p.product_id.type=='service') and (p.procure_method=='make_to_order') and p.task_id and (p.task_id.state not in ('done', 'cancelled')):
return False
return True
def check_produce_service(self, cr, uid, procurement, context=None):
return True
def _convert_qty_company_hours(self, cr, uid, procurement, context=None):
product_uom = self.pool.get('product.uom')
company_time_uom_id = self.pool.get('res.users').browse(cr, uid, uid).company_id.project_time_mode_id
if procurement.product_uom.id != company_time_uom_id.id and procurement.product_uom.category_id.id == company_time_uom_id.category_id.id:
planned_hours = product_uom._compute_qty(cr, uid, procurement.product_uom.id, procurement.product_qty, company_time_uom_id.id)
else:
planned_hours = procurement.product_qty
return planned_hours
def _get_project(self, cr, uid, procurement, context=None):
project_project = self.pool.get('project.project')
project = procurement.product_id.project_id
if not project and procurement.sale_line_id:
# find the project corresponding to the analytic account of the sales order
account = procurement.sale_line_id.order_id.project_id
project_ids = project_project.search(cr, uid, [('analytic_account_id', '=', account.id)])
projects = project_project.browse(cr, uid, project_ids, context=context)
project = projects and projects[0] or False
return project
def action_produce_assign_service(self, cr, uid, ids, context=None):
project_task = self.pool.get('project.task')
for procurement in self.browse(cr, uid, ids, context=context):
project = self._get_project(cr, uid, procurement, context=context)
planned_hours = self._convert_qty_company_hours(cr, uid, procurement, context=context)
task_id = project_task.create(cr, uid, {
'name': '%s:%s' % (procurement.origin or '', procurement.product_id.name),
'date_deadline': procurement.date_planned,
'planned_hours': planned_hours,
'remaining_hours': planned_hours,
'partner_id': procurement.sale_line_id and procurement.sale_line_id.order_id.partner_id.id or False,
'user_id': procurement.product_id.product_manager.id,
'procurement_id': procurement.id,
'description': procurement.name + '\n' + (procurement.note or ''),
'project_id': project and project.id or False,
'company_id': procurement.company_id.id,
},context=context)
self.write(cr, uid, [procurement.id], {'task_id': task_id, 'state': 'running', 'message':_('Task created.')}, context=context)
self.project_task_create_note(cr, uid, ids, context=context)
return task_id
def project_task_create_note(self, cr, uid, ids, context=None):
for procurement in self.browse(cr, uid, ids, context=context):
body = _("Task created")
self.message_post(cr, uid, [procurement.id], body=body, context=context)
if procurement.sale_line_id and procurement.sale_line_id.order_id:
procurement.sale_line_id.order_id.message_post(body=body)
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -1034,14 +1034,14 @@ class procurement_order(osv.osv):
'purchase_id': fields.many2one('purchase.order', 'Purchase Order'),
}
def _assign(self, cr, uid, procurement, context=None):
rule = super(procurement_order, self)._assign(cr, uid, procurement, context=context)
if not rule:
def _find_suitable_rule(self, cr, uid, procurement, context=None):
rule_id = super(procurement_order, self)._find_suitable_rule(cr, uid, procurement, context=context)
if not rule_id:
#if there isn't any specific procurement.rule defined for the product, we try to directly supply it from a supplier
if procurement.product_id.supply_method == 'buy' and self._check_supplier_info(cr, uid, [procurement.id], context=context):
rule = self.pool.get('procurement.rule').search(cr, uid, [('action', '=', 'buy'), ('location_id', '=', procurement.location_id.id)], context=context)
rule = rule and rule[0] or False
return rule
rule_id = self.pool.get('procurement.rule').search(cr, uid, [('action', '=', 'buy'), ('location_id', '=', procurement.location_id.id)], context=context)
rule_id = rule_id and rule_id[0] or False
return rule_id
def _run(self, cr, uid, procurement, context=None):
if procurement.rule_id and procurement.rule_id.action == 'buy':

View File

@ -55,7 +55,7 @@ class sale_order(osv.osv):
('shipping_except', 'Shipping Exception'),
('invoice_except', 'Invoice Exception'),
('done', 'Done'),
], 'Status', readonly=True,help="Gives the status of the quotation or sales order.\
], 'Status', readonly=True, help="Gives the status of the quotation or sales order.\
\nThe exception status is automatically set when a cancel operation occurs \
in the invoice validation (Invoice Exception) or in the picking list process (Shipping Exception).\nThe 'Waiting Schedule' status is set when the invoice is confirmed\
but waiting for the scheduler to run on the order date.", select=True),
@ -494,3 +494,4 @@ class sale_advance_payment_inv(osv.osv_memory):
}
sale_line_obj.create(cr, uid, vals, context=context)
return result
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: