1 # -*- coding: utf-8 -*-
2 ##############################################################################
4 # OpenERP, Open Source Management Solution
5 # Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
7 # This program is free software: you can redistribute it and/or modify
8 # it under the terms of the GNU Affero General Public License as
9 # published by the Free Software Foundation, either version 3 of the
10 # License, or (at your option) any later version.
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU Affero General Public License for more details.
17 # You should have received a copy of the GNU Affero General Public License
18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
20 ##############################################################################
22 from datetime import datetime, timedelta
23 from dateutil.relativedelta import relativedelta
24 from tools.translate import _
25 from osv import fields, osv
26 from resource.faces import task as Task
28 from new import classobj
32 class project_phase(osv.osv):
33 _name = "project.phase"
34 _description = "Project Phase"
36 def _check_recursion(self, cr, uid, ids, context=None):
40 data_phase = self.browse(cr, uid, ids[0], context=context)
41 prev_ids = data_phase.previous_phase_ids
42 next_ids = data_phase.next_phase_ids
43 # it should neither be in prev_ids nor in next_ids
44 if (data_phase in prev_ids) or (data_phase in next_ids):
46 ids = [id for id in prev_ids if id in next_ids]
47 # both prev_ids and next_ids must be unique
51 prev_ids = [rec.id for rec in prev_ids]
52 next_ids = [rec.id for rec in next_ids]
55 cr.execute('SELECT distinct prv_phase_id FROM project_phase_rel WHERE next_phase_id IN %s', (tuple(prev_ids),))
56 prv_phase_ids = filter(None, map(lambda x: x[0], cr.fetchall()))
57 if data_phase.id in prv_phase_ids:
59 ids = [id for id in prv_phase_ids if id in next_ids]
62 prev_ids = prv_phase_ids
65 cr.execute('SELECT distinct next_phase_id FROM project_phase_rel WHERE prv_phase_id IN %s', (tuple(next_ids),))
66 next_phase_ids = filter(None, map(lambda x: x[0], cr.fetchall()))
67 if data_phase.id in next_phase_ids:
69 ids = [id for id in next_phase_ids if id in prev_ids]
72 next_ids = next_phase_ids
75 def _check_dates(self, cr, uid, ids, context=None):
76 for phase in self.read(cr, uid, ids, ['date_start', 'date_end'], context=context):
77 if phase['date_start'] and phase['date_end'] and phase['date_start'] > phase['date_end']:
81 def _check_constraint_start(self, cr, uid, ids, context=None):
82 phase = self.read(cr, uid, ids[0], ['date_start', 'constraint_date_start'], context=context)
83 if phase['date_start'] and phase['constraint_date_start'] and phase['date_start'] < phase['constraint_date_start']:
87 def _check_constraint_end(self, cr, uid, ids, context=None):
88 phase = self.read(cr, uid, ids[0], ['date_end', 'constraint_date_end'], context=context)
89 if phase['date_end'] and phase['constraint_date_end'] and phase['date_end'] > phase['constraint_date_end']:
93 def _get_default_uom_id(self, cr, uid):
94 model_data_obj = self.pool.get('ir.model.data')
95 model_data_id = model_data_obj._get_id(cr, uid, 'product', 'uom_hour')
96 return model_data_obj.read(cr, uid, [model_data_id], ['res_id'])[0]['res_id']
98 def _compute(self, cr, uid, ids, field_name, arg, context=None):
102 for phase in self.browse(cr, uid, ids, context=context):
104 for task in phase.task_ids:
105 tot += task.planned_hours
110 'name': fields.char("Name", size=64, required=True),
111 'date_start': fields.date('Start Date', help="It's computed by the scheduler according the project date or the end date of the previous phase.", states={'done':[('readonly',True)], 'cancelled':[('readonly',True)]}),
112 'date_end': fields.date('End Date', help=" It's computed by the scheduler according to the start date and the duration.", states={'done':[('readonly',True)], 'cancelled':[('readonly',True)]}),
113 'constraint_date_start': fields.date('Minimum Start Date', help='force the phase to start after this date', states={'done':[('readonly',True)], 'cancelled':[('readonly',True)]}),
114 'constraint_date_end': fields.date('Deadline', help='force the phase to finish before this date', states={'done':[('readonly',True)], 'cancelled':[('readonly',True)]}),
115 'project_id': fields.many2one('project.project', 'Project', required=True),
116 'next_phase_ids': fields.many2many('project.phase', 'project_phase_rel', 'prv_phase_id', 'next_phase_id', 'Next Phases', states={'cancelled':[('readonly',True)]}),
117 'previous_phase_ids': fields.many2many('project.phase', 'project_phase_rel', 'next_phase_id', 'prv_phase_id', 'Previous Phases', states={'cancelled':[('readonly',True)]}),
118 'sequence': fields.integer('Sequence', help="Gives the sequence order when displaying a list of phases."),
119 'duration': fields.float('Duration', required=True, help="By default in days", states={'done':[('readonly',True)], 'cancelled':[('readonly',True)]}),
120 'product_uom': fields.many2one('product.uom', 'Duration UoM', required=True, help="UoM (Unit of Measure) is the unit of measurement for Duration", states={'done':[('readonly',True)], 'cancelled':[('readonly',True)]}),
121 'task_ids': fields.one2many('project.task', 'phase_id', "Project Tasks", states={'done':[('readonly',True)], 'cancelled':[('readonly',True)]}),
122 'resource_ids': fields.one2many('project.resource.allocation', 'phase_id', "Project Resources",states={'done':[('readonly',True)], 'cancelled':[('readonly',True)]}),
123 'responsible_id': fields.many2one('res.users', 'Responsible', states={'done':[('readonly',True)], 'cancelled':[('readonly',True)]}),
124 'state': fields.selection([('draft', 'Draft'), ('open', 'In Progress'), ('pending', 'Pending'), ('cancelled', 'Cancelled'), ('done', 'Done')], 'State', readonly=True, required=True,
125 help='If the phase is created the state \'Draft\'.\n If the phase is started, the state becomes \'In Progress\'.\n If review is needed the phase is in \'Pending\' state.\
126 \n If the phase is over, the states is set to \'Done\'.'),
127 'total_hours': fields.function(_compute, method=True, string='Total Hours'),
130 'responsible_id': lambda obj,cr,uid,context: uid,
133 'product_uom': lambda self,cr,uid,c: self.pool.get('product.uom').search(cr, uid, [('name', '=', _('Day'))], context=c)[0]
135 _order = "project_id, date_start, sequence, name"
137 (_check_recursion,'Loops in phases not allowed',['next_phase_ids', 'previous_phase_ids']),
138 (_check_dates, 'Phase start-date must be lower than phase end-date.', ['date_start', 'date_end']),
141 def onchange_project(self, cr, uid, ids, project, context=None):
143 result['date_start'] = False
144 project_obj = self.pool.get('project.project')
146 project_id = project_obj.browse(cr, uid, project, context=context)
147 result['date_start'] = project_id.date_start
148 return {'value': result}
151 def _check_date_start(self, cr, uid, phase, date_end, context=None):
153 Check And Compute date_end of phase if change in date_start < older time.
155 uom_obj = self.pool.get('product.uom')
156 resource_obj = self.pool.get('resource.resource')
157 cal_obj = self.pool.get('resource.calendar')
158 calendar_id = phase.project_id.resource_calendar_id and phase.project_id.resource_calendar_id.id or False
159 resource_id = resource_obj.search(cr, uid, [('user_id', '=', phase.responsible_id.id)])
161 res = resource_obj.read(cr, uid, resource_id, ['calendar_id'], context=context)[0]
162 cal_id = res.get('calendar_id', False) and res.get('calendar_id')[0] or False
165 default_uom_id = self._get_default_uom_id(cr, uid)
166 avg_hours = uom_obj._compute_qty(cr, uid, phase.product_uom.id, phase.duration, default_uom_id)
167 work_times = cal_obj.interval_min_get(cr, uid, calendar_id, date_end, avg_hours or 0.0, resource_id and resource_id[0] or False)
168 dt_start = work_times[0][0].strftime('%Y-%m-%d')
169 self.write(cr, uid, [phase.id], {'date_start': dt_start, 'date_end': date_end.strftime('%Y-%m-%d')}, context=context)
171 def _check_date_end(self, cr, uid, phase, date_start, context=None):
173 Check And Compute date_end of phase if change in date_end > older time.
175 uom_obj = self.pool.get('product.uom')
176 resource_obj = self.pool.get('resource.resource')
177 cal_obj = self.pool.get('resource.calendar')
178 calendar_id = phase.project_id.resource_calendar_id and phase.project_id.resource_calendar_id.id or False
179 resource_id = resource_obj.search(cr, uid, [('user_id', '=', phase.responsible_id.id)], context=context)
181 res = resource_obj.read(cr, uid, resource_id, ['calendar_id'], context=context)[0]
182 cal_id = res.get('calendar_id', False) and res.get('calendar_id')[0] or False
185 default_uom_id = self._get_default_uom_id(cr, uid)
186 avg_hours = uom_obj._compute_qty(cr, uid, phase.product_uom.id, phase.duration, default_uom_id)
187 work_times = cal_obj.interval_get(cr, uid, calendar_id, date_start, avg_hours or 0.0, resource_id and resource_id[0] or False)
188 dt_end = work_times[-1][1].strftime('%Y-%m-%d')
189 self.write(cr, uid, [phase.id], {'date_start': date_start.strftime('%Y-%m-%d'), 'date_end': dt_end}, context=context)
191 def copy(self, cr, uid, id, default=None, context=None):
194 if not default.get('name', False):
195 default['name'] = self.browse(cr, uid, id, context=context).name + _(' (copy)')
196 return super(project_phase, self).copy(cr, uid, id, default, context)
198 def set_draft(self, cr, uid, ids, *args):
199 self.write(cr, uid, ids, {'state': 'draft'})
202 def set_open(self, cr, uid, ids, *args):
203 self.write(cr, uid, ids, {'state': 'open'})
206 def set_pending(self, cr, uid, ids, *args):
207 self.write(cr, uid, ids, {'state': 'pending'})
210 def set_cancel(self, cr, uid, ids, *args):
211 self.write(cr, uid, ids, {'state': 'cancelled'})
214 def set_done(self, cr, uid, ids, *args):
215 self.write(cr, uid, ids, {'state': 'done'})
218 def generate_phase(self, cr, uid, ids, f, parent=False, context=None):
222 resource_pool = self.pool.get('resource.resource')
223 data_pool = self.pool.get('ir.model.data')
224 resource_allocation_pool = self.pool.get('project.resource.allocation')
225 uom_pool = self.pool.get('product.uom')
226 task_pool = self.pool.get('project.task')
227 data_model, day_uom_id = data_pool.get_object_reference(cr, uid, 'product', 'uom_day')
228 for phase in self.browse(cr, uid, ids, context=context):
229 avg_days = uom_pool._compute_qty(cr, uid, phase.product_uom.id, phase.duration, day_uom_id)
230 duration = str(avg_days) + 'd'
231 # Create a new project for each phase
232 str_resource = ('%s & '*len(phase.resource_ids))[:-2]
233 str_vals = str_resource % tuple(map(lambda x: 'Resource_%s'%x.resource_id.id, phase.resource_ids))
235 # Phases Defination for the Project
241 '''%(phase.id, phase.name, duration, str_vals or False)
243 # Recalculate date_start and date_end
244 # according to constraints on date start and date end on phase
247 if phase.constraint_date_start:
248 start_date = datetime.strptime(phase.constraint_date_start, '%Y-%m-%d')
251 '''%(datetime.strftime(start_date, "%Y-%m-%d"))
254 start = 'up.Phase_%s.end' % (parent.id)
259 start = phase.project_id.date_start or phase.date_start
264 if phase.constraint_date_end :
265 end_date= datetime.strptime(phase.constraint_date_end, '%Y-%m-%d')
268 '''%(datetime.strftime(end_date, "%Y-%m-%d"))
271 #start = datetime.strftime((datetime.strptime(start, "%Y-%m-%d")), "%Y-%m-%d")
273 phase_ids.append(phase.id)
276 todo_task_ids = task_pool.search(cr, uid, [('id', 'in', map(lambda x : x.id, phase.task_ids)),
277 ('state', 'in', ['draft', 'open', 'pending'])
280 for task in task_pool.browse(cr, uid, todo_task_ids, context=context):
281 s += task_pool.generate_task(cr, uid, task.id, parent=parent, flag=False, context=context)
284 task_ids.append(task.id)
287 # Recursive call till all the next phases scheduled
288 for next_phase in phase.next_phase_ids:
289 if next_phase.state in ['draft', 'open', 'pending']:
290 rf, rphase_ids = self.generate_phase(cr, uid, [next_phase.id], f = '', parent=phase, context=context)
292 phase_ids += rphase_ids
297 def schedule_tasks(self, cr, uid, ids, context=None):
299 Schedule tasks base on faces lib
303 if type(ids) in (long, int,):
305 task_pool = self.pool.get('project.task')
306 resource_pool = self.pool.get('resource.resource')
307 data_pool = self.pool.get('ir.model.data')
308 resource_allocation_pool = self.pool.get('project.resource.allocation')
310 for phase in self.browse(cr, uid, ids, context=context):
311 project = phase.project_id
312 calendar_id = project.resource_calendar_id and project.resource_calendar_id.id or False
313 start_date = project.date_start
314 #Creating resources using the member of the Project
315 u_ids = [i.id for i in project.members]
316 resource_objs = resource_pool.generate_resources(cr, uid, u_ids, calendar_id, context=context)
317 start_date = datetime.strftime((datetime.strptime(start_date, "%Y-%m-%d")), "%Y-%m-%d")
320 minimum_time_unit = 1
322 working_hours_per_day = 24
323 working_days_per_week = 7
324 working_days_per_month = 30
325 working_days_per_year = 365
329 working_hours_per_day = 8 #TODO: it should be come from calendars
330 working_days_per_week = 5
331 working_days_per_month = 20
332 working_days_per_year = 200
333 vacation = tuple(resource_pool.compute_vacation(cr, uid, calendar_id, context=context))
335 working_days = resource_pool.compute_working_calendar(cr, uid, calendar_id, context=context)
338 # Creating Resources for the Project
339 for key, vals in resource_objs.items():
341 class Resource_%s(Resource):
345 '''%(key, vals.get('name',False), vals.get('vacation', False), vals.get('efficiency', False))
347 # Create a new project for each phase
350 from resource.faces import Resource
353 minimum_time_unit = %s
354 working_hours_per_day = %s
355 working_days_per_week = %s
356 working_days_per_month = %s
357 working_days_per_year = %s
360 '''%(phase.id, phase.name, start, minimum_time_unit, working_hours_per_day, working_days_per_week, working_days_per_month, working_days_per_year, vacation, working_days )
364 todo_task_ids = task_pool.search(cr, uid, [('id', 'in', map(lambda x : x.id, phase.task_ids)),
365 ('state', 'in', ['draft', 'open', 'pending'])
367 for task in task_pool.browse(cr, uid, todo_task_ids, context=context):
368 func_str += task_pool.generate_task(cr, uid, task.id, parent=parent, flag=True, context=context)
371 task_ids.append(task.id)
373 #Temp File to test the Code for the Allocation
374 # fn = '/home/tiny/Desktop/plt.py'
376 # fp.writelines(func_str)
379 # Allocating Memory for the required Project and Pahses and Resources
381 Phase = eval('Phase_%d' % phase.id)
382 phase = Task.BalancedProject(Phase)
384 for task_id in task_ids:
385 task = eval("phase.Task_%d" % task_id)
386 start_date = task.start.to_datetime()
387 end_date = task.end.to_datetime()
389 task_pool.write(cr, uid, [task_id], {
390 'date_start': start_date.strftime('%Y-%m-%d'),
391 'date_end': end_date.strftime('%Y-%m-%d')
396 class project_resource_allocation(osv.osv):
397 _name = 'project.resource.allocation'
398 _description = 'Project Resource Allocation'
399 _rec_name = 'resource_id'
401 def get_name(self, cr, uid, ids, field_name, arg, context=None):
403 for allocation in self.browse(cr, uid, ids, context=context):
404 name = allocation.phase_id.name
405 name += ' (%s%%)' %(allocation.useability)
406 res[allocation.id] = name
409 'name': fields.function(get_name, method=True, type='char', size=256),
410 'resource_id': fields.many2one('resource.resource', 'Resource', required=True),
411 'phase_id': fields.many2one('project.phase', 'Project Phase', ondelete='cascade', required=True),
412 'project_id': fields.related('phase_id', 'project_id', type='many2one', relation="project.project", string='Project', store=True),
413 'user_id': fields.related('resource_id', 'user_id', type='many2one', relation="res.users", string='User'),
414 'date_start': fields.date('Start Date', help="Starting Date"),
415 'date_end': fields.date('End Date', help="Ending Date"),
416 'useability': fields.float('Availability', help="Availability of this resource for this project phase in percentage (=50%)"),
422 project_resource_allocation()
424 class project(osv.osv):
425 _inherit = "project.project"
427 'phase_ids': fields.one2many('project.phase', 'project_id', "Project Phases"),
428 'resource_calendar_id': fields.many2one('resource.calendar', 'Working Time', help="Timetable working hours to adjust the gantt diagram report", states={'close':[('readonly',True)]} ),
430 def generate_members(self, cr, uid, ids, context=None):
432 Return a list of Resource Class objects for the resources allocated to the phase.
435 resource_pool = self.pool.get('resource.resource')
436 for project in self.browse(cr, uid, ids, context=context):
437 user_ids = map(lambda x:x.id, project.members)
438 calendar_id = project.resource_calendar_id and project.resource_calendar_id.id or False
439 resource_objs = resource_pool.generate_resources(cr, uid, user_ids, calendar_id, context=context)
440 res[project.id] = resource_objs
443 def schedule_phases(self, cr, uid, ids, context=None):
445 Schedule phase base on faces lib
449 if type(ids) in (long, int,):
451 phase_pool = self.pool.get('project.phase')
452 task_pool = self.pool.get('project.task')
453 resource_pool = self.pool.get('resource.resource')
454 data_pool = self.pool.get('ir.model.data')
455 resource_allocation_pool = self.pool.get('project.resource.allocation')
456 uom_pool = self.pool.get('product.uom')
457 data_model, day_uom_id = data_pool.get_object_reference(cr, uid, 'product', 'uom_day')
459 for project in self.browse(cr, uid, ids, context=context):
460 root_phase_ids = phase_pool.search(cr, uid, [('project_id', '=', project.id),
461 ('state', 'in', ['draft', 'open', 'pending']),
462 ('previous_phase_ids', '=', False)
464 calendar_id = project.resource_calendar_id and project.resource_calendar_id.id or False
465 start_date = project.date_start
467 # start_date = datetime.strftime((datetime.strptime(start_date, "%Y-%m-%d")), "%Y-%m-%d")
468 #Creating resources using the member of the Project
469 u_ids = [i.id for i in project.members]
470 resource_objs = resource_pool.generate_resources(cr, uid, u_ids, calendar_id, context=context)
473 minimum_time_unit = 1
475 working_hours_per_day = 24
476 working_days_per_week = 7
477 working_days_per_month = 30
478 working_days_per_year = 365
482 working_hours_per_day = 8 #TODO: it should be come from calendars
483 working_days_per_week = 5
484 working_days_per_month = 20
485 working_days_per_year = 200
486 vacation = tuple(resource_pool.compute_vacation(cr, uid, calendar_id, context=context))
488 working_days = resource_pool.compute_working_calendar(cr, uid, calendar_id, context=context)
491 # Creating Resources for the Project
492 for key, vals in resource_objs.items():
494 class Resource_%s(Resource):
498 '''%(key, vals.get('name',False), vals.get('vacation', False), vals.get('efficiency', False))
500 # Create a new project for each phase
503 from resource.faces import Resource
506 minimum_time_unit = %s
507 working_hours_per_day = %s
508 working_days_per_week = %s
509 working_days_per_month = %s
510 working_days_per_year = %s
513 '''%(project.id, project.name, start, minimum_time_unit, working_hours_per_day, working_days_per_week, working_days_per_month, working_days_per_year, vacation, working_days )
517 for root_phase in phase_pool.browse(cr, uid, root_phase_ids, context=context):
518 phases, child_phase_ids = phase_pool.generate_phase(cr, uid, [root_phase.id], '', context=context)
520 phase_ids += child_phase_ids
521 #Temp File to test the Code for the Allocation
522 fn = '/home/tiny/Desktop/plt.py'
524 fp.writelines(func_str)
527 # Allocating Memory for the required Project and Pahses and Resources
529 Project = eval('Project_%d' % project.id)
530 project = Task.BalancedProject(Project)
532 for phase_id in phase_ids:
533 act_phase = phase_pool.browse(cr, uid, phase_id, context=context)
534 resources = act_phase.resource_ids
535 phase = eval("project.Phase_%d" % phase_id)
536 start_date = phase.start.to_datetime()
537 end_date = phase.end.to_datetime()
540 for res in resources:
542 vals.update({'date_start' : start_date })
543 vals.update({'date_end' : end_date})
544 resource_allocation_pool.write(cr, uid, res.id, vals, context=context)
545 if act_phase.task_ids:
546 for task in act_phase.task_ids:
548 #Getting values of the Tasks
549 temp = eval("phase.Task_%s"%task.id)
550 if temp.booked_resource:
551 res_name = temp.booked_resource[0].title
552 res_id = resource_pool.search(cr, uid,[('name','=',res_name)], context = context)
554 res = resource_pool.browse(cr, uid, res_id[0], context = context)
555 vals.update({'user_id' : res.user_id.id})
557 vals.update({'date_start' : temp.start.strftime('%Y-%m-%d %H:%M:%S')})
558 vals.update({'date_end' : temp.end.strftime('%Y-%m-%d %H:%M:%S')})
559 task_pool.write(cr, uid, task.id, vals, context=context)
562 phase_pool.write(cr, uid, [phase_id], {
563 'date_start': start_date.strftime('%Y-%m-%d'),
564 'date_end': end_date.strftime('%Y-%m-%d')
568 #TODO: DO Resource allocation and compute availability
569 def compute_allocation(self, rc, uid, ids, start_date, end_date, context=None):
575 def schedule_tasks(self, cr, uid, ids, context=None):
577 Schedule task base on faces lib
581 if type(ids) in (long, int,):
583 task_pool = self.pool.get('project.task')
584 resource_pool = self.pool.get('resource.resource')
585 data_pool = self.pool.get('ir.model.data')
586 resource_allocation_pool = self.pool.get('project.resource.allocation')
587 uom_pool = self.pool.get('product.uom')
588 data_model, day_uom_id = data_pool.get_object_reference(cr, uid, 'product', 'uom_day')
590 for project in self.browse(cr, uid, ids, context=context):
591 calendar_id = project.resource_calendar_id and project.resource_calendar_id.id or False
592 start_date = project.date_start
593 #Creating resources using the member of the Project
594 u_ids = [i.id for i in project.members]
595 resource_objs = resource_pool.generate_resources(cr, uid, u_ids, calendar_id, context=context)
596 start_date = datetime.strftime((datetime.strptime(start_date, "%Y-%m-%d")), "%Y-%m-%d")
599 minimum_time_unit = 1
601 working_hours_per_day = 24
602 working_days_per_week = 7
603 working_days_per_month = 30
604 working_days_per_year = 365
608 working_hours_per_day = 8 #TODO: it should be come from calendars
609 working_days_per_week = 5
610 working_days_per_month = 20
611 working_days_per_year = 200
612 vacation = tuple(resource_pool.compute_vacation(cr, uid, calendar_id, context=context))
614 working_days = resource_pool.compute_working_calendar(cr, uid, calendar_id, context=context)
617 # Creating Resources for the Project
618 for key, vals in resource_objs.items():
620 class Resource_%s(Resource):
624 '''%(key, vals.get('name',False), vals.get('vacation', False), vals.get('efficiency', False))
626 # Create a new project for each phase
629 from resource.faces import Resource
632 minimum_time_unit = %s
633 working_hours_per_day = %s
634 working_days_per_week = %s
635 working_days_per_month = %s
636 working_days_per_year = %s
639 '''%(project.id, project.name, start, minimum_time_unit, working_hours_per_day, working_days_per_week, working_days_per_month, working_days_per_year, vacation, working_days )
643 todo_task_ids = task_pool.search(cr, uid, [('project_id', '=', project.id),
644 ('state', 'in', ['draft', 'open', 'pending'])
647 for task in task_pool.browse(cr, uid, todo_task_ids, context=context):
648 func_str += task_pool.generate_task(cr, uid, task.id, parent=parent, flag=True,context=context)
651 task_ids.append(task.id)
653 #Temp File to test the Code for the Allocation
654 # fn = '/home/tiny/Desktop/plt.py'
656 # fp.writelines(func_str)
659 # Allocating Memory for the required Project and Pahses and Resources
661 Project = eval('Project_%d' % project.id)
662 project = Task.BalancedProject(Project)
663 for task_id in task_ids:
664 task = eval("project.Task_%d" % task_id)
665 start_date = task.start.to_datetime()
666 end_date = task.end.to_datetime()
668 task_pool.write(cr, uid, [task_id], {
669 'date_start': start_date.strftime('%Y-%m-%d'),
670 'date_end': end_date.strftime('%Y-%m-%d')
676 class resource_resource(osv.osv):
677 _inherit = "resource.resource"
678 def search(self, cr, uid, args, offset=0, limit=None, order=None, context=None, count=False):
681 if context.get('project_id',False):
682 project_pool = self.pool.get('project.project')
683 project_rec = project_pool.browse(cr, uid, context['project_id'], context=context)
684 user_ids = [user_id.id for user_id in project_rec.members]
685 args.append(('user_id','in',user_ids))
686 return super(resource_resource, self).search(cr, uid, args, offset, limit, order, context, count)
690 class project_task(osv.osv):
691 _inherit = "project.task"
693 'phase_id': fields.many2one('project.phase', 'Project Phase'),
699 def generate_task(self, cr, uid, task_id, parent=False, flag=False, context=None):
702 phase_pool = self.pool.get('project.phase')
703 resource_pool = self.pool.get('resource.resource')
704 resource_allocation_pool = self.pool.get('project.resource.allocation')
705 task = self.browse(cr, uid, task_id, context=context)
706 duration = str(task.planned_hours )+ 'H'
708 if task.phase_id.resource_ids:
709 str_resource = ('%s | '*len(task.phase_id.resource_ids))[:-2]
710 str_resource = str_resource % tuple(map(lambda x: 'Resource_%s'%x.resource_id.id, task.phase_id.resource_ids))
711 # Task Defination for the Phase of the Project
718 '''%(task.id, task.name, duration, str_resource)
719 #start = datetime.strftime((datetime.strptime(start, "%Y-%m-%d")), "%Y-%m-%d")
726 '''%(task.id, task.name, duration, str_resource)
730 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: