[FIX] hr_timesheet: problem desynchronization time between server and client
TaskID: 2088586 When we launch the timer, if the clock of the client isn't correctly synchronize with internet, we can't correctly display the timer, because the clock of the server can be in advance. The solution is to call the server to have this time and use the timer only with the time of the server.
This commit is contained in:
committed by
Yannick Tivisse
parent
15e41f59c7
commit
2d3a44e6bd
@@ -65,3 +65,12 @@ class TimerMixin(models.AbstractModel):
|
||||
def action_timer_resume(self) -> None:
|
||||
new_start = self.timer_start + (fields.Datetime.now() - self.timer_pause)
|
||||
self.write({'timer_start': new_start, 'timer_pause': False})
|
||||
|
||||
def get_server_time(self):
|
||||
""" Get the time of the server
|
||||
|
||||
The problem with the timer, it's the time can be different between server side and client side.
|
||||
We need to have the time of the server and don't use the local time. Then, we have a timer beginning at 0:00
|
||||
and not 23:59 or something else.
|
||||
"""
|
||||
return fields.Datetime.now()
|
||||
|
||||
@@ -12,6 +12,10 @@ odoo.define('hr_timesheet.Timer', function (require) {
|
||||
this.seconds = seconds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert float to time
|
||||
* @param {number} float
|
||||
*/
|
||||
static convertFloatToTime(float) {
|
||||
if (float === 0) {
|
||||
return new Timer(0, 0, 0);
|
||||
@@ -24,6 +28,25 @@ odoo.define('hr_timesheet.Timer', function (require) {
|
||||
return new Timer(hours, Math.round(minutes), 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create timer
|
||||
* @param {number} unit_amount
|
||||
* @param {String} timer_start
|
||||
* @param {String} serverTime
|
||||
*/
|
||||
static createTimer(unit_amount, timer_start, serverTime) {
|
||||
const timer = this.convertFloatToTime(unit_amount);
|
||||
|
||||
timer.addTime(
|
||||
moment.utc(
|
||||
moment.utc(serverTime)
|
||||
.diff(moment.utc(timer_start))
|
||||
).format("HH:mm:ss")
|
||||
);
|
||||
|
||||
return timer;
|
||||
}
|
||||
|
||||
addHours(hours) {
|
||||
this.hours += hours;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ odoo.define('hr_timesheet.timer', function (require) {
|
||||
|
||||
var fieldRegistry = require('web.field_registry');
|
||||
var AbstractField = require('web.AbstractField');
|
||||
var Timer = require('hr_timesheet.Timer');
|
||||
|
||||
var TimerFieldWidget = AbstractField.extend({
|
||||
|
||||
@@ -13,48 +14,47 @@ var TimerFieldWidget = AbstractField.extend({
|
||||
isSet: function () {
|
||||
return true;
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_getDuration: function (dateStart, datePause) {
|
||||
if (datePause && dateStart) {
|
||||
return moment(datePause).diff(moment(dateStart));
|
||||
}
|
||||
if (dateStart) {
|
||||
return moment().diff(moment(dateStart));
|
||||
}
|
||||
else return 0;
|
||||
},
|
||||
/**
|
||||
* @override
|
||||
* @private
|
||||
*/
|
||||
_render: function () {
|
||||
this._startTimeCounter();
|
||||
|
||||
},
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
destroy: function () {
|
||||
this._super.apply(this, arguments);
|
||||
clearTimeout(this.timer);
|
||||
clearInterval(this.timer);
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_startTimeCounter: function () {
|
||||
var self = this;
|
||||
clearTimeout(this.timer);
|
||||
if (self.record.data.timer_start) {
|
||||
this.timer = setTimeout(function () {
|
||||
self._startTimeCounter();
|
||||
_startTimeCounter: async function () {
|
||||
if (this.record.data.timer_start) {
|
||||
const serverTime = this.record.data.timer_pause || await this._getServerTime();
|
||||
this.time = Timer.createTimer(0, this.record.data.timer_start, serverTime);
|
||||
this.$el.text(this.time.toString());
|
||||
this.timer = setInterval(() => {
|
||||
if (this.record.data.timer_pause) {
|
||||
clearInterval(this.timer);
|
||||
} else {
|
||||
this.time.addSecond();
|
||||
this.$el.text(this.time.toString());
|
||||
}
|
||||
}, 1000);
|
||||
this.$el.text(moment.utc(self._getDuration(self.record.data.timer_start, self.record.data.timer_pause)).format("HH:mm:ss"));
|
||||
} else if (!self.record.data.timer_pause){
|
||||
clearTimeout(this.timer);
|
||||
} else if (!this.record.data.timer_pause){
|
||||
clearInterval(this.timer);
|
||||
}
|
||||
},
|
||||
_getServerTime: function () {
|
||||
return this._rpc({
|
||||
model: 'account.analytic.line',
|
||||
method: 'get_server_time',
|
||||
args: [false]
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
fieldRegistry.add('timesheet_timer', TimerFieldWidget);
|
||||
|
||||
@@ -86,14 +86,19 @@ const FieldTimesheetTime = basicFields.FieldFloatTime.extend({
|
||||
this.parseOptions.factor = session.timesheet_uom_factor;
|
||||
}
|
||||
},
|
||||
_render: function () {
|
||||
_render: async function () {
|
||||
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.time = this._createTimer(this.recordData.unit_amount, this.recordData.timer_start);
|
||||
const time = await this._rpc({
|
||||
model: this.model,
|
||||
method: 'get_server_time',
|
||||
args: [false]
|
||||
});
|
||||
this.time = Timer.createTimer(this.recordData.unit_amount, this.recordData.timer_start, time);
|
||||
return this._startTimeCounter();
|
||||
} else if (this.mode === "edit") {
|
||||
return this._renderEdit();
|
||||
@@ -108,18 +113,6 @@ const FieldTimesheetTime = basicFields.FieldFloatTime.extend({
|
||||
this._super.apply(this, arguments);
|
||||
clearTimeout(this.timer);
|
||||
},
|
||||
_createTimer: function (unit_amount, timer_start) {
|
||||
const timer = Timer.convertFloatToTime(unit_amount);
|
||||
|
||||
timer.addTime(
|
||||
moment.utc(
|
||||
moment()
|
||||
.diff(moment(timer_start))
|
||||
).format("HH:mm:ss")
|
||||
);
|
||||
|
||||
return timer;
|
||||
},
|
||||
_startTimeCounter: function () {
|
||||
if (this.time) {
|
||||
this.timer = setInterval(() => {
|
||||
|
||||
Reference in New Issue
Block a user