-
-
Notifications
You must be signed in to change notification settings - Fork 759
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 all 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
**This file is going to be generated by oca-gen-addon-readme.** |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). | ||
from . import models |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
# Copyright 2018 Tecnativa - Ernesto Tejeda | ||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). | ||
{ | ||
"name": "Project task employee", | ||
"version": "11.0.1.0.0", | ||
"category": "Project Management", | ||
"author": "Tecnativa, " | ||
"Odoo Community Association (OCA)", | ||
"website": "https://github.com/OCA/project", | ||
"license": "AGPL-3", | ||
"depends": [ | ||
"hr", | ||
"project", | ||
], | ||
"data": [ | ||
"views/project_view.xml", | ||
"views/project_task_view.xml", | ||
], | ||
"demo": [ | ||
"demo/project_task.xml", | ||
], | ||
"installable": True, | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<!-- Copyright 2018 Tecnativa - Ernesto Tejeda | ||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). --> | ||
<odoo> | ||
|
||
<record id="restricted_project" model="project.project"> | ||
<field name="name">Project restricted</field> | ||
<field name="employee_ids" eval="[(6, 0, [ref('hr.employee_jth'), ref('hr.employee_root')])]"/> | ||
</record> | ||
|
||
<record id="restricted_task_2" model="project.task"> | ||
<field name="name">2</field> | ||
<field name="project_id" ref="restricted_project"/> | ||
<field name="planned_hours">2</field> | ||
<field name="date_deadline" eval="datetime.now()+timedelta(days=30)"/> | ||
<field name="stage_id" ref="project.project_stage_0"/> | ||
</record> | ||
|
||
<record id="restricted_task_3" model="project.task"> | ||
<field name="name">3</field> | ||
<field name="project_id" ref="restricted_project"/> | ||
<field name="planned_hours">3</field> | ||
<field name="date_deadline" eval="datetime.now()+timedelta(days=30)"/> | ||
<field name="stage_id" ref="project.project_stage_0"/> | ||
</record> | ||
|
||
<record id="restricted_task_7" model="project.task"> | ||
<field name="name">7</field> | ||
<field name="project_id" ref="restricted_project"/> | ||
<field name="planned_hours">7</field> | ||
<field name="date_deadline" eval="datetime.now()+timedelta(days=30)"/> | ||
<field name="stage_id" ref="project.project_stage_0"/> | ||
<field name="employee_category_id" ref="hr.employee_category_3"/> | ||
</record> | ||
|
||
<record id="restricted_task_1" model="project.task"> | ||
<field name="name">1</field> | ||
<field name="project_id" ref="restricted_project"/> | ||
<field name="planned_hours">1</field> | ||
<field name="date_deadline" eval="datetime.now()+timedelta(days=30)"/> | ||
<field name="stage_id" ref="project.project_stage_0"/> | ||
<field name="employee_category_id" ref="hr.employee_category_5"/> | ||
</record> | ||
|
||
</odoo> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +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,12 @@ | ||
# Copyright 2018 Tecnativa - Ernesto Tejeda | ||
# 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,62 @@ | ||
# Copyright 2018 Tecnativa - Ernesto Tejeda | ||
# 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.", | ||
) | ||
|
||
@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('date_end', 'employee_id', 'employee_domain_ids') | ||
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.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 @@ | ||
* `Tecnativa <https://www.tecnativa.com>`_: | ||
|
||
* Ernesto Tejeda |
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 |
---|---|---|
@@ -0,0 +1,2 @@ | ||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). | ||
from . import test_project_task | ||
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. Please add newline 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. After the comment line? Why? |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
# Copyright 2018 Tecnativa - Ernesto Tejeda | ||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). | ||
from odoo.tests.common import TransactionCase | ||
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. Newline would be great |
||
|
||
|
||
class TestProjectTask(TransactionCase): | ||
def setUp(self): | ||
super(TestProjectTask, self).setUp() | ||
self.task_3 = self.env.ref("project_task_employee.restricted_task_3") | ||
self.task_2 = self.env.ref("project_task_employee.restricted_task_2") | ||
self.task_7 = self.env.ref("project_task_employee.restricted_task_7") | ||
self.task_1 = self.env.ref("project_task_employee.restricted_task_1") | ||
|
||
def test_employee_domain_ids(self): | ||
jth = self.env.ref("hr.employee_jth") | ||
root = self.env.ref("hr.employee_root") | ||
|
||
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_change_employee_domain_ids_and_employee_id(self): | ||
with self.env.do_in_onchange(): | ||
|
||
self.task_3.user_id = False | ||
self.assertFalse(self.task_3.user_id) | ||
|
||
self.task_3.employee_id = self.env.ref("hr.employee_root") | ||
self.task_3._onchange_employee_id() | ||
user = self.env.ref("base.user_root") | ||
self.assertEqual(self.task_3.user_id, user) | ||
|
||
category_5 = self.env.ref("hr.employee_category_5") | ||
self.task_3.employee_category_id = category_5 | ||
self.task_3._onchange_employee_domain_ids() | ||
self.assertFalse(self.task_3.employee_id) | ||
|
||
self.assertEqual(self.task_3.user_id, user) | ||
self.task_3._onchange_employee_id() | ||
self.assertFalse(self.task_3.user_id) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<!-- Copyright 2018 Tecnativa - Ernesto Tejeda | ||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). --> | ||
<odoo> | ||
|
||
<record id="view_task_form2_inherit_schedule" model="ir.ui.view"> | ||
<field name="name">project.task.form.inherit.schedule</field> | ||
<field name="model">project.task</field> | ||
<field name="inherit_id" ref="project.view_task_form2"/> | ||
<field name="arch" type="xml"> | ||
<field name="user_id" position="attributes"> | ||
<attribute name="string">Assigned to user</attribute> | ||
</field> | ||
<field name="user_id" position="after"> | ||
<field name="employee_domain_ids" invisible="1"/> | ||
<field name="employee_id"/> | ||
</field> | ||
<field name="tag_ids" position="after"> | ||
<field name="employee_category_id"/> | ||
</field> | ||
</field> | ||
</record> | ||
|
||
</odoo> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<!-- Copyright 2018 Tecnativa - Ernesto Tejeda | ||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). --> | ||
<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 |
---|---|---|
@@ -0,0 +1 @@ | ||
**This file is going to be generated by oca-gen-addon-readme.** |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). | ||
from . import models | ||
from . import wizards |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
# Copyright 2018 Tecnativa - Ernesto Tejeda | ||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). | ||
{ | ||
"name": "Automating Project Task Scheduling", | ||
"version": "11.0.1.0.0", | ||
"category": "Project Management", | ||
"author": "Tecnativa, " | ||
"Odoo Community Association (OCA)", | ||
"website": "https://github.com/OCA/project", | ||
"license": "AGPL-3", | ||
"depends": [ | ||
"hr", | ||
"hr_timesheet", | ||
"project", | ||
"project_task_employee", | ||
"project_task_dependency", | ||
"project_timeline", | ||
"project_stage_closed", | ||
], | ||
"data": [ | ||
"views/project_task_scheduling_menu_views.xml", | ||
"wizards/scheduling_wizard_views.xml", | ||
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 Add last |
||
"views/project_task_scheduling_proposal_views.xml", | ||
"views/project_task_scheduling_views.xml", | ||
], | ||
"installable": True, | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). | ||
from . import project_task_scheduling | ||
from . import project_task_scheduling_proposal |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
# Copyright 2018 Tecnativa - Ernesto Tejeda | ||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). | ||
from odoo import api, fields, models | ||
|
||
|
||
class ProjectTaskScheduling(models.TransientModel): | ||
_name = 'project.task.scheduling' | ||
_description = 'Project task scheduling' | ||
_rec_name = "task_id" | ||
|
||
proposal_id = fields.Many2one( | ||
comodel_name='project.task.scheduling.proposal', | ||
string="Proposal", | ||
ondelete='cascade', | ||
required=True, | ||
) | ||
employee_id = fields.Many2one( | ||
comodel_name='hr.employee', | ||
string="Employee", | ||
required=True, | ||
) | ||
task_id = fields.Many2one( | ||
comodel_name='project.task', | ||
string="Task", | ||
required=True, | ||
) | ||
datetime_start = fields.Datetime( | ||
required=True, | ||
) | ||
datetime_stop = fields.Datetime( | ||
required=True, | ||
) | ||
delayed = fields.Boolean( | ||
compute='_compute_delayed', | ||
default=False, | ||
) | ||
|
||
@api.multi | ||
@api.depends('task_id.date_deadline', 'datetime_stop') | ||
def _compute_delayed(self): | ||
for rec in self: | ||
date_deadline = fields.Date.from_string(rec.task_id.date_deadline) | ||
datetime_stop = fields.Datetime.from_string(rec.datetime_stop) | ||
if date_deadline and datetime_stop: | ||
rec.delayed = date_deadline < datetime_stop.date() | ||
|
||
@api.multi | ||
def set_assignation(self): | ||
for record in self: | ||
record.task_id.write({ | ||
'employee_id': record.employee_id.id, | ||
'user_id': record.employee_id.user_id.id, | ||
'date_start': record.datetime_start, | ||
'date_end': record.datetime_stop, | ||
}) |
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