From 14874a989ecfdd9b0a4db3cc059d2c6bd4d080dc Mon Sep 17 00:00:00 2001 From: Fabien Pinckaers Date: Sun, 13 Nov 2011 16:40:52 +0100 Subject: [PATCH] [IMP] Clean demo data of project and project long term using scheduler bzr revid: fp@tinyerp.com-20111113154052-gh2a8y2tqkdv2ll9 --- addons/project/__openerp__.py | 2 +- addons/project/project.py | 128 ++++++++++++++++++ addons/project/project_demo.xml | 24 ++-- addons/project_long_term/project_long_term.py | 124 ----------------- 4 files changed, 144 insertions(+), 134 deletions(-) diff --git a/addons/project/__openerp__.py b/addons/project/__openerp__.py index 936c7d361fc..9132636b56f 100644 --- a/addons/project/__openerp__.py +++ b/addons/project/__openerp__.py @@ -28,7 +28,7 @@ "category": "Project Management", 'complexity': "easy", "images": ["images/gantt.png", "images/project_dashboard.jpeg","images/project_task_tree.jpeg","images/project_task.jpeg","images/project.jpeg","images/task_analysis.jpeg"], - "depends": ["base_setup", "product", "analytic", "board", "mail"], + "depends": ["base_setup", "product", "analytic", "board", "mail", "resource"], "description": """ Project management module tracks multi-level projects, tasks, work done on tasks, eso. ====================================================================================== diff --git a/addons/project/project.py b/addons/project/project.py index 4b4e3079e38..1fc83771005 100644 --- a/addons/project/project.py +++ b/addons/project/project.py @@ -25,6 +25,7 @@ from datetime import datetime, date from tools.translate import _ from osv import fields, osv +from resource.faces import task as Task # I think we can remove this in v6.1 since VMT's improvements in the framework ? #class project_project(osv.osv): @@ -139,6 +140,7 @@ class project(osv.osv): '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), @@ -305,6 +307,105 @@ class project(osv.osv): self.setActive(cr, uid, child_ids, value, context=None) return True + def _schedule_header(self, cr, uid, ids, force_members=True, context=None): + context = context or {} + if type(ids) in (long, int,): + ids = [ids] + projects = self.browse(cr, uid, ids, context=context) + + for project in projects: + if (not project.members) and force_members: + raise osv.except_osv(_('Warning !'),_("You must assign members on the project '%s' !") % (project.name,)) + + resource_pool = self.pool.get('resource.resource') + + result = "from resource.faces import *\n" + result += "import datetime\n" + for project in self.browse(cr, uid, ids, context=context): + u_ids = [i.id for i in project.members] + if project.user_id and (project.user_id.id not in u_ids): + u_ids.append(project.user_id.id) + for task in project.tasks: + if task.state in ('done','cancelled'): + continue + if task.user_id and (task.user_id.id not in u_ids): + u_ids.append(task.user_id.id) + calendar_id = project.resource_calendar_id and project.resource_calendar_id.id or False + resource_objs = resource_pool.generate_resources(cr, uid, u_ids, calendar_id, context=context) + for key, vals in resource_objs.items(): + result +=''' +class User_%s(Resource): + efficiency = %s +''' % (key, vals.get('efficiency', False)) + + result += ''' +def Project(): + ''' + return result + + def _schedule_project(self, cr, uid, project, context=None): + resource_pool = self.pool.get('resource.resource') + calendar_id = project.resource_calendar_id and project.resource_calendar_id.id or False + working_days = resource_pool.compute_working_calendar(cr, uid, calendar_id, context=context) + # TODO: check if we need working_..., default values are ok. + puids = [x.id for x in project.members] + if project.user_id: + puids.append(project.user_id.id) + result = """ + def Project_%d(): + start = \'%s\' + working_days = %s + resource = %s +""" % ( + project.id, + project.date_start, working_days, + '|'.join(['User_'+str(x) for x in puids]) + ) + vacation = calendar_id and tuple(resource_pool.compute_vacation(cr, uid, calendar_id, context=context)) or False + if vacation: + result+= """ + vacation = %s +""" % ( vacation, ) + return result + + #TODO: DO Resource allocation and compute availability + def compute_allocation(self, rc, uid, ids, start_date, end_date, context=None): + if context == None: + context = {} + allocation = {} + return allocation + + def schedule_tasks(self, cr, uid, ids, context=None): + context = context or {} + if type(ids) in (long, int,): + ids = [ids] + projects = self.browse(cr, uid, ids, context=context) + result = self._schedule_header(cr, uid, ids, False, context=context) + for project in projects: + result += self._schedule_project(cr, uid, project, context=context) + result += self.pool.get('project.task')._generate_task(cr, uid, project.tasks, ident=4, context=context) + + local_dict = {} + exec result in local_dict + projects_gantt = Task.BalancedProject(local_dict['Project']) + + for project in projects: + project_gantt = getattr(projects_gantt, 'Project_%d' % (project.id,)) + for task in project.tasks: + if task.state in ('done','cancelled'): + continue + + p = getattr(project_gantt, 'Task_%d' % (task.id,)) + + self.pool.get('project.task').write(cr, uid, [task.id], { + 'date_start': p.start.strftime('%Y-%m-%d %H:%M:%S'), + 'date_end': p.end.strftime('%Y-%m-%d %H:%M:%S') + }, context=context) + if (not task.user_id) and (p.booked_resource): + self.pool.get('project.task').write(cr, uid, [task.id], { + 'user_id': int(p.booked_resource[0].name[5:]), + }, context=context) + return True project() class users(osv.osv): @@ -836,6 +937,33 @@ class task(osv.osv): res = super(task, self).unlink(cr, uid, ids, context) return res + def _generate_task(self, cr, uid, tasks, ident=4, context=None): + context = context or {} + result = "" + ident = ' '*ident + for task in tasks: + if task.state in ('done','cancelled'): + continue + result += ''' +%sdef Task_%s(): +%s todo = \"%.2fH\" +%s effort = \"%.2fH\"''' % (ident,task.id, ident,task.remaining_hours, ident,task.total_hours) + start = [] + for t2 in task.parent_ids: + start.append("up.Task_%s.end" % (t2.id,)) + if start: + result += ''' +%s start = max(%s) +''' % (ident,','.join(start)) + + if task.user_id: + result += ''' +%s resource = %s +''' % (ident, 'User_'+str(task.user_id.id)) + + result += "\n" + return result + task() class project_work(osv.osv): diff --git a/addons/project/project_demo.xml b/addons/project/project_demo.xml index f2ff9413063..ac4bc14c701 100644 --- a/addons/project/project_demo.xml +++ b/addons/project/project_demo.xml @@ -272,6 +272,7 @@ Study + Prototype + 20 @@ -279,12 +280,14 @@ Specific Developments + 30 Install, data import, configuration + @@ -292,7 +295,7 @@ 38.0 38.0 - + BoM, After sales returns, interventions. Traceability. Specific adaptation to MRP @@ -302,8 +305,8 @@ 16.0 16.0 + - Data importation + Doc @@ -312,8 +315,8 @@ 16.0 16.0 + - Modifications asked by the customer. @@ -323,18 +326,17 @@ 16.0 16.0 - + 0 Customer analysis + Architecture - 12-17-2011 15 8.0 8.0 - + Internal testing + Software Install @@ -343,7 +345,7 @@ 16.0 16.0 - + 2 Analysis, Data Importation @@ -354,7 +356,7 @@ 20 16.0 16.0 - + Parameters @@ -365,12 +367,16 @@ 20 32.0 32.0 - + open Start of the doc redaction + MRP + + + + diff --git a/addons/project_long_term/project_long_term.py b/addons/project_long_term/project_long_term.py index 8588b90f5a2..f7e23c29a58 100644 --- a/addons/project_long_term/project_long_term.py +++ b/addons/project_long_term/project_long_term.py @@ -23,7 +23,6 @@ from datetime import datetime from tools.translate import _ from osv import fields, osv from resource.faces import task as Task -from operator import itemgetter class project_phase(osv.osv): _name = "project.phase" @@ -223,65 +222,7 @@ class project(osv.osv): _inherit = "project.project" _columns = { 'phase_ids': fields.one2many('project.phase', 'project_id', "Project Phases"), - 'resource_calendar_id': fields.many2one('resource.calendar', 'Working Time', help="Timetable working hours to adjust the gantt diagram report", states={'close':[('readonly',True)]} ), } - def _schedule_header(self, cr, uid, ids, context=None): - context = context or {} - if type(ids) in (long, int,): - ids = [ids] - projects = self.browse(cr, uid, ids, context=context) - - for project in projects: - if not project.members: - raise osv.except_osv(_('Warning !'),_("You must assign members on the project '%s' !") % (project.name,)) - - resource_pool = self.pool.get('resource.resource') - - result = "from resource.faces import *\n" - result += "import datetime\n" - for project in self.browse(cr, uid, ids, context=context): - u_ids = [i.id for i in project.members] - for task in project.tasks: - if task.state in ('done','cancelled'): - continue - if task.user_id and (task.user_id.id not in u_ids): - u_ids.append(task.user_id.id) - calendar_id = project.resource_calendar_id and project.resource_calendar_id.id or False - resource_objs = resource_pool.generate_resources(cr, uid, u_ids, calendar_id, context=context) - for key, vals in resource_objs.items(): - result +=''' -class User_%s(Resource): - efficiency = %s -''' % (key, vals.get('efficiency', False)) - - result += ''' -def Project(): - ''' - return result - - def _schedule_project(self, cr, uid, project, context=None): - resource_pool = self.pool.get('resource.resource') - calendar_id = project.resource_calendar_id and project.resource_calendar_id.id or False - working_days = resource_pool.compute_working_calendar(cr, uid, calendar_id, context=context) - # TODO: check if we need working_..., default values are ok. - result = """ - def Project_%d(): - start = \'%s\' - working_days = %s - resource = %s -""" % ( - project.id, - project.date_start, working_days, - '|'.join(['User_'+str(x.id) for x in project.members]) - ) - vacation = calendar_id and tuple(resource_pool.compute_vacation(cr, uid, calendar_id, context=context)) or False - if vacation: - result+= """ - vacation = %s -""" % ( vacation, ) - return result - - def schedule_phases(self, cr, uid, ids, context=None): context = context or {} if type(ids) in (long, int,): @@ -321,45 +262,6 @@ def Project(): 'date_end': p.end.strftime('%Y-%m-%d %H:%M:%S') }, context=context) return True - - #TODO: DO Resource allocation and compute availability - def compute_allocation(self, rc, uid, ids, start_date, end_date, context=None): - if context == None: - context = {} - allocation = {} - return allocation - - def schedule_tasks(self, cr, uid, ids, context=None): - context = context or {} - if type(ids) in (long, int,): - ids = [ids] - projects = self.browse(cr, uid, ids, context=context) - result = self._schedule_header(cr, uid, ids, context=context) - for project in projects: - result += self._schedule_project(cr, uid, project, context=context) - result += self.pool.get('project.task')._generate_task(cr, uid, project.tasks, ident=4, context=context) - - local_dict = {} - exec result in local_dict - projects_gantt = Task.BalancedProject(local_dict['Project']) - - for project in projects: - project_gantt = getattr(projects_gantt, 'Project_%d' % (project.id,)) - for task in project.tasks: - if task.state in ('done','cancelled'): - continue - - p = getattr(project_gantt, 'Task_%d' % (task.id,)) - - self.pool.get('project.task').write(cr, uid, [task.id], { - 'date_start': p.start.strftime('%Y-%m-%d %H:%M:%S'), - 'date_end': p.end.strftime('%Y-%m-%d %H:%M:%S') - }, context=context) - if (not task.user_id) and (p.booked_resource): - self.pool.get('project.task').write(cr, uid, [task.id], { - 'user_id': int(p.booked_resource[0].name[5:]), - }, context=context) - return True project() class project_task(osv.osv): @@ -367,30 +269,4 @@ class project_task(osv.osv): _columns = { 'phase_id': fields.many2one('project.phase', 'Project Phase'), } - def _generate_task(self, cr, uid, tasks, ident=4, context=None): - context = context or {} - result = "" - ident = ' '*ident - for task in tasks: - if task.state in ('done','cancelled'): - continue - result += ''' -%sdef Task_%s(): -%s todo = \"%.2fH\" -%s effort = \"%.2fH\"''' % (ident,task.id, ident,task.remaining_hours, ident,task.total_hours) - start = [] - for t2 in task.parent_ids: - start.append("up.Task_%s.end" % (t2.id,)) - if start: - result += ''' -%s start = max(%s) -''' % (ident,','.join(start)) - - if task.user_id: - result += ''' -%s resource = %s -''' % (ident, 'User_'+str(task.user_id.id)) - - result += "\n" - return result project_task()