diff --git a/automatic_project_task_timer/README.rst b/automatic_project_task_timer/README.rst new file mode 100644 index 000000000..02b7f670d --- /dev/null +++ b/automatic_project_task_timer/README.rst @@ -0,0 +1,50 @@ +.. image:: https://img.shields.io/badge/license-AGPL--3-blue.svg + :target: https://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 + +Automatic Project Task Timer +============================ +App for running the timer automatically for the task comes in In Progress stage. + +Configuration +============= +* For configuring the timer, Go to Users --> Set the user group as Administrator + for Projects then, + + Projects --> Configuration --> Timer Configuration menu to configure the + project and stage. + +Company +------- +* `Cybrosys Techno Solutions `__ + +License +------- +GNU AFFERO GENERAL PUBLIC LICENSE v3.0 (AGPL-3) +(https://www.gnu.org/licenses/agpl-3.0-standalone.html) + +Credits +------- +* Developers: (V16) Prathyunnan R, Contact: odoo@cybrosys.com + +Contacts +-------- +* Mail Contact : odoo@cybrosys.com +* Website : https://cybrosys.com + +Bug Tracker +----------- +Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. + +Maintainer +========== +.. image:: https://cybrosys.com/images/logo.png + :target: https://cybrosys.com + +This module is maintained by Cybrosys Technologies. + +For support and more information, please visit `Our Website `__ + +Further information +=================== +HTML Description: ``__ diff --git a/automatic_project_task_timer/__init__.py b/automatic_project_task_timer/__init__.py new file mode 100644 index 000000000..a2f5f7fc0 --- /dev/null +++ b/automatic_project_task_timer/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies() +# Author: Prathyunnan R(odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +############################################################################### +from . import models diff --git a/automatic_project_task_timer/__manifest__.py b/automatic_project_task_timer/__manifest__.py new file mode 100644 index 000000000..7a33c62c5 --- /dev/null +++ b/automatic_project_task_timer/__manifest__.py @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies() +# Author: Prathyunnan R(odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +############################################################################### +{ + 'name': 'Automatic Project Task Timer', + 'version': '16.0.1.0.0', + 'category': 'Project', + 'summary': 'Automatic Running Timer for Project Tasks', + 'description': "This module helps you to track time sheet in project " + "using a real timer, it's starts when task is in " + "configured stage and stops when its moves to any other " + "stage and the timesheet will be recorded.", + 'author': 'Cybrosys Techno Solutions', + 'company': 'Cybrosys Techno Solutions', + 'maintainer': 'Cybrosys Techno Solutions', + 'website': 'https://www.cybrosys.com', + 'depends': ['hr_timesheet'], + 'data': [ + 'security/ir.model.access.csv', + 'views/project_task_views.xml', + 'views/res_config_settings_views.xml', + 'views/timer_configuration_views.xml' + ], + 'assets': { + 'web.assets_backend': [ + 'automatic_project_task_timer/static/src/js/task_timer.js', + 'automatic_project_task_timer/static/src/js/form_open.js', + 'automatic_project_task_timer/static/src/xml/task_timer_templates.xml', + ]}, + 'images': ['static/description/banner.png'], + 'license': 'AGPL-3', + 'installable': True, + 'auto_install': False, + 'application': False, +} diff --git a/automatic_project_task_timer/doc/RELEASE_NOTES.md b/automatic_project_task_timer/doc/RELEASE_NOTES.md new file mode 100644 index 000000000..08a4d005f --- /dev/null +++ b/automatic_project_task_timer/doc/RELEASE_NOTES.md @@ -0,0 +1,5 @@ +## Module +#### 02.12.2023 +#### Version 16.0.1.0.0 +#### ADD +- Initial commit for Automatic Project Task Timer diff --git a/automatic_project_task_timer/models/__init__.py b/automatic_project_task_timer/models/__init__.py new file mode 100644 index 000000000..7856db05d --- /dev/null +++ b/automatic_project_task_timer/models/__init__.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies() +# Author: Prathyunnan R(odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +############################################################################### +from . import account_analytic_line +from . import project_task +from . import res_config_settings +from . import timer_configuration diff --git a/automatic_project_task_timer/models/account_analytic_line.py b/automatic_project_task_timer/models/account_analytic_line.py new file mode 100644 index 000000000..7262c9c81 --- /dev/null +++ b/automatic_project_task_timer/models/account_analytic_line.py @@ -0,0 +1,37 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies() +# Author: Prathyunnan R(odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +############################################################################### +from odoo import fields, models + + +class AccountAnalyticLine(models.Model): + """inherited the 'account.analytic.line' for showing the time records.""" + _inherit = 'account.analytic.line' + + date_start = fields.Datetime(string='Start Date', help='Shows the ' + 'starting time of ' + 'the timer') + date_end = fields.Datetime(string='End Date', readonly=1, help='Shows ' + 'the ending' + ' time of ' + 'the timer') + timer_duration = fields.Float(invisible=1, string='Time Duration(Minutes)', + help='Shows the real time ') diff --git a/automatic_project_task_timer/models/project_task.py b/automatic_project_task_timer/models/project_task.py new file mode 100644 index 000000000..05c809093 --- /dev/null +++ b/automatic_project_task_timer/models/project_task.py @@ -0,0 +1,147 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies() +# Author: Prathyunnan R(odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +############################################################################### +from datetime import datetime +from odoo import api, fields, models + + +class Task(models.Model): + """inherited the 'project.task' for running the timer """ + _inherit = 'project.task' + + task_timer = fields.Boolean(string='Timer', default=False, + help='Activated when task configured stage') + is_user_working = fields.Boolean(string='Is Current User Working', + compute='_compute_is_user_working', + help="Technical field indicating whether " + "the current user is working. ") + duration = fields.Float(string='Real Duration', store=True, copy=False, + readonly=False, help='Shows the duration') + is_status_stage = fields.Boolean(string='Stage Status', + help='To set the status of task at the ' + 'initial time.') + check_stage = fields.Integer(string='Stage', + compute='_compute_check_stage', + help='To check the stage whether it is ' + 'configured or not') + + def _compute_check_stage(self): + """To check the stage whether it is configured or not, for that + assigning the configured stage id to this field.""" + for rec in self: + rec.check_stage = self.env['timer.configuration'].search( + [('project_id.id', '=', rec.project_id.id)]).stage_id.id + + @api.constrains('stage_id') + def _task_timer(self): + """Checks the status of timer setting and + toggle the task timer boolean to active """ + self.write({ + 'is_status_stage': False + }) + timer_setting = self.env['ir.config_parameter'].sudo().get_param( + 'automatic_project_task_timer.timer_setting') + if timer_setting: + for rec in self.env['timer.configuration'].search([]): + if self.project_id == rec.project_id: + if self.stage_id.id == rec.stage_id.id: + self.write({'task_timer': True}) + else: + self.write({'task_timer': False}) + + def _compute_is_user_working(self): + """ Checks whether the current user is working """ + for order in self: + if order.timesheet_ids.filtered( + lambda x: (x.user_id.id == self.env.user.id) and ( + not x.date_end)): + order.is_user_working = True + else: + order.is_user_working = False + + @api.model + @api.constrains('task_timer') + def toggle_start(self): + """The time sheet record will be created + by checking all the conditions """ + time_line_obj = self.env['account.analytic.line'] + for rec in self: + if rec.task_timer is True: + rec.write({'is_user_working': True}) + for time_sheet in rec: + time_line_obj.create({ + 'name': '%s : %s' % (self.env.user.name, + time_sheet.name), + 'task_id': time_sheet.id, + 'user_id': self.env.user.id, + 'project_id': time_sheet.project_id.id, + 'date_start': datetime.now(), + }) + else: + rec.write({'is_user_working': False}) + for time_line in time_line_obj.search( + [('task_id', 'in', self.ids), + ('date_end', '=', False)]): + time_line.write({'date_end': fields.Datetime.now()}) + if time_line.date_start: + if time_line.date_end: + diff = fields.Datetime.from_string( + time_line.date_end) \ + - fields.Datetime.from_string( + time_line.date_start).replace( + second=0, microsecond=0) + time_line.timer_duration = \ + round(diff.total_seconds() / 60.0, 2) + time_line.unit_amount = \ + round(diff.total_seconds() / (60.0 * 60.0), 2) + else: + time_line.unit_amount = 0.0 + time_line.timer_duration = 0.0 + else: + time_line.write({'date_start': fields.Datetime.now()}) + if time_line.date_end: + diff = fields.Datetime.from_string( + time_line.date_end) \ + - fields.Datetime.from_string( + time_line.date_start).replace( + second=0, microsecond=0) + time_line.timer_duration = \ + round(diff.total_seconds() / 60.0, 2) + time_line.unit_amount = \ + round(diff.total_seconds() / (60.0 * 60.0), 2) + else: + time_line.unit_amount = 0.0 + time_line.timer_duration = 0.0 + + def get_working_duration(self): + """Get the additional duration for 'open times' + i.e. productivity lines with no date_end.""" + self.ensure_one() + duration = 0 + for time in \ + self.timesheet_ids.filtered(lambda time: not time.date_end): + if type(time.date_start) != datetime: + time.date_start = datetime.now() + duration = 0 + else: + duration += \ + (datetime.now() - time.date_start).total_seconds() / 60 + return duration diff --git a/automatic_project_task_timer/models/res_config_settings.py b/automatic_project_task_timer/models/res_config_settings.py new file mode 100644 index 000000000..812d6c6db --- /dev/null +++ b/automatic_project_task_timer/models/res_config_settings.py @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies() +# Author: Prathyunnan R(odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +############################################################################### +from odoo import fields, models + + +class ResConfigSettings(models.TransientModel): + """inherited the 'res.config.settings' + for activating timer in project module.""" + _inherit = 'res.config.settings' + + timer_setting = fields.Boolean( + string='Task Timer', + config_parameter='automatic_project_task_timer.timer_setting', + help='Enable to activate the timer') diff --git a/automatic_project_task_timer/models/timer_configuration.py b/automatic_project_task_timer/models/timer_configuration.py new file mode 100644 index 000000000..6e3e93328 --- /dev/null +++ b/automatic_project_task_timer/models/timer_configuration.py @@ -0,0 +1,73 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies() +# Author: Prathyunnan R(odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +############################################################################### +from odoo import api, fields, models + + +class TimerConfiguration(models.Model): + """Timer configuration model for configure the automatic timer + stage to activate the timer, Each project have different stages, + based on the configured stage for each project the timer will be runs.""" + _name = 'timer.configuration' + _description = 'Timer Configuration' + + project_id = fields.Many2one('project.project', string='Project', + help='Configure the project to activate the ' + 'timer') + stage_ids = fields.Many2many('project.task.type', + string='Stages', + help='To set the domain for stages') + stage_id = fields.Many2one('project.task.type', string='Stage', + help='Set the stage to activate the timer', + domain="[('id', 'in', stage_ids)]", + required=True) + + @api.onchange('project_id') + def _onchange_project_id(self): + """To set the domain for stage_id field to select the stages + from the stages of the selected project""" + data = [] + for rec in self.env['project.task.type'].search([]): + if self.project_id.id in rec.project_ids.ids: + data.append(rec.id) + self.stage_ids = data + + @api.model + def create(self, vals): + """To set the status stage for all the tasks in the corresponding + project, so that the warning message will pop-ups when the form + opens. For that supering the ORM Create method to get the corresponding + project. """ + projects = self.env['project.project'].sudo().browse(vals.get( + 'project_id')) + tasks = self.env['project.task'].search([]).filtered( + lambda sol: sol.project_id == projects) + for records in tasks: + if records.stage_id.id == vals.get('stage_id'): + records.write({ + 'is_status_stage': True + }) + else: + records.write({ + 'is_status_stage': False + }) + res = super(TimerConfiguration, self).create(vals) + return res diff --git a/automatic_project_task_timer/security/ir.model.access.csv b/automatic_project_task_timer/security/ir.model.access.csv new file mode 100644 index 000000000..f6a7ffa10 --- /dev/null +++ b/automatic_project_task_timer/security/ir.model.access.csv @@ -0,0 +1,3 @@ +id,name,model_id/id,group_id/id,perm_read,perm_write,perm_create,perm_unlink +access_timer_configuration_manager,access.timer.configuration.manager,model_timer_configuration,project.group_project_manager,1,1,1,1 +access_timer_configuration_user,access.timer.configuration.user,model_timer_configuration,project.group_project_user,0,0,1,0 diff --git a/automatic_project_task_timer/static/description/assets/icons/check.png b/automatic_project_task_timer/static/description/assets/icons/check.png new file mode 100644 index 000000000..c8e85f51d Binary files /dev/null and b/automatic_project_task_timer/static/description/assets/icons/check.png differ diff --git a/automatic_project_task_timer/static/description/assets/icons/chevron.png b/automatic_project_task_timer/static/description/assets/icons/chevron.png new file mode 100644 index 000000000..2089293d6 Binary files /dev/null and b/automatic_project_task_timer/static/description/assets/icons/chevron.png differ diff --git a/automatic_project_task_timer/static/description/assets/icons/cogs.png b/automatic_project_task_timer/static/description/assets/icons/cogs.png new file mode 100644 index 000000000..95d0bad62 Binary files /dev/null and b/automatic_project_task_timer/static/description/assets/icons/cogs.png differ diff --git a/automatic_project_task_timer/static/description/assets/icons/consultation.png b/automatic_project_task_timer/static/description/assets/icons/consultation.png new file mode 100644 index 000000000..8319d4baa Binary files /dev/null and b/automatic_project_task_timer/static/description/assets/icons/consultation.png differ diff --git a/automatic_project_task_timer/static/description/assets/icons/ecom-black.png b/automatic_project_task_timer/static/description/assets/icons/ecom-black.png new file mode 100644 index 000000000..a9385ff13 Binary files /dev/null and b/automatic_project_task_timer/static/description/assets/icons/ecom-black.png differ diff --git a/automatic_project_task_timer/static/description/assets/icons/education-black.png b/automatic_project_task_timer/static/description/assets/icons/education-black.png new file mode 100644 index 000000000..3eb09b27b Binary files /dev/null and b/automatic_project_task_timer/static/description/assets/icons/education-black.png differ diff --git a/automatic_project_task_timer/static/description/assets/icons/hotel-black.png b/automatic_project_task_timer/static/description/assets/icons/hotel-black.png new file mode 100644 index 000000000..130f613be Binary files /dev/null and b/automatic_project_task_timer/static/description/assets/icons/hotel-black.png differ diff --git a/automatic_project_task_timer/static/description/assets/icons/license.png b/automatic_project_task_timer/static/description/assets/icons/license.png new file mode 100644 index 000000000..a5869797e Binary files /dev/null and b/automatic_project_task_timer/static/description/assets/icons/license.png differ diff --git a/automatic_project_task_timer/static/description/assets/icons/lifebuoy.png b/automatic_project_task_timer/static/description/assets/icons/lifebuoy.png new file mode 100644 index 000000000..658d56ccc Binary files /dev/null and b/automatic_project_task_timer/static/description/assets/icons/lifebuoy.png differ diff --git a/automatic_project_task_timer/static/description/assets/icons/manufacturing-black.png b/automatic_project_task_timer/static/description/assets/icons/manufacturing-black.png new file mode 100644 index 000000000..697eb0e9f Binary files /dev/null and b/automatic_project_task_timer/static/description/assets/icons/manufacturing-black.png differ diff --git a/automatic_project_task_timer/static/description/assets/icons/pos-black.png b/automatic_project_task_timer/static/description/assets/icons/pos-black.png new file mode 100644 index 000000000..97c0f90c1 Binary files /dev/null and b/automatic_project_task_timer/static/description/assets/icons/pos-black.png differ diff --git a/automatic_project_task_timer/static/description/assets/icons/puzzle.png b/automatic_project_task_timer/static/description/assets/icons/puzzle.png new file mode 100644 index 000000000..65cf854e7 Binary files /dev/null and b/automatic_project_task_timer/static/description/assets/icons/puzzle.png differ diff --git a/automatic_project_task_timer/static/description/assets/icons/restaurant-black.png b/automatic_project_task_timer/static/description/assets/icons/restaurant-black.png new file mode 100644 index 000000000..4a35eb939 Binary files /dev/null and b/automatic_project_task_timer/static/description/assets/icons/restaurant-black.png differ diff --git a/automatic_project_task_timer/static/description/assets/icons/service-black.png b/automatic_project_task_timer/static/description/assets/icons/service-black.png new file mode 100644 index 000000000..301ab51cb Binary files /dev/null and b/automatic_project_task_timer/static/description/assets/icons/service-black.png differ diff --git a/automatic_project_task_timer/static/description/assets/icons/trading-black.png b/automatic_project_task_timer/static/description/assets/icons/trading-black.png new file mode 100644 index 000000000..9398ba2f1 Binary files /dev/null and b/automatic_project_task_timer/static/description/assets/icons/trading-black.png differ diff --git a/automatic_project_task_timer/static/description/assets/icons/training.png b/automatic_project_task_timer/static/description/assets/icons/training.png new file mode 100644 index 000000000..884ca024d Binary files /dev/null and b/automatic_project_task_timer/static/description/assets/icons/training.png differ diff --git a/automatic_project_task_timer/static/description/assets/icons/update.png b/automatic_project_task_timer/static/description/assets/icons/update.png new file mode 100644 index 000000000..ecbc5a01a Binary files /dev/null and b/automatic_project_task_timer/static/description/assets/icons/update.png differ diff --git a/automatic_project_task_timer/static/description/assets/icons/user.png b/automatic_project_task_timer/static/description/assets/icons/user.png new file mode 100644 index 000000000..6ffb23d9f Binary files /dev/null and b/automatic_project_task_timer/static/description/assets/icons/user.png differ diff --git a/automatic_project_task_timer/static/description/assets/icons/wrench.png b/automatic_project_task_timer/static/description/assets/icons/wrench.png new file mode 100644 index 000000000..6c04dea0f Binary files /dev/null and b/automatic_project_task_timer/static/description/assets/icons/wrench.png differ diff --git a/automatic_project_task_timer/static/description/assets/misc/categories.png b/automatic_project_task_timer/static/description/assets/misc/categories.png new file mode 100644 index 000000000..bedf1e0b1 Binary files /dev/null and b/automatic_project_task_timer/static/description/assets/misc/categories.png differ diff --git a/automatic_project_task_timer/static/description/assets/misc/check-box.png b/automatic_project_task_timer/static/description/assets/misc/check-box.png new file mode 100644 index 000000000..42caf24b9 Binary files /dev/null and b/automatic_project_task_timer/static/description/assets/misc/check-box.png differ diff --git a/automatic_project_task_timer/static/description/assets/misc/compass.png b/automatic_project_task_timer/static/description/assets/misc/compass.png new file mode 100644 index 000000000..d5fed8faa Binary files /dev/null and b/automatic_project_task_timer/static/description/assets/misc/compass.png differ diff --git a/automatic_project_task_timer/static/description/assets/misc/corporate.png b/automatic_project_task_timer/static/description/assets/misc/corporate.png new file mode 100644 index 000000000..2eb13edbf Binary files /dev/null and b/automatic_project_task_timer/static/description/assets/misc/corporate.png differ diff --git a/automatic_project_task_timer/static/description/assets/misc/customer-support.png b/automatic_project_task_timer/static/description/assets/misc/customer-support.png new file mode 100644 index 000000000..79efc72ed Binary files /dev/null and b/automatic_project_task_timer/static/description/assets/misc/customer-support.png differ diff --git a/automatic_project_task_timer/static/description/assets/misc/cybrosys-logo.png b/automatic_project_task_timer/static/description/assets/misc/cybrosys-logo.png new file mode 100644 index 000000000..cc3cc0ccf Binary files /dev/null and b/automatic_project_task_timer/static/description/assets/misc/cybrosys-logo.png differ diff --git a/automatic_project_task_timer/static/description/assets/misc/features.png b/automatic_project_task_timer/static/description/assets/misc/features.png new file mode 100644 index 000000000..b41769f77 Binary files /dev/null and b/automatic_project_task_timer/static/description/assets/misc/features.png differ diff --git a/automatic_project_task_timer/static/description/assets/misc/logo.png b/automatic_project_task_timer/static/description/assets/misc/logo.png new file mode 100644 index 000000000..478462d3e Binary files /dev/null and b/automatic_project_task_timer/static/description/assets/misc/logo.png differ diff --git a/automatic_project_task_timer/static/description/assets/misc/pictures.png b/automatic_project_task_timer/static/description/assets/misc/pictures.png new file mode 100644 index 000000000..56d255fe9 Binary files /dev/null and b/automatic_project_task_timer/static/description/assets/misc/pictures.png differ diff --git a/automatic_project_task_timer/static/description/assets/misc/pie-chart.png b/automatic_project_task_timer/static/description/assets/misc/pie-chart.png new file mode 100644 index 000000000..426e05244 Binary files /dev/null and b/automatic_project_task_timer/static/description/assets/misc/pie-chart.png differ diff --git a/automatic_project_task_timer/static/description/assets/misc/right-arrow.png b/automatic_project_task_timer/static/description/assets/misc/right-arrow.png new file mode 100644 index 000000000..730984a06 Binary files /dev/null and b/automatic_project_task_timer/static/description/assets/misc/right-arrow.png differ diff --git a/automatic_project_task_timer/static/description/assets/misc/star.png b/automatic_project_task_timer/static/description/assets/misc/star.png new file mode 100644 index 000000000..2eb9ab29f Binary files /dev/null and b/automatic_project_task_timer/static/description/assets/misc/star.png differ diff --git a/automatic_project_task_timer/static/description/assets/misc/support.png b/automatic_project_task_timer/static/description/assets/misc/support.png new file mode 100644 index 000000000..4f18b8b82 Binary files /dev/null and b/automatic_project_task_timer/static/description/assets/misc/support.png differ diff --git a/automatic_project_task_timer/static/description/assets/misc/whatsapp.png b/automatic_project_task_timer/static/description/assets/misc/whatsapp.png new file mode 100644 index 000000000..d513a5356 Binary files /dev/null and b/automatic_project_task_timer/static/description/assets/misc/whatsapp.png differ diff --git a/automatic_project_task_timer/static/description/assets/modules/1.png b/automatic_project_task_timer/static/description/assets/modules/1.png new file mode 100644 index 000000000..8047cf484 Binary files /dev/null and b/automatic_project_task_timer/static/description/assets/modules/1.png differ diff --git a/automatic_project_task_timer/static/description/assets/modules/2.jpg b/automatic_project_task_timer/static/description/assets/modules/2.jpg new file mode 100644 index 000000000..9e2de064a Binary files /dev/null and b/automatic_project_task_timer/static/description/assets/modules/2.jpg differ diff --git a/automatic_project_task_timer/static/description/assets/modules/3.png b/automatic_project_task_timer/static/description/assets/modules/3.png new file mode 100644 index 000000000..d0a1ba017 Binary files /dev/null and b/automatic_project_task_timer/static/description/assets/modules/3.png differ diff --git a/automatic_project_task_timer/static/description/assets/modules/4.png b/automatic_project_task_timer/static/description/assets/modules/4.png new file mode 100644 index 000000000..6c8c8adc3 Binary files /dev/null and b/automatic_project_task_timer/static/description/assets/modules/4.png differ diff --git a/automatic_project_task_timer/static/description/assets/modules/5.png b/automatic_project_task_timer/static/description/assets/modules/5.png new file mode 100644 index 000000000..4e8874e3f Binary files /dev/null and b/automatic_project_task_timer/static/description/assets/modules/5.png differ diff --git a/automatic_project_task_timer/static/description/assets/modules/6.png b/automatic_project_task_timer/static/description/assets/modules/6.png new file mode 100644 index 000000000..5acf9a06a Binary files /dev/null and b/automatic_project_task_timer/static/description/assets/modules/6.png differ diff --git a/automatic_project_task_timer/static/description/assets/screenshots/hero.gif b/automatic_project_task_timer/static/description/assets/screenshots/hero.gif new file mode 100644 index 000000000..f15f22d02 Binary files /dev/null and b/automatic_project_task_timer/static/description/assets/screenshots/hero.gif differ diff --git a/automatic_project_task_timer/static/description/assets/screenshots/screenshot_1.png b/automatic_project_task_timer/static/description/assets/screenshots/screenshot_1.png new file mode 100644 index 000000000..308dfbbbb Binary files /dev/null and b/automatic_project_task_timer/static/description/assets/screenshots/screenshot_1.png differ diff --git a/automatic_project_task_timer/static/description/assets/screenshots/screenshot_10.png b/automatic_project_task_timer/static/description/assets/screenshots/screenshot_10.png new file mode 100644 index 000000000..f9d10ef3d Binary files /dev/null and b/automatic_project_task_timer/static/description/assets/screenshots/screenshot_10.png differ diff --git a/automatic_project_task_timer/static/description/assets/screenshots/screenshot_2.png b/automatic_project_task_timer/static/description/assets/screenshots/screenshot_2.png new file mode 100644 index 000000000..0c2074b98 Binary files /dev/null and b/automatic_project_task_timer/static/description/assets/screenshots/screenshot_2.png differ diff --git a/automatic_project_task_timer/static/description/assets/screenshots/screenshot_3.png b/automatic_project_task_timer/static/description/assets/screenshots/screenshot_3.png new file mode 100644 index 000000000..b2e551960 Binary files /dev/null and b/automatic_project_task_timer/static/description/assets/screenshots/screenshot_3.png differ diff --git a/automatic_project_task_timer/static/description/assets/screenshots/screenshot_4.png b/automatic_project_task_timer/static/description/assets/screenshots/screenshot_4.png new file mode 100644 index 000000000..d9480928b Binary files /dev/null and b/automatic_project_task_timer/static/description/assets/screenshots/screenshot_4.png differ diff --git a/automatic_project_task_timer/static/description/assets/screenshots/screenshot_5.png b/automatic_project_task_timer/static/description/assets/screenshots/screenshot_5.png new file mode 100644 index 000000000..6eec020ca Binary files /dev/null and b/automatic_project_task_timer/static/description/assets/screenshots/screenshot_5.png differ diff --git a/automatic_project_task_timer/static/description/assets/screenshots/screenshot_6.png b/automatic_project_task_timer/static/description/assets/screenshots/screenshot_6.png new file mode 100644 index 000000000..b112fce0d Binary files /dev/null and b/automatic_project_task_timer/static/description/assets/screenshots/screenshot_6.png differ diff --git a/automatic_project_task_timer/static/description/assets/screenshots/screenshot_7.png b/automatic_project_task_timer/static/description/assets/screenshots/screenshot_7.png new file mode 100644 index 000000000..2191f143b Binary files /dev/null and b/automatic_project_task_timer/static/description/assets/screenshots/screenshot_7.png differ diff --git a/automatic_project_task_timer/static/description/assets/screenshots/screenshot_8.png b/automatic_project_task_timer/static/description/assets/screenshots/screenshot_8.png new file mode 100644 index 000000000..73b7b3b29 Binary files /dev/null and b/automatic_project_task_timer/static/description/assets/screenshots/screenshot_8.png differ diff --git a/automatic_project_task_timer/static/description/assets/screenshots/screenshot_9.png b/automatic_project_task_timer/static/description/assets/screenshots/screenshot_9.png new file mode 100644 index 000000000..31a80edc4 Binary files /dev/null and b/automatic_project_task_timer/static/description/assets/screenshots/screenshot_9.png differ diff --git a/automatic_project_task_timer/static/description/banner.png b/automatic_project_task_timer/static/description/banner.png new file mode 100644 index 000000000..64bf90957 Binary files /dev/null and b/automatic_project_task_timer/static/description/banner.png differ diff --git a/automatic_project_task_timer/static/description/icon.png b/automatic_project_task_timer/static/description/icon.png new file mode 100644 index 000000000..def49456b Binary files /dev/null and b/automatic_project_task_timer/static/description/icon.png differ diff --git a/automatic_project_task_timer/static/description/index.html b/automatic_project_task_timer/static/description/index.html new file mode 100644 index 000000000..9797cac5c --- /dev/null +++ b/automatic_project_task_timer/static/description/index.html @@ -0,0 +1,590 @@ +
+ +
+ +
+
+ Community +
+
+
+ +
+
+
+ +

+ Automatic Project Task Timer +

+

Automatic Running Timer for Project Tasks at the Configured Stages.

+ + +
+
+
+
+ + +
+
+ +
+

Explore This + Module

+
+ + + + +
+
+ +
+

Overview +

+
+
+
+ This module will give the feature of running a timer when a task comes in 'In Progress' stage and stops when it is moved to any other stage +
+
+ + + +
+
+ +
+

Features +

+
+
+
+
+ + Control the availability of features from the configuration settings. +
+
+ + The timer will be run if it is activated in the configuration settings. +
+
+ + Automatically starts to count from the beginning whether the task is moved to In progress stage by changing the stage by clicking or dragging. +
+ +
+ + Starting time and ending time will be recorded in the timesheet. +
+
+
+
+ + Available in Odoo 16.0 + Community. +
+
+
+ + + +
+
+ +
+

Screenshots +

+
+
+
+
+

+ Set the User Group for Project as Administrator to see the + Configuration menu. +

+

+ Go to Settings -> Users & Companies -> Users -> Project : + Administrator

+ +
+ +
+

+ Configure your custom stage of each project to make the automatic timer on that particular stage only from the Timer Configuration menu. +

+

+ Go to Project -> Configuration -> Timer Configuration

+ +
+ +
+

+ Timer Configuration +

