From e7dda3fab002f5db930b4af340787177d597d59e Mon Sep 17 00:00:00 2001 From: jbm-odoo Date: Thu, 28 May 2020 08:33:19 +0200 Subject: [PATCH 1/3] [IMP] project_timesheet: Add internal project by default to ease onboarding taskId: 2217930 --- addons/hr_timesheet/__init__.py | 40 +++++++++++++++++ addons/hr_timesheet/__manifest__.py | 1 + addons/hr_timesheet/models/hr_timesheet.py | 10 ++++- addons/hr_timesheet/models/res_company.py | 33 +++++++++++++- .../models/res_company.py | 44 ++++++++++++------- addons/timer/static/src/js/timer_mixin.js | 10 +++-- 6 files changed, 117 insertions(+), 21 deletions(-) diff --git a/addons/hr_timesheet/__init__.py b/addons/hr_timesheet/__init__.py index 4e9b019bd7a..67486585c98 100644 --- a/addons/hr_timesheet/__init__.py +++ b/addons/hr_timesheet/__init__.py @@ -5,3 +5,43 @@ from . import controllers from . import models from . import report from . import wizard + +from odoo import api, fields, SUPERUSER_ID, _ + + +def create_internal_project(cr, registry): + env = api.Environment(cr, SUPERUSER_ID, {}) + companies_with_internal = env['project.project'].read_group([ + ('name', '=', _('Internal')), ('allow_timesheets', '=', True) + ], ['company_id'], ['company_id']) + company_ids_with_internal = [c['company_id'][0] for c in companies_with_internal] + for company in env['res.company'].search([('id', 'not in', company_ids_with_internal)]): + company = company.with_company(company) + internal_project = company.env['project.project'].create({ + 'name': _('Internal'), + 'allow_timesheets': True, + 'company_id': company.id, + }) + admin = env.ref('base.user_admin', raise_if_not_found=False) + if not admin: + continue + tasks = company.env['project.task'].create([{ + 'name': _('Training'), + 'project_id': internal_project.id, + 'company_id': company.id, + }, { + 'name': _('Meeting'), + 'project_id': internal_project.id, + 'company_id': company.id, + }]) + + if not admin.employee_ids.filtered(lambda e: e.company_id == company): + continue + company.env['account.analytic.line'].create([{ + 'name': _("Analysis"), + 'user_id': admin.id, + 'date': fields.datetime.today(), + 'unit_amount': 0, + 'project_id': internal_project.id, + 'task_id': task.id, + } for task in tasks]) diff --git a/addons/hr_timesheet/__manifest__.py b/addons/hr_timesheet/__manifest__.py index 7af5ebb8404..e529653a5e6 100644 --- a/addons/hr_timesheet/__manifest__.py +++ b/addons/hr_timesheet/__manifest__.py @@ -42,4 +42,5 @@ up a management by affair. 'installable': True, 'application': False, 'auto_install': False, + 'post_init_hook': 'create_internal_project', } diff --git a/addons/hr_timesheet/models/hr_timesheet.py b/addons/hr_timesheet/models/hr_timesheet.py index b61421191a1..820d7a694ce 100644 --- a/addons/hr_timesheet/models/hr_timesheet.py +++ b/addons/hr_timesheet/models/hr_timesheet.py @@ -234,4 +234,12 @@ class AccountAnalyticLine(models.Model): self.write({'unit_amount': amount}) def _action_interrupt_user_timers(self): - self.action_timer_stop() \ No newline at end of file + self.action_timer_stop() + + def unlink(self): + res = super(AccountAnalyticLine, self).unlink() + self.env['timer.timer'].search([ + ('res_model', '=', self._name), + ('res_id', 'in', self.ids) + ]).unlink() + return res diff --git a/addons/hr_timesheet/models/res_company.py b/addons/hr_timesheet/models/res_company.py index 8d48a0e4bb1..429799ec54e 100644 --- a/addons/hr_timesheet/models/res_company.py +++ b/addons/hr_timesheet/models/res_company.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -from odoo import api, fields, models +from odoo import api, fields, models, _ class ResCompany(models.Model): @@ -36,3 +36,34 @@ class ResCompany(models.Model): default=_default_timesheet_encode_uom_id, domain=lambda self: [('category_id', '=', self.env.ref('uom.uom_categ_wtime').id)], help="""This will set the unit of measure used to encode timesheet. This will simply provide tools and widgets to help the encoding. All reporting will still be expressed in hours (default value).""") + + @api.model_create_multi + def create(self, values): + company = super(ResCompany, self).create(values) + # use sudo as the user could have the right to create a company + # but not to create a project. On the other hand, when the company + # is created, it is not in the allowed_company_ids on the env + company.sudo()._create_internal_project_task() + return company + + def _create_internal_project_task(self): + results = [] + for company in self: + company = company.with_company(company) + internal_project = company.env['project.project'].sudo().create({ + 'name': _('Internal'), + 'allow_timesheets': True, + 'company_id': company.id, + }) + + company.env['project.task'].sudo().create([{ + 'name': _('Training'), + 'project_id': internal_project.id, + 'company_id': company.id, + }, { + 'name': _('Meeting'), + 'project_id': internal_project.id, + 'company_id': company.id, + }]) + results.append(internal_project) + return results diff --git a/addons/project_timesheet_holidays/models/res_company.py b/addons/project_timesheet_holidays/models/res_company.py index c6e15eff9c2..bd50f4a0864 100644 --- a/addons/project_timesheet_holidays/models/res_company.py +++ b/addons/project_timesheet_holidays/models/res_company.py @@ -23,27 +23,39 @@ class Company(models.Model): raise ValidationError(_('The Internal Project of a company should be in that company.')) def init(self): - self.search([('leave_timesheet_project_id', '=', False)])._create_leave_project_task() - - @api.model_create_multi - def create(self, values): - company = super(Company, self).create(values) - # use sudo as the user could have the right to create a company - # but not to create a project. On the other hand, when the company - # is created, it is not in the allowed_company_ids on the env - company.sudo()._create_leave_project_task() - return company - - def _create_leave_project_task(self): - for company in self: + for company in self.search([('leave_timesheet_project_id', '=', False)]): company = company.with_company(company) - if not company.leave_timesheet_project_id: - project = company.env['project.project'].sudo().create({ - 'name': _('Internal Project'), + project = company.env['project.project'].search([ + ('name', '=', _('Internal')), + ('allow_timesheets', '=', True), + ('company_id', '=', company.id), + ], limit=1) + if not project: + project = company.env['project.project'].create({ + 'name': _('Internal'), 'allow_timesheets': True, + 'company_id': company.id, + }) + company.write({ + 'leave_timesheet_project_id': project.id, + }) + if not company.leave_timesheet_task_id: + task = company.env['project.task'].create({ + 'name': _('Time Off'), + 'project_id': company.leave_timesheet_project_id.id, 'active': False, 'company_id': company.id, }) + company.write({ + 'leave_timesheet_task_id': task.id, + }) + + def _create_internal_project_task(self): + projects = super()._create_internal_project_task() + for project in projects: + company = project.company_id + company = company.with_company(company) + if not company.leave_timesheet_project_id: company.write({ 'leave_timesheet_project_id': project.id, }) diff --git a/addons/timer/static/src/js/timer_mixin.js b/addons/timer/static/src/js/timer_mixin.js index 779d06dbe4a..7a70e81341e 100644 --- a/addons/timer/static/src/js/timer_mixin.js +++ b/addons/timer/static/src/js/timer_mixin.js @@ -39,9 +39,9 @@ odoo.define('timer.Timer', function (require) { timer.addTime( moment.utc( - moment.utc(serverTime) + Math.abs(moment.utc(serverTime) .diff(moment.utc(timer_start)) - ).format("HH:mm:ss") + )).format("HH:mm:ss") ); return timer; @@ -87,7 +87,7 @@ odoo.define('timer.Timer', function (require) { hour = parseInt(hour); minute = parseInt(minute); - second = parseInt(second); + second = (second === undefined) ? 0 : parseInt(second); this.addSeconds(second); this.addMinutes(minute); @@ -99,6 +99,10 @@ odoo.define('timer.Timer', function (require) { return (this.hours * 60 + this.minutes) * 60 / 3600; } + convertToSeconds() { + return (this.hours * 60 + this.minutes) * 60 + this.seconds; + } + toString() { const time = { hours: this.display2digits(this.hours), From d6a23144d5c5b85c2a02097bcbb3e006a9c2c52a Mon Sep 17 00:00:00 2001 From: jbm-odoo Date: Fri, 5 Jun 2020 17:13:53 +0200 Subject: [PATCH 2/3] [MOV] timer: Move to Enterprise taskId: 2217930 --- addons/hr_timesheet/__init__.py | 49 +++--- addons/hr_timesheet/__manifest__.py | 2 +- addons/hr_timesheet/models/hr_timesheet.py | 51 +------ addons/hr_timesheet/models/project.py | 91 +---------- .../static/src/js/timesheet_kanban_view.js | 34 ----- .../static/src/js/timesheet_list_view.js | 34 ----- .../static/src/js/timesheet_uom.js | 54 +------ .../static/src/js/timesheet_uom_timer.js | 3 +- .../static/src/scss/timer_button.scss | 26 ---- addons/hr_timesheet/tests/test_timesheet.py | 78 ---------- addons/hr_timesheet/views/assets.xml | 4 - .../hr_timesheet/views/hr_timesheet_views.xml | 23 +-- addons/hr_timesheet/views/project_views.xml | 86 ----------- .../wizard/project_task_create_timesheet.py | 5 - addons/sale_timesheet/models/project.py | 5 +- addons/sale_timesheet/models/sale_order.py | 2 +- .../views/project_task_views.xml | 4 +- addons/test_timer/__init__.py | 4 - addons/test_timer/__manifest__.py | 20 --- addons/test_timer/models/__init__.py | 4 - addons/test_timer/models/timer_test.py | 25 ---- .../test_timer/security/ir.model.access.csv | 3 - addons/test_timer/tests/__init__.py | 4 - addons/test_timer/tests/test_timer.py | 141 ------------------ addons/timer/__init__.py | 4 - addons/timer/__manifest__.py | 27 ---- addons/timer/i18n/timer.pot | 127 ---------------- addons/timer/models/__init__.py | 5 - addons/timer/models/timer.py | 70 --------- addons/timer/security/ir.model.access.csv | 2 - addons/timer/security/timer_security.xml | 30 ---- addons/timer/static/src/js/timer.js | 63 -------- addons/timer/static/src/js/timer_mixin.js | 119 --------------- .../static/src/js/timer_toggle_button.js | 3 +- .../timer/static/src/scss/timer_button.scss | 26 ---- addons/timer/views/assets.xml | 11 -- 36 files changed, 40 insertions(+), 1199 deletions(-) delete mode 100644 addons/hr_timesheet/static/src/js/timesheet_kanban_view.js delete mode 100644 addons/hr_timesheet/static/src/js/timesheet_list_view.js delete mode 100644 addons/hr_timesheet/static/src/scss/timer_button.scss delete mode 100644 addons/test_timer/__init__.py delete mode 100644 addons/test_timer/__manifest__.py delete mode 100644 addons/test_timer/models/__init__.py delete mode 100644 addons/test_timer/models/timer_test.py delete mode 100644 addons/test_timer/security/ir.model.access.csv delete mode 100644 addons/test_timer/tests/__init__.py delete mode 100644 addons/test_timer/tests/test_timer.py delete mode 100644 addons/timer/__init__.py delete mode 100644 addons/timer/__manifest__.py delete mode 100644 addons/timer/i18n/timer.pot delete mode 100644 addons/timer/models/__init__.py delete mode 100644 addons/timer/models/timer.py delete mode 100644 addons/timer/security/ir.model.access.csv delete mode 100644 addons/timer/security/timer_security.xml delete mode 100644 addons/timer/static/src/js/timer.js delete mode 100644 addons/timer/static/src/js/timer_mixin.js delete mode 100644 addons/timer/static/src/scss/timer_button.scss delete mode 100644 addons/timer/views/assets.xml diff --git a/addons/hr_timesheet/__init__.py b/addons/hr_timesheet/__init__.py index 67486585c98..6aab6c417a5 100644 --- a/addons/hr_timesheet/__init__.py +++ b/addons/hr_timesheet/__init__.py @@ -11,37 +11,28 @@ from odoo import api, fields, SUPERUSER_ID, _ def create_internal_project(cr, registry): env = api.Environment(cr, SUPERUSER_ID, {}) - companies_with_internal = env['project.project'].read_group([ - ('name', '=', _('Internal')), ('allow_timesheets', '=', True) - ], ['company_id'], ['company_id']) - company_ids_with_internal = [c['company_id'][0] for c in companies_with_internal] - for company in env['res.company'].search([('id', 'not in', company_ids_with_internal)]): + admin = env.ref('base.user_admin', raise_if_not_found=False) + if not admin: + return + project_vals = [] + for company in env['res.company'].search([]): company = company.with_company(company) - internal_project = company.env['project.project'].create({ + project_vals += [{ 'name': _('Internal'), 'allow_timesheets': True, 'company_id': company.id, - }) - admin = env.ref('base.user_admin', raise_if_not_found=False) - if not admin: - continue - tasks = company.env['project.task'].create([{ - 'name': _('Training'), - 'project_id': internal_project.id, - 'company_id': company.id, - }, { - 'name': _('Meeting'), - 'project_id': internal_project.id, - 'company_id': company.id, - }]) + 'task_ids': [(0, 0, { + 'name': name, + 'company_id': company.id, + }) for name in [_('Training'), _('Meeting')]] + }] + project_ids = env['project.project'].create(project_vals) - if not admin.employee_ids.filtered(lambda e: e.company_id == company): - continue - company.env['account.analytic.line'].create([{ - 'name': _("Analysis"), - 'user_id': admin.id, - 'date': fields.datetime.today(), - 'unit_amount': 0, - 'project_id': internal_project.id, - 'task_id': task.id, - } for task in tasks]) + env['account.analytic.line'].create([{ + 'name': _("Analysis"), + 'user_id': admin.id, + 'date': fields.datetime.today(), + 'unit_amount': 0, + 'project_id': task.project_id.id, + 'task_id': task.id, + } for task in project_ids.task_ids.filtered(lambda t: t.company_id in admin.employee_ids.company_id)]) diff --git a/addons/hr_timesheet/__manifest__.py b/addons/hr_timesheet/__manifest__.py index e529653a5e6..841971e8836 100644 --- a/addons/hr_timesheet/__manifest__.py +++ b/addons/hr_timesheet/__manifest__.py @@ -20,7 +20,7 @@ It is completely integrated with the cost accounting module. It allows you to se up a management by affair. """, 'website': 'https://www.odoo.com/page/timesheet-mobile-app', - 'depends': ['hr', 'analytic', 'project', 'uom', 'timer'], + 'depends': ['hr', 'analytic', 'project', 'uom'], 'data': [ 'security/hr_timesheet_security.xml', 'security/ir.model.access.csv', diff --git a/addons/hr_timesheet/models/hr_timesheet.py b/addons/hr_timesheet/models/hr_timesheet.py index 820d7a694ce..dc41a4e5963 100644 --- a/addons/hr_timesheet/models/hr_timesheet.py +++ b/addons/hr_timesheet/models/hr_timesheet.py @@ -9,8 +9,7 @@ from odoo.exceptions import UserError, AccessError from odoo.osv import expression class AccountAnalyticLine(models.Model): - _name = 'account.analytic.line' - _inherit = ['account.analytic.line', 'timer.mixin'] + _inherit = 'account.analytic.line' @api.model def default_get(self, field_list): @@ -48,9 +47,6 @@ class AccountAnalyticLine(models.Model): employee_id = fields.Many2one('hr.employee', "Employee", check_company=True, domain=_domain_employee_id) department_id = fields.Many2one('hr.department', "Department", compute='_compute_department_id', store=True, compute_sudo=True) encoding_uom_id = fields.Many2one('uom.uom', compute='_compute_encoding_uom_id') - display_timer = fields.Boolean( - compute='_compute_display_timer', - help="Technical field used to display the timer if the encoding unit is 'Hours'.") def _compute_encoding_uom_id(self): for analytic_line in self: @@ -198,48 +194,3 @@ class AccountAnalyticLine(models.Model): 'amount': amount_converted, }) return result - - def _compute_display_timer(self): - uom_hour = self.env.ref('uom.product_uom_hour') - for analytic_line in self: - analytic_line.display_timer = analytic_line.encoding_uom_id == uom_hour - - def action_timer_start(self): - """ Start a timer if it isn't already started and the - timesheets allow to track time - """ - if not self.user_timer_id.timer_start and self.display_timer: - super().action_timer_start() - - def action_timer_stop(self): - """ Stop the current timer - """ - if self.user_timer_id.timer_start and self.display_timer: - minutes_spent = super().action_timer_stop() - self._add_timesheet_time(minutes_spent) - - def _add_timesheet_time(self, minutes_spent): - if self.unit_amount == 0 and minutes_spent < 1 and not self._context.get('prevent_deletion', False): - # Check if unit_amount equals 0 and minutes_spent is less than 1 minute, - # if yes, then remove the timesheet - self.unlink() - else: - if minutes_spent < 1: - amount = self.unit_amount - else: - minimum_duration = int(self.env['ir.config_parameter'].sudo().get_param('hr_timesheet.timesheet_min_duration', 0)) - rounding = int(self.env['ir.config_parameter'].sudo().get_param('hr_timesheet.timesheet_rounding', 0)) - minutes_spent = self._timer_rounding(minutes_spent, minimum_duration, rounding) - amount = self.unit_amount + minutes_spent * 60 / 3600 - self.write({'unit_amount': amount}) - - def _action_interrupt_user_timers(self): - self.action_timer_stop() - - def unlink(self): - res = super(AccountAnalyticLine, self).unlink() - self.env['timer.timer'].search([ - ('res_model', '=', self._name), - ('res_id', 'in', self.ids) - ]).unlink() - return res diff --git a/addons/hr_timesheet/models/project.py b/addons/hr_timesheet/models/project.py index 686acad3409..ed0ac3a5bad 100644 --- a/addons/hr_timesheet/models/project.py +++ b/addons/hr_timesheet/models/project.py @@ -16,12 +16,6 @@ class Project(models.Model): ('partner_id', '=?', partner_id), ]""" ) - allow_timesheet_timer = fields.Boolean( - 'Timesheet Timer', - compute='_compute_allow_timesheet_timer', - readonly=False, - store=True, - help="Use a timer to record timesheets on tasks") timesheet_ids = fields.One2many('account.analytic.line', 'project_id', 'Associated Timesheets') timesheet_encode_uom_id = fields.Many2one('uom.uom', related='company_id.timesheet_encode_uom_id') @@ -29,10 +23,6 @@ class Project(models.Model): compute='_compute_total_timesheet_time', help="Total number of time (in the proper UoM) recorded in the project, rounded to the unit.") - _sql_constraints = [ - ('timer_only_when_timesheet', "CHECK((allow_timesheets = 'f' AND allow_timesheet_timer = 'f') OR (allow_timesheets = 't'))", 'The timesheet timer can only be activated on project allowing timesheets.'), - ] - @api.onchange('analytic_account_id') def _onchange_analytic_account(self): if not self.analytic_account_id and self._origin: @@ -44,11 +34,6 @@ class Project(models.Model): if project.allow_timesheets and not project.analytic_account_id: raise ValidationError(_('To allow timesheet, your project %s should have an analytic account set.' % (project.name,))) - @api.depends('allow_timesheets') - def _compute_allow_timesheet_timer(self): - for project in self: - project.allow_timesheet_timer = project.allow_timesheets - @api.depends('timesheet_ids') def _compute_total_timesheet_time(self): for project in self: @@ -87,13 +72,7 @@ class Project(models.Model): for project in self: if not project.analytic_account_id and not values.get('analytic_account_id'): project._create_analytic_account() - result = super(Project, self).write(values) - if 'allow_timesheet_timer' in values and not values.get('allow_timesheet_timer'): - self.with_context(active_test=False).mapped('task_ids').write({ - 'timer_start': False, - 'timer_pause': False, - }) - return result + return super(Project, self).write(values) @api.model def _init_data_analytic_account(self): @@ -120,7 +99,7 @@ class Project(models.Model): class Task(models.Model): _name = "project.task" - _inherit = ["project.task", "timer.mixin"] + _inherit = "project.task" analytic_account_active = fields.Boolean("Active Analytic Account", compute='_compute_analytic_account_active') allow_timesheets = fields.Boolean("Allow timesheets", related='project_id.allow_timesheets', help="Timesheets can be logged on this task.", readonly=True) @@ -132,38 +111,6 @@ class Task(models.Model): subtask_effective_hours = fields.Float("Sub-tasks Hours Spent", compute='_compute_subtask_effective_hours', store=True, help="Time spent on the sub-tasks (and their own sub-tasks) of this task.") timesheet_ids = fields.One2many('account.analytic.line', 'task_id', 'Timesheets') - # YTI FIXME: Those field seems quite useless - timesheet_timer_first_start = fields.Datetime("Timesheet Timer First Use", readonly=True) - timesheet_timer_last_stop = fields.Datetime("Timesheet Timer Last Use", readonly=True) - display_timesheet_timer = fields.Boolean("Display Timesheet Time", compute='_compute_display_timesheet_timer') - - display_timer_start_secondary = fields.Boolean(compute='_compute_display_timer_buttons') - - @api.depends('display_timesheet_timer', 'timer_start', 'timer_pause', 'total_hours_spent') - def _compute_display_timer_buttons(self): - for task in self: - if not task.display_timesheet_timer: - task.update({ - 'display_timer_start_primary': False, - 'display_timer_start_secondary': False, - 'display_timer_stop': False, - 'display_timer_pause': False, - 'display_timer_resume': False, - }) - else: - super(Task, task)._compute_display_timer_buttons() - task.display_timer_start_secondary = task.display_timer_start_primary - if not task.timer_start: - task.update({ - 'display_timer_stop': False, - 'display_timer_pause': False, - 'display_timer_resume': False, - }) - if not task.total_hours_spent: - task.display_timer_start_secondary = False - else: - task.display_timer_start_primary = False - @api.depends('project_id.analytic_account_id.active') def _compute_analytic_account_active(self): """ Overridden in sale_timesheet """ @@ -204,11 +151,6 @@ class Task(models.Model): for task in self: task.subtask_effective_hours = sum(child_task.effective_hours + child_task.subtask_effective_hours for child_task in task.child_ids) - @api.depends('allow_timesheets', 'project_id.allow_timesheet_timer', 'analytic_account_active') - def _compute_display_timesheet_timer(self): - for task in self: - task.display_timesheet_timer = task.allow_timesheets and task.project_id.allow_timesheet_timer and task.analytic_account_active - def action_view_subtask_timesheet(self): self.ensure_one() tasks = self._get_all_subtasks() @@ -256,35 +198,6 @@ class Task(models.Model): result['arch'] = self.env['account.analytic.line']._apply_timesheet_label(result['arch']) return result - def action_timer_start(self): - if not self.user_timer_id.timer_start and self.display_timesheet_timer: - super(Task, self).action_timer_start() - - def action_timer_stop(self): - # timer was either running or paused - if self.user_timer_id.timer_start and self.display_timesheet_timer: - minutes_spent = super().action_timer_stop() - minimum_duration = int(self.env['ir.config_parameter'].sudo().get_param('hr_timesheet.timesheet_min_duration', 0)) - rounding = int(self.env['ir.config_parameter'].sudo().get_param('hr_timesheet.timesheet_rounding', 0)) - minutes_spent = self._timer_rounding(minutes_spent, minimum_duration, rounding) - return self._action_create_timesheet(minutes_spent * 60 / 3600) - return False - - def _action_create_timesheet(self, time_spent): - return { - "name": _("Validate Spent Time"), - "type": 'ir.actions.act_window', - "res_model": 'project.task.create.timesheet', - "views": [[False, "form"]], - "target": 'new', - "context": { - **self.env.context, - 'active_id': self.id, - 'active_model': self._name, - 'default_time_spent': time_spent, - }, - } - def unlink(self): """ If some tasks to unlink have some timesheets entries, these diff --git a/addons/hr_timesheet/static/src/js/timesheet_kanban_view.js b/addons/hr_timesheet/static/src/js/timesheet_kanban_view.js deleted file mode 100644 index 9a577a9895d..00000000000 --- a/addons/hr_timesheet/static/src/js/timesheet_kanban_view.js +++ /dev/null @@ -1,34 +0,0 @@ -odoo.define('hr_timesheet.timesheet_kanban_view', function (require) { -"use strict"; - -const KanbanController = require('web.KanbanController'); -const KanbanView = require('web.KanbanView'); -const viewRegistry = require('web.view_registry'); - -/** - * @override the KanbanController to add a trigger when a timer is launched or stopped - */ -const TimesheetKanbanController = KanbanController.extend({ - custom_events: _.extend({}, KanbanController.prototype.custom_events, { - 'timer_changed': '_onTimerChanged', - }), - /** - * When a timer is launched or stopped, we reload the view to see the updating. - * @param {Object} event - */ - _onTimerChanged: function (event) { - this.reload(); - } -}); - -const TimesheetKanbanView = KanbanView.extend({ - config: _.extend({}, KanbanView.prototype.config, { - Controller: TimesheetKanbanController - }) -}); - -viewRegistry.add('timesheet_kanban_view', TimesheetKanbanView); - -return { TimesheetKanbanController, TimesheetKanbanView }; - -}); diff --git a/addons/hr_timesheet/static/src/js/timesheet_list_view.js b/addons/hr_timesheet/static/src/js/timesheet_list_view.js deleted file mode 100644 index 903352a35de..00000000000 --- a/addons/hr_timesheet/static/src/js/timesheet_list_view.js +++ /dev/null @@ -1,34 +0,0 @@ -odoo.define('hr_timesheet.timesheet_list_view', function (require) { -"use strict"; - -const ListController = require('web.ListController'); -var ListView = require('web.ListView'); -var viewRegistry = require('web.view_registry'); - -/** - * @override the ListController to add a trigger when the timer is launched or stopped - */ -const TimesheetListController = ListController.extend({ - custom_events: _.extend({}, ListController.prototype.custom_events, { - 'timer_changed': '_onTimerChanged', - }), - /** - * When a timer is launched or stopped, we reload the view to see the updating. - * @param {Object} event - */ - _onTimerChanged: function (event) { - this.reload(); - } -}); - -const TimesheetListView = ListView.extend({ - config: _.extend({}, ListView.prototype.config, { - Controller: TimesheetListController - }) -}); - -viewRegistry.add('timesheet_tree', TimesheetListView); - -return { TimesheetListController, TimesheetListView }; - -}); diff --git a/addons/hr_timesheet/static/src/js/timesheet_uom.js b/addons/hr_timesheet/static/src/js/timesheet_uom.js index acfd9fc6e5b..45979121bfa 100644 --- a/addons/hr_timesheet/static/src/js/timesheet_uom.js +++ b/addons/hr_timesheet/static/src/js/timesheet_uom.js @@ -6,8 +6,6 @@ const fieldUtils = require('web.field_utils'); const fieldRegistry = require('web.field_registry'); -const Timer = require('timer.Timer'); - // We need the field registry to be populated, as we bind the // timesheet_uom widget on existing field widgets. require('web._field_registry'); @@ -74,8 +72,7 @@ const FieldTimesheetToggle = basicFields.FieldFloatToggle.extend({ /** - * Extend float time widget to add the using of a timer for duration - * (unit_amount) field. + * Extend float time widget */ const FieldTimesheetTime = basicFields.FieldFloatTime.extend({ init: function () { @@ -85,54 +82,7 @@ const FieldTimesheetTime = basicFields.FieldFloatTime.extend({ this.nodeOptions.factor = session.timesheet_uom_factor; this.parseOptions.factor = session.timesheet_uom_factor; } - }, - willstart() { - const timePromise = this._rpc({ - model: 'timer.timer', - method: 'get_server_time', - args: [] - }).then((time) => { - this.serverTime = time; - }); - return Promise.all([ - this._super(...arguments), - timePromise, - ]); - }, - - _render: async function () { - await this._super.apply(this, arguments); - // Check if the timer_start exists and it's not false - // In other word, when user clicks on play button, this button - // launches the "action_timer_start". - if (this.recordData.timer_start && !this.recordData.timer_pause) { - this.time = Timer.createTimer(this.recordData.unit_amount, this.recordData.timer_start, this.serverTime); - this._startTimeCounter(); - } - }, - /** - * @override - */ - destroy: function () { - clearTimeout(this.timer); - this._super.apply(this, arguments); - }, - _startTimeCounter: function () { - if (this.time) { - this.timer = setInterval(() => { - this.time.addSecond(); - if (this.$el.children().length) { - this.$el.contents()[1].replaceWith(this.time.toString()); - } else { - this.$el.text(this.time.toString()); - } - this.$el.addClass('font-weight-bold text-danger'); - }, 1000); - } else { - clearTimeout(this.timer); - this.$el.removeClass('font-weight-bold text-danger'); - } - }, + } }); diff --git a/addons/hr_timesheet/static/src/js/timesheet_uom_timer.js b/addons/hr_timesheet/static/src/js/timesheet_uom_timer.js index 165dfa6eb92..4eae761f444 100644 --- a/addons/hr_timesheet/static/src/js/timesheet_uom_timer.js +++ b/addons/hr_timesheet/static/src/js/timesheet_uom_timer.js @@ -48,12 +48,11 @@ const FieldTimesheetTimeTimer = TimesheetUom.FieldTimesheetTime.extend({ _onToggleButton: async function (event) { const context = this.record.getContext(); - const prevent_deletion = this.attrs.options && this.attrs.options.prevent_deletion || false; event.stopPropagation(); const result = await this._rpc({ model: this.model, method: this._getActionButton(), - context: $.extend({}, context, {prevent_deletion: prevent_deletion}), + context: context, args: [this.res_id] }); diff --git a/addons/hr_timesheet/static/src/scss/timer_button.scss b/addons/hr_timesheet/static/src/scss/timer_button.scss deleted file mode 100644 index 8b269fa8b20..00000000000 --- a/addons/hr_timesheet/static/src/scss/timer_button.scss +++ /dev/null @@ -1,26 +0,0 @@ -.o-timer-button { - &:focus { - border: none !important; - outline: 0 !important; - } - - & > i { - transition: 0.3s; - - &.o-timer-play-button { - color: $link-color !important; - } - - &.o-timer-stop-button { - color: $red !important; - } - } - - &:hover > i.o-timer-play-button { - color: $link-hover-color !important; - } - - &:hover > i.o-timer-stop-button { - color: darken($red, 15%) !important; - } -} diff --git a/addons/hr_timesheet/tests/test_timesheet.py b/addons/hr_timesheet/tests/test_timesheet.py index f0cdc38a0da..463c0fdbdac 100644 --- a/addons/hr_timesheet/tests/test_timesheet.py +++ b/addons/hr_timesheet/tests/test_timesheet.py @@ -4,8 +4,6 @@ from odoo.tests.common import TransactionCase from odoo.exceptions import AccessError, UserError -from datetime import datetime, timedelta - class TestCommonTimesheet(TransactionCase): @@ -37,7 +35,6 @@ class TestCommonTimesheet(TransactionCase): 'allow_timesheets': True, 'partner_id': self.partner.id, 'analytic_account_id': self.analytic_account.id, - 'allow_timesheet_timer': True }) self.task1 = self.env['project.task'].create({ 'name': 'Task One', @@ -172,7 +169,6 @@ class TestTimesheet(TestCommonTimesheet): non_tracked_project = self.env['project.project'].create({ 'name': 'Project without timesheet', 'allow_timesheets': False, - 'allow_timesheet_timer': False, 'partner_id': self.partner.id, }) self.assertFalse(non_tracked_project.analytic_account_id, "A non time-tracked project shouldn't generate an analytic account") @@ -289,77 +285,3 @@ class TestTimesheet(TestCommonTimesheet): }, { 'amount': -12.0, }]) - - def test_minutes_computing_after_timer_stop(self): - """ Test if unit_amount is updated after stoping a timer """ - Timesheet = self.env['account.analytic.line'] - timesheet_1 = Timesheet.with_user(self.user_employee).create({ - 'project_id': self.project_customer.id, - 'task_id': self.task1.id, - 'name': '/', - 'unit_amount': 1, - }) - - # When the timer is less than 1 minute - now = datetime.now() - timesheet_1.with_user(self.user_employee).action_timer_start() - timesheet_1.with_user(self.user_employee).user_timer_id.timer_start = now - timedelta(seconds=28) - timesheet_1.with_user(self.user_employee).action_timer_stop() - - self.assertEqual(timesheet_1.unit_amount, 1, 'unit_amount still should have the same value') - - # When the timer is greater than 1 minute - now = datetime.now() - timesheet_1.with_user(self.user_employee).action_timer_start() - timesheet_1.with_user(self.user_employee).user_timer_id.timer_start = now - timedelta(minutes=1, seconds=28) - timesheet_1.with_user(self.user_employee).action_timer_stop() - - self.assertGreater(timesheet_1.unit_amount, 1, 'unit_amount should be greated than his last value') - - def test_allow_timesheets_and_timer(self): - """ - Check that a modification of the 'allow_timesheets' field updates correctly the - 'allow_timesheet_timer' field. - """ - Project = self.env['project.project'] - - # case 1: create a project with allow_timesheets set to FALSE - project_1 = Project.create({ - 'name': 'Project 1', - 'allow_timesheets': False, - 'partner_id': self.partner.id - }) - - self.assertFalse( - project_1.allow_timesheet_timer, - "On project creation with 'allow_timesheets' set to FALSE, 'allow_timesheet_timer' shall be set to FALSE") - - # case 2: create a project with allow_timesheets set to TRUE - project_2 = Project.create({ - 'name': 'Project 2', - 'allow_timesheets': True, - 'partner_id': self.partner.id, - 'analytic_account_id': self.analytic_account.id - }) - - self.assertTrue( - project_2.allow_timesheet_timer, - "On project creation with 'allow_timesheets' set to TRUE, 'allow_timesheet_timer' shall be set to TRUE") - - # case 3: change 'allow_timesheets' from FALSE to TRUE - project_1.write({ - 'allow_timesheets': True - }) - - self.assertTrue( - project_1.allow_timesheet_timer, - "On 'allow_timesheets' change to TRUE, 'allow_timesheet_timer' shall be set to TRUE") - - # case 4: change 'allow_timesheets' from TRUE to FALSE - project_2.write({ - 'allow_timesheets': False - }) - - self.assertFalse( - project_2.allow_timesheet_timer, - "On 'allow_timesheets' change to FALSE, 'allow_timesheet_timer' shall be set to FALSE") diff --git a/addons/hr_timesheet/views/assets.xml b/addons/hr_timesheet/views/assets.xml index b20bdf051b8..816f36f5c53 100644 --- a/addons/hr_timesheet/views/assets.xml +++ b/addons/hr_timesheet/views/assets.xml @@ -2,12 +2,8 @@