diff --git a/addons/hr_timesheet/__manifest__.py b/addons/hr_timesheet/__manifest__.py index ae824a8467a..493bc9057a6 100644 --- a/addons/hr_timesheet/__manifest__.py +++ b/addons/hr_timesheet/__manifest__.py @@ -37,6 +37,7 @@ up a management by affair. 'views/hr_views.xml', 'data/hr_timesheet_data.xml', 'views/project_sharing_views.xml', + 'views/rating_views.xml', ], 'demo': [ 'data/hr_timesheet_demo.xml', diff --git a/addons/hr_timesheet/models/project.py b/addons/hr_timesheet/models/project.py index ebb9037f2ee..3c1e14451e5 100644 --- a/addons/hr_timesheet/models/project.py +++ b/addons/hr_timesheet/models/project.py @@ -319,16 +319,20 @@ class Task(models.Model): def action_view_subtask_timesheet(self): self.ensure_one() tasks = self.with_context(active_test=False)._get_all_subtasks() - return { - 'type': 'ir.actions.act_window', - 'name': _('Timesheets'), - 'res_model': 'account.analytic.line', - 'view_mode': 'list,form', - 'context': { - 'default_project_id': self.project_id.id - }, + action = self.env["ir.actions.actions"]._for_xml_id("hr_timesheet.timesheet_action_all") + graph_view_id = self.env.ref("hr_timesheet.view_hr_timesheet_line_graph_by_employee").id + new_views = [] + for view in action['views']: + if view[1] == 'graph': + view = (graph_view_id, 'graph') + new_views.insert(0, view) if view[1] == 'tree' else new_views.append(view) + action.update({ + 'display_name': _('Timesheets'), + 'context': {'default_project_id': self.project_id.id, 'grid_range': 'week'}, 'domain': [('project_id', '!=', False), ('task_id', 'in', tasks.ids)], - } + 'views': new_views, + }) + return action def _get_timesheet(self): # Is override in sale_timesheet diff --git a/addons/hr_timesheet/report/project_report_view.xml b/addons/hr_timesheet/report/project_report_view.xml index 710b5eafd41..d48ebee50d9 100644 --- a/addons/hr_timesheet/report/project_report_view.xml +++ b/addons/hr_timesheet/report/project_report_view.xml @@ -38,11 +38,13 @@ - + + - + + diff --git a/addons/hr_timesheet/views/hr_timesheet_views.xml b/addons/hr_timesheet/views/hr_timesheet_views.xml index a917e27d065..140dee553ce 100644 --- a/addons/hr_timesheet/views/hr_timesheet_views.xml +++ b/addons/hr_timesheet/views/hr_timesheet_views.xml @@ -117,6 +117,16 @@ + + account.analytic.line.graph.by.employee + account.analytic.line + + primary + + + + + account.analytic.line.form account.analytic.line diff --git a/addons/hr_timesheet/views/project_portal_templates.xml b/addons/hr_timesheet/views/project_portal_templates.xml index cb8ff94437a..5509efc8072 100644 --- a/addons/hr_timesheet/views/project_portal_templates.xml +++ b/addons/hr_timesheet/views/project_portal_templates.xml @@ -52,15 +52,14 @@ 8 - Days Spent - Hours Spent + Days Spent + Hours Spent - + / - day(s) @@ -68,7 +67,6 @@ / - hour(s) diff --git a/addons/hr_timesheet/views/project_views.xml b/addons/hr_timesheet/views/project_views.xml index 7fd3577dc36..d45911dfebb 100644 --- a/addons/hr_timesheet/views/project_views.xml +++ b/addons/hr_timesheet/views/project_views.xml @@ -131,13 +131,12 @@
- -
-
- @@ -163,7 +162,6 @@ - @@ -173,6 +171,7 @@
+
@@ -348,6 +347,7 @@ + @@ -362,6 +362,7 @@ + @@ -373,6 +374,7 @@ + diff --git a/addons/hr_timesheet/views/rating_views.xml b/addons/hr_timesheet/views/rating_views.xml new file mode 100644 index 00000000000..9f55a28ed81 --- /dev/null +++ b/addons/hr_timesheet/views/rating_views.xml @@ -0,0 +1,14 @@ + + + + rating.rating.search.project.inherited + rating.rating + + + + + + + + + diff --git a/addons/project/data/project_demo.xml b/addons/project/data/project_demo.xml index 79ed148921a..c3df3fd6e29 100644 --- a/addons/project/data/project_demo.xml +++ b/addons/project/data/project_demo.xml @@ -7,12 +7,6 @@ - - - - - Bug diff --git a/addons/project/models/project.py b/addons/project/models/project.py index cffef538612..8cf76783020 100644 --- a/addons/project/models/project.py +++ b/addons/project/models/project.py @@ -1341,7 +1341,7 @@ class Task(models.Model): if recurrence_left == 0: recurrence_title = _('There are no more occurrences.') else: - recurrence_title = _('Next Occurrences:') + recurrence_title = _('A new task will be created on the following dates:') task.recurrence_message = '

%s

    ' % recurrence_title task.recurrence_message += ''.join(['
  • %s
  • ' % date.strftime(date_format) for date in recurring_dates[:5]]) if task.repeat_type == 'after' and recurrence_left > 5 or task.repeat_type == 'forever' or len(recurring_dates) > 5: diff --git a/addons/project/models/project_collaborator.py b/addons/project/models/project_collaborator.py index 640a71c0523..5919f33da72 100644 --- a/addons/project/models/project_collaborator.py +++ b/addons/project/models/project_collaborator.py @@ -10,6 +10,7 @@ class ProjectCollaborator(models.Model): project_id = fields.Many2one('project.project', 'Project Shared', domain=[('privacy_visibility', '=', 'portal')], required=True, readonly=True) partner_id = fields.Many2one('res.partner', 'Collaborator', required=True, readonly=True) + partner_email = fields.Char(related='partner_id.email') _sql_constraints = [ ('unique_collaborator', 'UNIQUE(project_id, partner_id)', 'A collaborator cannot be selected more than once in the project sharing access. Please remove duplicate(s) and try again.'), diff --git a/addons/project/models/project_task_recurrence.py b/addons/project/models/project_task_recurrence.py index a80156be610..b6f5ce2e4fe 100644 --- a/addons/project/models/project_task_recurrence.py +++ b/addons/project/models/project_task_recurrence.py @@ -146,7 +146,7 @@ class ProjectTaskRecurrence(models.Model): return ['message_partner_ids', 'company_id', 'description', 'displayed_image_id', 'email_cc', 'parent_id', 'partner_email', 'partner_id', 'partner_phone', 'planned_hours', 'project_id', 'display_project_id', 'project_privacy_visibility', 'sequence', 'tag_ids', 'recurrence_id', - 'name', 'recurring_task', 'analytic_account_id'] + 'name', 'recurring_task', 'analytic_account_id', 'user_ids'] def _get_weekdays(self, n=1): self.ensure_one() @@ -209,7 +209,6 @@ class ProjectTaskRecurrence(models.Model): field: value[0] if isinstance(value, tuple) else value for field, value in task_values.items() } create_values['stage_id'] = task.project_id.type_ids[0].id if task.project_id.type_ids else task.stage_id.id - create_values['user_ids'] = False return create_values def _create_subtasks(self, task, new_task, depth=3): diff --git a/addons/project/report/project_report.py b/addons/project/report/project_report.py index 3c304d73464..13562dcf036 100644 --- a/addons/project/report/project_report.py +++ b/addons/project/report/project_report.py @@ -3,7 +3,7 @@ from odoo import fields, models, tools -from odoo.addons.rating.models.rating_data import RATING_LIMIT_MIN +from odoo.addons.rating.models.rating_data import RATING_LIMIT_MIN, RATING_TEXT class ReportProjectTaskUser(models.Model): _name = "report.project.task.user" @@ -51,6 +51,18 @@ class ReportProjectTaskUser(models.Model): column1='project_task_id', column2='project_tags_id', string='Tags', readonly=True) parent_id = fields.Many2one('project.task', string='Parent Task', readonly=True) + # We are explicitly not using a related field in order to prevent the recomputing caused by the depends as the model is a report. + rating_last_text = fields.Selection(RATING_TEXT, string="Rating Last Text", compute="_compute_rating_last_text", search="_search_rating_last_text") + personal_stage_type_ids = fields.Many2many('project.task.type', relation='project_task_user_rel', + column1='task_id', column2='stage_id', + string="Personal Stage", readonly=True) + + def _compute_rating_last_text(self): + for task_analysis in self: + task_analysis.rating_last_text = task_analysis.task_id.rating_last_text + + def _search_rating_last_text(self, operator, value): + return [('task_id.rating_last_text', operator, value)] def _select(self): return """ @@ -109,7 +121,6 @@ class ReportProjectTaskUser(models.Model): def _from(self): return f""" project_task t - LEFT JOIN project_task_user_rel tu on t.id=tu.task_id LEFT JOIN rating_rating rt ON rt.res_id = t.id AND rt.res_model = 'project.task' AND rt.consumed = True diff --git a/addons/project/report/project_report_views.xml b/addons/project/report/project_report_views.xml index 874619ae3db..ae878335502 100644 --- a/addons/project/report/project_report_views.xml +++ b/addons/project/report/project_report_views.xml @@ -43,43 +43,56 @@ report.project.task.user + + + - - - + - + - + + + + + - + + - - - + + + + + + + - + + + + diff --git a/addons/project/static/src/scss/project_rightpanel.scss b/addons/project/static/src/scss/project_rightpanel.scss index 10c444f9699..c1b139f9b3f 100644 --- a/addons/project/static/src/scss/project_rightpanel.scss +++ b/addons/project/static/src/scss/project_rightpanel.scss @@ -184,7 +184,7 @@ html .o_web_client > .o_action_manager > .o_action > .o_content > .o_controller_ border-width: 1px; margin-top: -1px; margin-left: -1px; - height: 56px; + height: 57.5px; &:nth-child(3n){ border-right-width: 0px; diff --git a/addons/project/tests/test_project_subtasks.py b/addons/project/tests/test_project_subtasks.py index 793f7baf964..ef966aca8bd 100644 --- a/addons/project/tests/test_project_subtasks.py +++ b/addons/project/tests/test_project_subtasks.py @@ -194,6 +194,11 @@ class TestProjectSubtasks(TestProjectCommon): self.assertEqual(self.task_1.child_ids.stage_id.name, "New", "The stage of the child task should be the default one of the display project id, once set.") def test_copy_project_with_subtasks(self): + # Enable the company setting + self.env['res.config.settings'].create({ + 'group_subtask_project': True + }).execute() + self.env['project.task'].with_context({'mail_create_nolog': True}).create({ 'name': 'Parent Task', 'project_id': self.project_goats.id, diff --git a/addons/project/tests/test_task_dependencies.py b/addons/project/tests/test_task_dependencies.py index e225cc100da..34c43a693b9 100644 --- a/addons/project/tests/test_task_dependencies.py +++ b/addons/project/tests/test_task_dependencies.py @@ -183,6 +183,8 @@ class TestTaskDependencies(TestProjectCommon): "Copy should not alter the relation if the other task is in a different project") def test_duplicate_project_with_subtask_dependencies(self): + self.project_goats.allow_task_dependencies = True + self.project_goats.allow_subtasks = True parent_task = self.env['project.task'].with_context({'mail_create_nolog': True}).create({ 'name': 'Parent Task', 'project_id': self.project_goats.id, diff --git a/addons/project/views/project_collaborator_views.xml b/addons/project/views/project_collaborator_views.xml index 62f18014783..15e26993ae4 100644 --- a/addons/project/views/project_collaborator_views.xml +++ b/addons/project/views/project_collaborator_views.xml @@ -21,8 +21,8 @@ project.collaborator - + diff --git a/addons/project/views/project_portal_templates.xml b/addons/project/views/project_portal_templates.xml index 8e68e576b8d..6b02a821360 100644 --- a/addons/project/views/project_portal_templates.xml +++ b/addons/project/views/project_portal_templates.xml @@ -33,7 +33,7 @@