+

+ Set up your Projects and related Stages.

+ +
+ +
+

Activate the feature from configuration setting. +

+

Go to Projects -> Configuration + -> + Settings. + Activate the Task Timer boolean to activate the run timer.

+ +
+ +
+

Create a new task. +

Add a task under the timer configured stage.

+ +
+ +
+

The timer is assigned to zero when a task is in other stage. +

+

A real duration field will be seen on the timesheet page. In the other stages the timer won't be run, and also timesheet not be recorded.

+ +
+ +
+

The timer starts to run when a task comes in Configured stage. +

+

The timer starts running and timesheet also created with the starting time.

+ +
+ +
+

The timer will stop when a task comes to the other stage. +

+

The timer stops running when the task moves to any other stage and the timesheet will update with the ending time also we can see the time when the timer stops.

+ +
+ +
+

The timer will also be activated when a task is dragged to the Configured stage.

+ +
+ +
+
+ + + +
+
+ +
+

Related + Products +

+
+
+
+ +
+
+ + + + +
+
+ +
+

Our Services +

+
+ +
+
+
+
+ +
+
+ Odoo + Customization
+
+ +
+
+ +
+
+ Odoo + Implementation
+
+ +
+
+ +
+
+ Odoo + Support
+
+ + +
+
+ +
+
+ Hire + Odoo + Developer
+
+ +
+
+ +
+
+ Odoo + Integration
+
+ +
+
+ +
+
+ Odoo + Migration
+
+ + +
+
+ +
+
+ Odoo + Consultancy
+
+ +
+
+ +
+
+ Odoo + Implementation
+
+ +
+
+ +
+
+ Odoo + Licensing Consultancy
+
+
+ +
+ + + + + +
+
+ +
+

