[WIP] procurement, project_mrp
authorQuentin (OpenERP) <qdp-launchpad@openerp.com>
Wed, 10 Jul 2013 15:00:42 +0000 (17:00 +0200)
committerQuentin (OpenERP) <qdp-launchpad@openerp.com>
Wed, 10 Jul 2013 15:00:42 +0000 (17:00 +0200)
bzr revid: qdp-launchpad@openerp.com-20130710150042-djynhii0hrib2rlk

addons/procurement/procurement.py
addons/project_mrp/__init__.py
addons/project_mrp/project_mrp.py
addons/project_mrp/project_procurement.py [deleted file]
addons/purchase/purchase.py
addons/sale_stock/sale_stock.py

index 282680a..d3bb422 100644 (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
index df4f0fa..c0c3172 100644 (file)
@@ -19,7 +19,6 @@
 #
 ##############################################################################
 
-import project_procurement
 import project_mrp
 
 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
index bb25b4a..081a343 100644 (file)
 
 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,
diff --git a/addons/project_mrp/project_procurement.py b/addons/project_mrp/project_procurement.py
deleted file mode 100644 (file)
index f4b4a28..0000000
+++ /dev/null
@@ -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:
index 08bcaa5..f0d796f 100644 (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':
index a3b489e..38a8d77 100644 (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: