From e7dda3fab002f5db930b4af340787177d597d59e Mon Sep 17 00:00:00 2001 From: jbm-odoo Date: Thu, 28 May 2020 08:33:19 +0200 Subject: [PATCH] [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),