Our + Industries +

+
+ +
+
+
+
+ +
+ Trading +
+

+ Easily procure + and + sell your products

+
+
+ +
+
+ +
+ POS +
+

+ Easy + configuration + and convivial experience

+
+
+ +
+
+ +
+ Education +
+

+ A platform for + educational management

+
+
+ +
+
+ +
+ Manufacturing +
+

+ Plan, track and + schedule your operations

+
+
+ +
+
+ +
+ E-commerce & Website +
+

+ Mobile + friendly, + awe-inspiring product pages

+
+
+ +
+
+ +
+ Service Management +
+

+ Keep track of + services and invoice

+
+
+ +
+
+ +
+ Restaurant +
+

+ Run your bar or + restaurant methodically

+
+
+ +
+
+ +
+ Hotel Management +
+

+ An + all-inclusive + hotel management application

+
+
+
+
+ + + + +
+
+ +
+

Support +

+
+
+
+
+
+
+ +
+
+

Need Help?

+

Got questions or need help? Get in touch.

+ +

+ odoo@cybrosys.com

+
+
+
+
+
+
+
+ +
+
+

WhatsApp

+

Say hi to us on WhatsApp!

+ +

+91 86068 + 27707

+
+
+
+
+
+
+
+ +
+
+
+ \ No newline at end of file diff --git a/automatic_project_task_timer/static/src/js/form_open.js b/automatic_project_task_timer/static/src/js/form_open.js new file mode 100644 index 000000000..f3af6eaef --- /dev/null +++ b/automatic_project_task_timer/static/src/js/form_open.js @@ -0,0 +1,15 @@ +/** @odoo-module **/ +import { patch } from "@web/core/utils/patch"; +import { FormRenderer } from '@web/views/form/form_renderer'; +import { useService } from "@web/core/utils/hooks"; +patch(FormRenderer.prototype, "warning", { + // Patched the form render to show the notification for already existing task. + setup(){ + this._super.apply(); + if(this.props.record.data.is_status_stage) + { + this.notification = useService("notification"); + this.notification.add("Timer will not works properly for already existing task, To make that, Change the stage once again after activating task timer from configuration.", {title: "Warning", type: "danger"}); + } + }, +}); diff --git a/automatic_project_task_timer/static/src/js/task_timer.js b/automatic_project_task_timer/static/src/js/task_timer.js new file mode 100644 index 000000000..942665290 --- /dev/null +++ b/automatic_project_task_timer/static/src/js/task_timer.js @@ -0,0 +1,87 @@ +/** @odoo-module **/ +import { registry } from "@web/core/registry"; +import { useService } from "@web/core/utils/hooks"; +import { parseFloatTime } from "@web/views/fields/parsers"; +import { useInputField } from "@web/views/fields/input_field_hook"; + +const { Component, useState, onWillUpdateProps, onWillStart, onWillDestroy } = owl; +// Function for converting the time and return the value in each seconds. +function formatMinutes(value) { + if (value === false) { + return ""; + } + const isNegative = value < 0; + if (isNegative) { + value = Math.abs(value); + } + let min = Math.floor(value); + let sec = Math.floor((value % 1) * 60); + sec = `${sec}`.padStart(2, "0"); + min = `${min}`.padStart(2, "0"); + return `${isNegative ? "-" : ""}${min}:${sec}`; +} + +export class TaskTimer extends Component { +//Extend component to add TaskTimer + setup() { + this.orm = useService('orm'); + this.state = useState({ + // Duration is expected to be given in minutes + duration: + this.props.value !== undefined ? this.props.value : this.props.record.data.duration, + }); + useInputField({ + getValue: () => this.durationFormatted, + refName: "numpadDecimal", + parse: (v) => parseFloatTime(v), + }); + + this.ongoing = + this.props.ongoing !== undefined + ? this.props.ongoing + : this.props.record.data.is_user_working; + + onWillStart(async () => { + //Check the status while form rendering. + if(this.props.ongoing === undefined && !this.props.record.model.useSampleModel && this.props.record.data.stage_id[0] == this.props.record.data.check_stage) { + const additionalDuration = await this.orm.call('project.task', 'get_working_duration', [this.props.record.resId]); + this.state.duration += additionalDuration; + } + if (this.ongoing) { + this._runTimer(); + } + }); + onWillUpdateProps((nextProps) => { + const newOngoing = + "ongoing" in nextProps + ? nextProps.ongoing + : "record" in nextProps && nextProps.record.data.is_user_working; + const rerun = !this.ongoing && newOngoing; + this.ongoing = newOngoing; + if (rerun) { + this.state.duration = nextProps.value; + this._runTimer(); + } + }); + onWillDestroy(() => clearTimeout(this.timer)); + } + //Getting the formatted time duration + get durationFormatted() { + return formatMinutes(this.state.duration); + } + //Function for setting the interval and call in each 1000ms + _runTimer() { + this.timer = setTimeout(() => { + if (this.ongoing) { + this.state.duration += 1 / 60; + this._runTimer(); + } + }, 1000); + } +} + +TaskTimer.supportedTypes = ["float"]; +TaskTimer.template = "TaskTimerTemplate"; +//Adding the widget to the field registry +registry.category("fields").add("task_timer", TaskTimer); +registry.category("formatters").add("task_timer", formatMinutes); diff --git a/automatic_project_task_timer/static/src/xml/task_timer_templates.xml b/automatic_project_task_timer/static/src/xml/task_timer_templates.xml new file mode 100644 index 000000000..6a7d39f82 --- /dev/null +++ b/automatic_project_task_timer/static/src/xml/task_timer_templates.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/automatic_project_task_timer/views/project_task_views.xml b/automatic_project_task_timer/views/project_task_views.xml new file mode 100644 index 000000000..b511aa0ba --- /dev/null +++ b/automatic_project_task_timer/views/project_task_views.xml @@ -0,0 +1,45 @@ + + + + + project.task.view.form.inherit.automatic.project.task.timer + project.task + + + + + +
+ +
+
+ + + + + + + + +
+
+
diff --git a/automatic_project_task_timer/views/res_config_settings_views.xml b/automatic_project_task_timer/views/res_config_settings_views.xml new file mode 100644 index 000000000..54cc54216 --- /dev/null +++ b/automatic_project_task_timer/views/res_config_settings_views.xml @@ -0,0 +1,28 @@ + + + + + res.config.settings.view.form.inherit.automatic.project.task.timer + res.config.settings + + + +
+
+
+ +
+
+
+
+
+
+
+
+
diff --git a/automatic_project_task_timer/views/timer_configuration_views.xml b/automatic_project_task_timer/views/timer_configuration_views.xml new file mode 100644 index 000000000..7e01dec04 --- /dev/null +++ b/automatic_project_task_timer/views/timer_configuration_views.xml @@ -0,0 +1,26 @@ + + + + + timer.configuration.view.tree + timer.configuration + + + + + + + + + + + Timer Configuration + timer.configuration + tree + + + + +