From c6a4f572a51da7f2d8b23836ff96752cadda9250 Mon Sep 17 00:00:00 2001 From: AjmalCybro Date: Tue, 20 Jun 2023 12:18:52 +0530 Subject: [PATCH] Jun 20 : [FIX] Bug Fixed 'project_task_timer' --- project_task_timer/__manifest__.py | 3 +- .../models/project_task_timer.py | 40 ++--- project_task_timer/static/src/js/timer.js | 146 +++++++++--------- project_task_timer/static/src/xml/timer.xml | 7 + .../views/project_task_timer_view.xml | 3 +- 5 files changed, 107 insertions(+), 92 deletions(-) create mode 100644 project_task_timer/static/src/xml/timer.xml diff --git a/project_task_timer/__manifest__.py b/project_task_timer/__manifest__.py index f06d94036..506f68fc2 100644 --- a/project_task_timer/__manifest__.py +++ b/project_task_timer/__manifest__.py @@ -26,13 +26,14 @@ 'author': 'Cybrosys Techno Solutions', 'company': 'Cybrosys Techno Solutions', 'website': "http://www.cybrosys.com", - 'depends': ['base', 'project', 'hr_timesheet','web'], + 'depends': ['base', 'project', 'hr_timesheet'], 'data': [ 'views/project_task_timer_view.xml', ], 'assets': { 'web.assets_backend': [ 'project_task_timer/static/src/js/timer.js', + 'project_task_timer/static/src/xml/timer.xml', ]}, 'images': ['static/description/banner.png'], 'license': 'AGPL-3', diff --git a/project_task_timer/models/project_task_timer.py b/project_task_timer/models/project_task_timer.py index d44c25048..871ad13b5 100644 --- a/project_task_timer/models/project_task_timer.py +++ b/project_task_timer/models/project_task_timer.py @@ -26,8 +26,7 @@ class ProjectTaskTimeSheet(models.Model): date_start = fields.Datetime(string='Start Date') date_end = fields.Datetime(string='End Date', readonly=1) - timer_duration = fields.Float(invisible=1, - string='Time Duration (Minutes)=') + timer_duration = fields.Float(invisible=1, string='Time Duration (Minutes)=') class ProjectTaskTimer(models.Model): @@ -41,15 +40,12 @@ class ProjectTaskTimer(models.Model): 'Real Duration', compute='_compute_duration', store=True) def _compute_duration(self): - """Compute Duration""" self 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)): + 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 @@ -73,15 +69,23 @@ class ProjectTaskTimer(models.Model): time_line_obj = self.env['account.analytic.line'] domain = [('task_id', 'in', self.ids), ('date_end', '=', False)] for time_line in time_line_obj.search(domain): - time_line.write({'date_end': fields.Datetime.now()}) - if time_line.date_start and time_line.date_end: - diff = fields.Datetime.from_string( - time_line.date_end) - fields.Datetime.from_string( - time_line.date_start).replace(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 + if time_line.date_start: + time_line.write({'date_end': fields.Datetime.now()}) + diff = fields.Datetime.from_string(time_line.date_end) - fields.Datetime.from_string(time_line.date_start) + time_line.timer_duration = round(diff.total_seconds() / 60.0, 2) + time_line.unit_amount = round(diff.total_seconds() / (60.0 * 60.0), 2) + + 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/project_task_timer/static/src/js/timer.js b/project_task_timer/static/src/js/timer.js index 035e65ee9..19d4675a8 100644 --- a/project_task_timer/static/src/js/timer.js +++ b/project_task_timer/static/src/js/timer.js @@ -1,82 +1,86 @@ -odoo.define('project_task_timer.timer', function (require) { -"use strict"; -var AbstractField = require('web.AbstractField'); -var core = require('web.core'); -var field_registry = require('web.field_registry'); -var time = require('web.time'); -var FieldManagerMixin = require('web.FieldManagerMixin'); +/** @odoo-module **/ -var _t = core._t; +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"; -// $(document).on('click','#timer', function(){ -// if ($(this).hasClass('btn-secondary')) -// { $(this).removeClass('btn-secondary'); -// $(this).addClass('btn-primary'); -// } -// }); +const { Component, useState, onWillUpdateProps, onWillStart, onWillDestroy } = owl; -/** - * Custom field type for displaying a time counter based on data from the account.analytic.line model. - * Inherits from the AbstractField class. - */ +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}`; +} -var TimeCounter = AbstractField.extend({ +export class TaskTimer extends Component { + 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), + }); - willStart: function () { - var self = this; - var def = this._rpc({ - model: 'account.analytic.line', - method: 'search_read', - domain: [['task_id', '=', this.res_id], - ['user_id', '=', self.record.context['uid']]], - }).then(function (result) { - if (self.mode === 'readonly') { - var currentDate = new Date(); - self.duration = 0; - _.each(result, function (data) { - self.duration += data.date_end ? - self._getDateDifference(data.date_start, data.date_end): - self._getDateDifference(time.auto_str_to_date(data.date_start), currentDate); - }); + this.ongoing = + this.props.ongoing !== undefined + ? this.props.ongoing + : this.props.record.data.is_user_working; + + onWillStart(async () => { + if(this.props.ongoing === undefined && !this.props.record.model.useSampleModel && this.props.record.data.task_timer) { + const additionalDuration = await this.orm.call('project.task', 'get_working_duration', [this.props.record.resId]); + this.state.duration += additionalDuration; + } + if (this.ongoing) { + this._runTimer(); } }); - return $.when(this._super.apply(this, arguments), def); - }, - destroy: function () { - this._super.apply(this, arguments); - clearTimeout(this.timer); - }, - isSet: function () { - return true; - }, - _getDateDifference: function (dateStart, dateEnd) { - return moment(dateEnd).diff(moment(dateStart)); - }, + 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)); + } - _render: function () { - this._startTimeCounter(); - }, + get durationFormatted() { + return formatMinutes(this.state.duration); + } - /** - * Starts a timer to update the field every second if the user is working. - * Increments the duration by one second each time the timer runs. - * Updates the field with the new duration in HH:mm:ss format. - */ - _startTimeCounter: function () { - var self = this; - clearTimeout(this.timer); - if (this.record.data.is_user_working) { - this.timer = setTimeout(function () { - self.duration += 1000; - self._startTimeCounter(); - }, 1000); - } else { - clearTimeout(this.timer); - } - this.$el.html($('' + moment.utc(this.duration).format("HH:mm:ss") + '')); - }, -}); -field_registry.add('timesheet_uoms', TimeCounter); -}); + _runTimer() { + this.timer = setTimeout(() => { + if (this.ongoing) { + this.state.duration += 1 / 60; + this._runTimer(); + } + }, 1000); + } +} +TaskTimer.supportedTypes = ["float"]; +TaskTimer.template = "TaskTimerTemplate"; +registry.category("fields").add("task_timer", TaskTimer); +registry.category("formatters").add("task_timer", formatMinutes); \ No newline at end of file diff --git a/project_task_timer/static/src/xml/timer.xml b/project_task_timer/static/src/xml/timer.xml new file mode 100644 index 000000000..469fe56b8 --- /dev/null +++ b/project_task_timer/static/src/xml/timer.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/project_task_timer/views/project_task_timer_view.xml b/project_task_timer/views/project_task_timer_view.xml index a5ce4692e..bf023cdfa 100644 --- a/project_task_timer/views/project_task_timer_view.xml +++ b/project_task_timer/views/project_task_timer_view.xml @@ -26,7 +26,6 @@ project.task - @@ -37,7 +36,7 @@