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'])
279 for task in task_pool.browse(cr, uid, todo_task_ids, context=context):
280 s += task_pool.generate_task(cr, uid, task.id, parent=parent, flag=False, context=context)
283 task_ids.append(task.id)
286 # Recursive call till all the next phases scheduled
287 for next_phase in phase.next_phase_ids:
288 if next_phase.state in ['draft', 'open', 'pending']:
289 rf, rphase_ids = self.generate_phase(cr, uid, [next_phase.id], f = '', parent=phase, context=context)
291 phase_ids += rphase_ids
296 def schedule_tasks(self, cr, uid, ids, context=None):
298 Schedule tasks base on faces lib
302 if type(ids) in (long, int,):
304 task_pool = self.pool.get('project.task')
305 resource_pool = self.pool.get('resource.resource')
306 data_pool = self.pool.get('ir.model.data')
307 resource_allocation_pool = self.pool.get('project.resource.allocation')
309 for phase in self.browse(cr, uid, ids, context=context):
310 project = phase.project_id
311 calendar_id = project.resource_calendar_id and project.resource_calendar_id.id or False
312 start_date = project.date_start
313 #Creating resources using the member of the Project
314 u_ids = [i.id for i in project.members]
315 resource_objs = resource_pool.generate_resources(cr, uid, u_ids, calendar_id, context=context)
316 start_date = datetime.strftime((datetime.strptime(start_date, "%Y-%m-%d")), "%Y-%m-%d")
319 minimum_time_unit = 1
321 working_hours_per_day = 24
322 working_days_per_week = 7
323 working_days_per_month = 30
324 working_days_per_year = 365
328 working_hours_per_day = 8 #TODO: it should be come from calendars
329 working_days_per_week = 5
330 working_days_per_month = 20
331 working_days_per_year = 200
332 vacation = tuple(resource_pool.compute_vacation(cr, uid, calendar_id, context=context))
334 working_days = resource_pool.compute_working_calendar(cr, uid, calendar_id, context=context)
337 # Creating Resources for the Project
338 for key, vals in resource_objs.items():
340 class Resource_%s(Resource):
344 '''%(key, vals.get('name',False), vals.get('vacation', False), vals.get('efficiency', False))
346 # Create a new project for each phase
349 from resource.faces import Resource
352 minimum_time_unit = %s
353 working_hours_per_day = %s
354 working_days_per_week = %s
355 working_days_per_month = %s
356 working_days_per_year = %s
359 '''%(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 )
363 todo_task_ids = task_pool.search(cr, uid, [('id', 'in', map(lambda x : x.id, phase.task_ids)),
364 ('state', 'in', ['draft', 'open', 'pending'])
366 for task in task_pool.browse(cr, uid, todo_task_ids, context=context):
367 func_str += task_pool.generate_task(cr, uid, task.id, parent=parent, flag=True, context=context)
370 task_ids.append(task.id)
372 #Temp File to test the Code for the Allocation
373 # fn = '/home/tiny/Desktop/plt.py'
375 # fp.writelines(func_str)
378 # Allocating Memory for the required Project and Pahses and Resources
380 Phase = eval('Phase_%d' % phase.id)
381 phase = Task.BalancedProject(Phase)
383 for task_id in task_ids:
384 task = eval("phase.Task_%d" % task_id)
385 start_date = task.start.to_datetime()
386 end_date = task.end.to_datetime()
388 task_pool.write(cr, uid, [task_id], {
389 'date_start': start_date.strftime('%Y-%m-%d'),
390 'date_end': end_date.strftime('%Y-%m-%d')
395 class project_resource_allocation(osv.osv):
396 _name = 'project.resource.allocation'
397 _description = 'Project Resource Allocation'
398 _rec_name = 'resource_id'
400 def get_name(self, cr, uid, ids, field_name, arg, context=None):
402 for allocation in self.browse(cr, uid, ids, context=context):
403 name = allocation.phase_id.name
404 name += ' (%s%%)' %(allocation.useability)
405 res[allocation.id] = name
408 'name': fields.function(get_name, method=True, type='char', size=256),
409 'resource_id': fields.many2one('resource.resource', 'Resource', required=True),
410 'phase_id': fields.many2one('project.phase', 'Project Phase', ondelete='cascade', required=True),
411 'project_id': fields.related('phase_id', 'project_id', type='many2one', relation="project.project", string='Project', store=True),
412 'user_id': fields.related('resource_id', 'user_id', type='many2one', relation="res.users", string='User'),
413 'date_start': fields.date('Start Date', help="Starting Date"),
414 'date_end': fields.date('End Date', help="Ending Date"),
415 'useability': fields.float('Availability', help="Availability of this resource for this project phase in percentage (=50%)"),
421 project_resource_allocation()
423 class project(osv.osv):
424 _inherit = "project.project"
426 'phase_ids': fields.one2many('project.phase', 'project_id', "Project Phases"),
427 'resource_calendar_id': fields.many2one('resource.calendar', 'Working Time', help="Timetable working hours to adjust the gantt diagram report", states={'close':[('readonly',True)]} ),
429 def generate_members(self, cr, uid, ids, context=None):
431 Return a list of Resource Class objects for the resources allocated to the phase.
434 resource_pool = self.pool.get('resource.resource')
435 for project in self.browse(cr, uid, ids, context=context):
436 user_ids = map(lambda x:x.id, project.members)
437 calendar_id = project.resource_calendar_id and project.resource_calendar_id.id or False
438 resource_objs = resource_pool.generate_resources(cr, uid, user_ids, calendar_id, context=context)
439 res[project.id] = resource_objs
442 def schedule_phases(self, cr, uid, ids, context=None):
444 Schedule phase base on faces lib
448 if type(ids) in (long, int,):
450 phase_pool = self.pool.get('project.phase')
451 task_pool = self.pool.get('project.task')
452 resource_pool = self.pool.get('resource.resource')
453 data_pool = self.pool.get('ir.model.data')
454 resource_allocation_pool = self.pool.get('project.resource.allocation')
455 uom_pool = self.pool.get('product.uom')
456 data_model, day_uom_id = data_pool.get_object_reference(cr, uid, 'product', 'uom_day')
458 for project in self.browse(cr, uid, ids, context=context):
459 root_phase_ids = phase_pool.search(cr, uid, [('project_id', '=', project.id),
460 ('state', 'in', ['draft', 'open', 'pending']),
461 ('previous_phase_ids', '=', False)
463 calendar_id = project.resource_calendar_id and project.resource_calendar_id.id or False
464 start_date = project.date_start
466 # start_date = datetime.strftime((datetime.strptime(start_date, "%Y-%m-%d")), "%Y-%m-%d")
467 #Creating resources using the member of the Project
468 u_ids = [i.id for i in project.members]
469 resource_objs = resource_pool.generate_resources(cr, uid, u_ids, calendar_id, context=context)
472 minimum_time_unit = 1
474 working_hours_per_day = 24
475 working_days_per_week = 7
476 working_days_per_month = 30
477 working_days_per_year = 365
481 working_hours_per_day = 8 #TODO: it should be come from calendars
482 working_days_per_week = 5
483 working_days_per_month = 20
484 working_days_per_year = 200
485 vacation = tuple(resource_pool.compute_vacation(cr, uid, calendar_id, context=context))
487 working_days = resource_pool.compute_working_calendar(cr, uid, calendar_id, context=context)
490 # Creating Resources for the Project
491 for key, vals in resource_objs.items():
493 class Resource_%s(Resource):
497 '''%(key, vals.get('name',False), vals.get('vacation', False), vals.get('efficiency', False))
499 # Create a new project for each phase
502 from resource.faces import Resource
505 minimum_time_unit = %s
506 working_hours_per_day = %s
507 working_days_per_week = %s
508 working_days_per_month = %s
509 working_days_per_year = %s
512 '''%(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 )
515 for root_phase in phase_pool.browse(cr, uid, root_phase_ids, context=context):
516 phases, child_phase_ids = phase_pool.generate_phase(cr, uid, [root_phase.id], '', context=context)
518 phase_ids += child_phase_ids
519 #Temp File to test the Code for the Allocation
520 fn = '/home/tiny/Desktop/plt.py'
522 fp.writelines(func_str)
525 # Allocating Memory for the required Project and Pahses and Resources
527 Project = eval('Project_%d' % project.id)
528 project = Task.BalancedProject(Project)
530 for phase_id in phase_ids:
531 act_phase = phase_pool.browse(cr, uid, phase_id, context=context)
532 resources = act_phase.resource_ids
533 phase = eval("project.Phase_%d" % phase_id)
534 start_date = phase.start.to_datetime()
535 end_date = phase.end.to_datetime()
536 # Write the calculated dates back
537 # if act_phase.constraint_date_start and str(start_date) < act_phase.constraint_date_start:
538 # start_date = datetime.strptime(act_phase.constraint_date_start, '%Y-%m-%d')
540 # start_date = start_date
541 # if act_phase.constraint_date_end and str(end_date) > act_phase.constraint_date_end:
542 # end_date= datetime.strptime(act_phase.constraint_date_end, '%Y-%m-%d')
543 # date_start = act_phase.constraint_date_end
545 # end_date = start_date
546 # start_date = end_date
548 ctx.update({'scheduler': True})
550 for res in resources:
552 vals.update({'date_start' : start_date })
553 vals.update({'date_end' : end_date})
554 resource_allocation_pool.write(cr, uid, res.id, vals, context=ctx)
555 if act_phase.task_ids:
556 for task in act_phase.task_ids:
558 #Getting values of the Tasks
559 temp = eval("phase.Task_%s"%task.id)
560 vals.update({'date_start' : temp.start.strftime('%Y-%m-%d %H:%M:%S')})
561 vals.update({'date_end' : temp.end.strftime('%Y-%m-%d %H:%M:%S')})
562 task_pool.write(cr, uid, task.id, vals, context=ctx)
565 phase_pool.write(cr, uid, [phase_id], {
566 'date_start': start_date.strftime('%Y-%m-%d'),
567 'date_end': end_date.strftime('%Y-%m-%d')
571 #TODO: DO Resource allocation and compute availability
572 def compute_allocation(self, rc, uid, ids, start_date, end_date, context=None):
578 def schedule_tasks(self, cr, uid, ids, context=None):
580 Schedule task base on faces lib
584 if type(ids) in (long, int,):
586 task_pool = self.pool.get('project.task')
587 resource_pool = self.pool.get('resource.resource')
588 data_pool = self.pool.get('ir.model.data')
589 resource_allocation_pool = self.pool.get('project.resource.allocation')
590 uom_pool = self.pool.get('product.uom')
591 data_model, day_uom_id = data_pool.get_object_reference(cr, uid, 'product', 'uom_day')
593 for project in self.browse(cr, uid, ids, context=context):
594 calendar_id = project.resource_calendar_id and project.resource_calendar_id.id or False
595 start_date = project.date_start
596 #Creating resources using the member of the Project
597 u_ids = [i.id for i in project.members]
598 resource_objs = resource_pool.generate_resources(cr, uid, u_ids, calendar_id, context=context)
599 start_date = datetime.strftime((datetime.strptime(start_date, "%Y-%m-%d")), "%Y-%m-%d")
602 minimum_time_unit = 1
604 working_hours_per_day = 24
605 working_days_per_week = 7
606 working_days_per_month = 30
607 working_days_per_year = 365
611 working_hours_per_day = 8 #TODO: it should be come from calendars
612 working_days_per_week = 5
613 working_days_per_month = 20
614 working_days_per_year = 200
615 vacation = tuple(resource_pool.compute_vacation(cr, uid, calendar_id, context=context))
617 working_days = resource_pool.compute_working_calendar(cr, uid, calendar_id, context=context)
620 # Creating Resources for the Project
621 for key, vals in resource_objs.items():
623 class Resource_%s(Resource):
627 '''%(key, vals.get('name',False), vals.get('vacation', False), vals.get('efficiency', False))
629 # Create a new project for each phase
632 from resource.faces import Resource
635 minimum_time_unit = %s
636 working_hours_per_day = %s
637 working_days_per_week = %s
638 working_days_per_month = %s
639 working_days_per_year = %s
642 '''%(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 )
646 todo_task_ids = task_pool.search(cr, uid, [('project_id', '=', project.id),
647 ('state', 'in', ['draft', 'open', 'pending'])
649 for task in task_pool.browse(cr, uid, todo_task_ids, context=context):
650 func_str += task_pool.generate_task(cr, uid, task.id, parent=parent, flag=True,context=context)
653 task_ids.append(task.id)
655 #Temp File to test the Code for the Allocation
656 # fn = '/home/tiny/Desktop/plt.py'
658 # fp.writelines(func_str)
661 # Allocating Memory for the required Project and Pahses and Resources
663 Project = eval('Project_%d' % project.id)
664 project = Task.BalancedProject(Project)
665 for task_id in task_ids:
666 task = eval("project.Task_%d" % task_id)
667 start_date = task.start.to_datetime()
668 end_date = task.end.to_datetime()
670 task_pool.write(cr, uid, [task_id], {
671 'date_start': start_date.strftime('%Y-%m-%d'),
672 'date_end': end_date.strftime('%Y-%m-%d')
678 class resource_resource(osv.osv):
679 _inherit = "resource.resource"
680 def search(self, cr, uid, args, offset=0, limit=None, order=None, context=None, count=False):
683 if context.get('project_id',False):
684 project_pool = self.pool.get('project.project')
685 project_rec = project_pool.browse(cr, uid, context['project_id'], context=context)
686 user_ids = [user_id.id for user_id in project_rec.members]
687 args.append(('user_id','in',user_ids))
688 return super(resource_resource, self).search(cr, uid, args, offset, limit, order, context, count)
692 class project_task(osv.osv):
693 _inherit = "project.task"
695 'phase_id': fields.many2one('project.phase', 'Project Phase'),
701 def generate_task(self, cr, uid, task_id, parent=False, flag=False, context=None):
704 resource_pool = self.pool.get('resource.resource')
705 resource_allocation_pool = self.pool.get('project.resource.allocation')
706 task = self.browse(cr, uid, task_id, context=context)
707 duration = str(task.planned_hours )+ 'H'
710 resource_ids = self.search(cr, uid, [('user_id', '=', task.user_id.id)], context=context)
711 if len(resource_ids):
712 resource = 'Resource_%s'%resource_ids[0]
713 # Phases Defination for the Project
720 '''%(task.id, task.name, duration, resource)
722 start = 'up.Task_%s.end' % (parent.id)
726 #start = datetime.strftime((datetime.strptime(start, "%Y-%m-%d")), "%Y-%m-%d")
733 '''%(task.id, task.name, duration, resource)
735 start = 'up.Task_%s.end' % (parent.id)
742 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: