New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
project_task_scheduling: Module for automatic task planning #419
Changes from 11 commits
5578e2d
4e5a21e
07022bb
e83e1ce
ba1d9f5
fb3b5c7
37ac1a5
02144ea
560de9d
e62beea
27851be
7841cb2
129ed4e
79045c2
7e637c3
ab28bee
36bc972
0ceb2d4
7920b43
f7211b2
4101b4c
445a350
05acf10
2f74b5a
02b6f64
de17f06
4ea656a
cd71b48
8b3619c
608fdbe
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). | ||
from . import project | ||
from . import project_task |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). | ||
from odoo import fields, models | ||
|
||
|
||
class ProjectProject(models.Model): | ||
_inherit = 'project.project' | ||
|
||
employee_ids = fields.Many2many( | ||
comodel_name='hr.employee', | ||
string="Employees", | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). | ||
from odoo import api, fields, models | ||
|
||
|
||
class Task(models.Model): | ||
_inherit = 'project.task' | ||
|
||
employee_domain_ids = fields.Many2many( | ||
compute='_compute_employee_domain_ids', | ||
comodel_name='hr.employee', | ||
string="Employees", | ||
) | ||
employee_scheduling_ids = fields.Many2many( | ||
compute='_compute_employee_scheduling_ids', | ||
comodel_name='hr.employee', | ||
string="Employees", | ||
) | ||
employee_id = fields.Many2one( | ||
comodel_name='hr.employee', | ||
string="Assigned to employee", | ||
domain="[('id', 'in', employee_domain_ids)]", | ||
help="If the task is not scheduled (without ending date), the " | ||
"automated scheduling will only assign the task to the employee " | ||
"selected here.", | ||
) | ||
employee_category_id = fields.Many2one( | ||
comodel_name='hr.employee.category', | ||
string="Employee category", | ||
help="Only employee selected on the project belonging to the task " | ||
"that have the categories selected here can do the task.", | ||
) | ||
scheduled = fields.Boolean( | ||
compute='_compute_scheduled', | ||
readonly=True, | ||
store=True, | ||
) | ||
|
||
@api.multi | ||
@api.depends('project_id.employee_ids.category_ids', | ||
'employee_category_id') | ||
def _compute_employee_domain_ids(self): | ||
for record in self: | ||
emp = record.mapped('project_id.employee_ids') | ||
task_skill = record.employee_category_id | ||
if task_skill: | ||
emp = emp.filtered(lambda r: task_skill in r.category_ids) | ||
record.employee_domain_ids = emp.ids | ||
|
||
@api.multi | ||
@api.depends('project_id.employee_ids.category_ids', | ||
'employee_category_id') | ||
def _compute_employee_scheduling_ids(self): | ||
for record in self: | ||
employees = record.employee_id | ||
if record.date_end or not record.employee_id: | ||
employees = record.employee_domain_ids | ||
record.employee_scheduling_ids = employees | ||
|
||
@api.multi | ||
@api.depends('employee_id', 'date_start', 'date_end') | ||
def _compute_scheduled(self): | ||
for record in self: | ||
record.scheduled = record.date_end | ||
|
||
@api.onchange('employee_domain_ids') | ||
def _onchange_employee_domain_ids(self): | ||
if self.employee_id not in self.employee_domain_ids: | ||
self.employee_id = False | ||
|
||
@api.onchange('employee_id') | ||
def _onchange_employee_id(self): | ||
if self.user_id != self.employee_id.user_id: | ||
self.user_id = self.employee_id.user_id |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
This module extends the functionality of project to allow you to add employees | ||
to a project, to specify required skills (Employee category) to a task and to | ||
add an employee to a task. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,22 +7,22 @@ def setUp(self): | |
super(TestProjectTask, self).setUp() | ||
|
||
self.task_3 = self.env['project.task'].browse( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @ernestotejeda IMO Add one variable and use this obj Ex: self.project_task_obj = self.env['project.task'] |
||
self.ref("project_task_assignment.restricted_task_3")) | ||
self.ref("project_task_employee.restricted_task_3")) | ||
self.task_2 = self.env['project.task'].browse( | ||
self.ref("project_task_assignment.restricted_task_2")) | ||
self.ref("project_task_employee.restricted_task_2")) | ||
self.task_7 = self.env['project.task'].browse( | ||
self.ref("project_task_assignment.restricted_task_7")) | ||
self.ref("project_task_employee.restricted_task_7")) | ||
self.task_1 = self.env['project.task'].browse( | ||
self.ref("project_task_assignment.restricted_task_1")) | ||
self.ref("project_task_employee.restricted_task_1")) | ||
|
||
def test_get_employees(self): | ||
def test_employee_domain_ids(self): | ||
jth = self.env['hr.employee'].browse(self.ref("hr.employee_jth")) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @ernestotejeda same as here |
||
root = self.env['hr.employee'].browse(self.ref("hr.employee_root")) | ||
|
||
self.assertEqual(self.task_3.employee_ids, jth + root) | ||
self.assertEqual(self.task_2.employee_ids, jth + root) | ||
self.assertEqual(self.task_7.employee_ids, root) | ||
self.assertEqual(self.task_1.employee_ids, jth) | ||
self.assertEqual(self.task_3.employee_domain_ids, jth + root) | ||
self.assertEqual(self.task_2.employee_domain_ids, jth + root) | ||
self.assertEqual(self.task_7.employee_domain_ids, root) | ||
self.assertEqual(self.task_1.employee_domain_ids, jth) | ||
|
||
def test_onchange_project_id_employee_id(self): | ||
onchange_result = self.task_3._onchange_project_id_employee_id() | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<!--License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).--> | ||
<odoo> | ||
|
||
<record id="edit_project" model="ir.ui.view"> | ||
<field name="name">project.project.form.inherit.scheduling</field> | ||
<field name="model">project.project</field> | ||
<field name="inherit_id" ref="project.edit_project"/> | ||
<field name="arch" type="xml"> | ||
<notebook> | ||
<page string="Employees"> | ||
<group> | ||
<field name="employee_ids" nolabel="1"/> | ||
</group> | ||
</page> | ||
</notebook> | ||
</field> | ||
</record> | ||
|
||
</odoo> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,5 @@ | ||
This module allow you to execute an automated project task scheduling. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you improve the description and add a use case? |
||
|
||
References: | ||
|
||
* Demeulemeester, E., Herroelen W./ PROJECT SCHEDULING A Research Handbook |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,9 @@ | ||
To use this module, you need to: | ||
|
||
#. Go to Project / Automation / Project task scheduler | ||
#. Set the parameters to compute the proposals of scheduling. List of task to be scheduled, The date to start the scheduling and The cooling ratio | ||
#. Create employees with skills (Categories) and set working hours (calendar). | ||
#. Create Project and choose employees belongs to the project. | ||
#. Add Tasks to the project. For each task, set deadline, employee category required by task, Initially planned hours, and dependencies on other tasks. If you set starting date but not ending date, starting date is considered as the earliest date-time required for the assignation during automatic scheduling of the task. If you set employee but not ending date, it will be the only employee required for the assignation during automatic scheduling of the task. | ||
#. Go to Project > Automation > Project task scheduler | ||
#. Choose a task option (Not finished, Not Scheduled, Customized), a Date Start and Calculation Speed (Slow, Middle, Fast) | ||
#. Click on Accept button | ||
#. You will see a list of proposals of scheduling. For each proposal you can see a time line view of that or click on one item to see all data of the scheduling in a form view or set the scheduling as definitive | ||
#. You will see a list of proposals of scheduling. For each proposal you can see a time line view for all task grouped by employee. You can also click on one item to see all data of the scheduling in a form view and set it as a definitive scheduling. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't we link to
res.users
here instead? Since https://github.com/odoo/odoo/blob/7e5d5045bfa7752176dd8f19c546ff6b19841381/addons/project/models/project.py#L439