Jigar Amin  (OpenERP) has proposed merging 
lp:~openerp-dev/openobject-addons/trunk-bug-823838-jam into 
lp:openobject-addons.

Requested reviews:
  Bhumika (OpenERP) (sbh-openerp)
Related bugs:
  Bug #823838 in OpenERP Addons: "project hours don't include child projects 
hours"
  https://bugs.launchpad.net/openobject-addons/+bug/823838

For more details, see:
https://code.launchpad.net/~openerp-dev/openobject-addons/trunk-bug-823838-jam/+merge/83924

Changes - Bug Fix : 
   - Bug #823838  project hours don't include child projects hours 


Test Case:
-----------------------
The project from existing Demo:
  - Integrate a Sale and Warehouse Management
    - planned time: 680
    - total time 0
    - time spent 0
    - progress 0
    - parent: Projects

Now, I create a new Project: MyProj and change the parent project of "Integrate 
a Sale and Warehouse Management to this one " 
  - planned hour form MyProj remains 0 
  - Create task MyTask1 for project 'MyProj' with Planned Hours 100
  - Create a MyWork for 'MyTask' with time spent 50 and Mark 'MyTask' as done
  - Now MyProj has
     - planned time: 100
     - total time: 100
     - time spent: 50
     - progress 50%

Now Check the Project "Integrate a Sale and Warehouse Management" which is 
completely ignoring the child project "MyProj" while tooltip of of the field 
planned_hours, effective_hours, total_hours Suggest that it will consider 
values of "this project and its child projects".

Kindly Review this and Let me Know if i am wrong.
Thank You
-- 
https://code.launchpad.net/~openerp-dev/openobject-addons/trunk-bug-823838-jam/+merge/83924
Your team OpenERP R&D Team is subscribed to branch 
lp:~openerp-dev/openobject-addons/trunk-bug-823838-jam.
=== modified file 'project/project.py'
--- project/project.py	2011-11-23 13:31:32 +0000
+++ project/project.py	2011-11-30 11:44:54 +0000
@@ -84,21 +84,47 @@
             val['pricelist_id'] = pricelist_id
         return {'value': val}
 
+    def _get_childs(self, cr, uid, ids, childs,context=None):
+        cr.execute("""SELECT id FROM project_project WHERE analytic_account_id IN (
+                        SELECT id FROM account_analytic_account WHERE parent_id = (
+	                        SELECT  analytic_account_id FROM project_project project
+		                        LEFT JOIN account_analytic_account account ON account.id = project.analytic_account_id
+		                        WHERE project.id = %s
+                            )
+                        )"""%(ids)) 
+        for child in cr.fetchall():
+            if child[0] not in childs: childs.append(child[0])
+            self._get_childs( cr, uid, child[0], childs,context)
+        return childs
+
+
+    def _get_parents(self, cr, uid, ids, parents,context=None):
+        for project in self.read(cr, uid, ids, ['id', 'parent_id'],context):
+            if project.get('parent_id'):
+                cr.execute('''SELECT id FROM project_project WHERE analytic_account_id = '%s' '''%project.get('parent_id')[0])
+                for child in cr.fetchall():
+                    if child[0] not in parents: parents.append(child[0])
+                    child_rec= self.read(cr, uid, child[0], ['id', 'parent_id'],context)
+                    if child_rec.get('parent_id'):
+                        parents = self._get_parents(cr, uid, [child[0]], parents,context)
+        return parents
+
+    def _get_project(self,cr, ids):
+        cr.execute('''SELECT project_id, sum(planned_hours), sum(total_hours), sum(effective_hours), SUM(remaining_hours)
+                      FROM project_task WHERE project_id in %s AND state<>'cancelled'
+                      GROUP BY project_id''', (tuple(ids),))
+        return cr
+
     def _progress_rate(self, cr, uid, ids, names, arg, context=None):
         res = {}.fromkeys(ids, 0.0)
         if not ids:
             return res
-        cr.execute('''SELECT
-                project_id, sum(planned_hours), sum(total_hours), sum(effective_hours), SUM(remaining_hours)
-            FROM
-                project_task
-            WHERE
-                project_id in %s AND
-                state<>'cancelled'
-            GROUP BY
-                project_id''', (tuple(ids),))
-        progress = dict(map(lambda x: (x[0], (x[1],x[2],x[3],x[4])), cr.fetchall()))
-        for project in self.browse(cr, uid, ids, context=context):
+        parents = self._get_parents(cr, uid, ids, ids,context)
+        cr = self._get_project(cr,ids)
+        progress = dict(map(lambda x: (x[0], (x[1] or 0.0 ,x[2] or 0.0 ,x[3] or 0.0 ,x[4] or 0.0)), cr.fetchall()))
+        for project in self.browse(cr, uid, parents, context=context):
+            childs = []
+            childs = self._get_childs(cr, uid, project.id, childs,context)
             s = progress.get(project.id, (0.0,0.0,0.0,0.0))
             res[project.id] = {
                 'planned_hours': s[0],
@@ -106,12 +132,33 @@
                 'total_hours': s[1],
                 'progress_rate': s[1] and round(100.0*s[2]/s[1],2) or 0.0
             }
+            
+            if childs:
+                cr = self._get_project(cr, childs)
+                child_progress = dict(map(lambda x: (x[0], (x[1] or 0.0 ,x[2] or 0.0 ,x[3] or 0.0 ,x[4] or 0.0)), cr.fetchall()))
+                planned_hours, effective_hours, total_hours, rnd= 0.0, 0.0,0.0, 0.0
+                for child in childs:
+                    ch_vals = child_progress.get(child, (0.0,0.0,0.0,0.0))
+                    planned_hours, effective_hours, total_hours = planned_hours+ch_vals[0], effective_hours+ch_vals[2] , total_hours+ch_vals[1]
+                if res.get(project.id).get('planned_hours')+ planned_hours > 0:
+                    rnd = round(( res.get(project.id).get('effective_hours')+effective_hours)/(res.get(project.id).get('planned_hours')+ planned_hours)*100,2) or 0.0
+                res[project.id] = {
+                    'planned_hours': res.get(project.id).get('planned_hours')+ planned_hours,
+                    'effective_hours': res.get(project.id).get('effective_hours')+ effective_hours,
+                    'total_hours': res.get(project.id).get('total_hours')+ total_hours,
+                    'progress_rate':  rnd
+                }
         return res
 
     def _get_project_task(self, cr, uid, ids, context=None):
         result = {}
         for task in self.pool.get('project.task').browse(cr, uid, ids, context=context):
-            if task.project_id: result[task.project_id.id] = True
+            if task.project_id: 
+                result[task.project_id.id] = True
+                if task.project_id.parent_id:
+                    cr.execute('''SELECT id FROM project_project WHERE analytic_account_id = '%s' '''%task.project_id.parent_id.id)
+                    for parent in cr.fetchall():
+                        result[parent[0]] = True
         return result.keys()
 
     def _get_project_work(self, cr, uid, ids, context=None):
@@ -139,14 +186,14 @@
         'tasks': fields.one2many('project.task', 'project_id', "Project tasks"),
         'planned_hours': fields.function(_progress_rate, multi="progress", string='Planned Time', help="Sum of planned hours of all tasks related to this project and its child projects.",
             store = {
-                'project.project': (lambda self, cr, uid, ids, c={}: ids, ['tasks'], 10),
+                'project.project': (lambda self, cr, uid, ids, c={}: ids, ['tasks', 'parent_id', 'child_ids'], 10),
                 'project.task': (_get_project_task, ['planned_hours', 'effective_hours', 'remaining_hours', 'total_hours', 'progress', 'delay_hours','state'], 10),
             }),
         'effective_hours': fields.function(_progress_rate, multi="progress", string='Time Spent', help="Sum of spent hours of all tasks related to this project and its child projects."),
         'resource_calendar_id': fields.many2one('resource.calendar', 'Working Time', help="Timetable working hours to adjust the gantt diagram report", states={'close':[('readonly',True)]} ),
         'total_hours': fields.function(_progress_rate, multi="progress", string='Total Time', help="Sum of total hours of all tasks related to this project and its child projects.",
             store = {
-                'project.project': (lambda self, cr, uid, ids, c={}: ids, ['tasks'], 10),
+                'project.project': (lambda self, cr, uid, ids, c={}: ids, ['tasks','parent_id', 'child_ids'], 10),
                 'project.task': (_get_project_task, ['planned_hours', 'effective_hours', 'remaining_hours', 'total_hours', 'progress', 'delay_hours','state'], 10),
             }),
         'progress_rate': fields.function(_progress_rate, multi="progress", string='Progress', type='float', group_operator="avg", help="Percent of tasks closed according to the total of tasks todo."),
@@ -531,8 +578,8 @@
     def _default_project(self, cr, uid, context=None):
         if context is None:
             context = {}
-        if 'project_id' in context and context['project_id']:
-            return int(context['project_id'])
+        if 'default_project_id' in context and context['default_project_id']:
+            return int(context['default_project_id'])
         return False
 
     def duplicate_task(self, cr, uid, map_ids, context=None):

_______________________________________________
Mailing list: https://launchpad.net/~openerp-dev-gtk
Post to     : [email protected]
Unsubscribe : https://launchpad.net/~openerp-dev-gtk
More help   : https://help.launchpad.net/ListHelp

Reply via email to