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 @@