[FIX] mrp: remove microseconds on timesheets

**Sum of timesheets time different than what the timer displays**

Steps to reproduce:

 1. Start a workorder timesheet, then stop it
 2. Repeat the process multiple times.

Current behavior:

The error is based on a microsecond precision so you could need
to try multiple times before reaching the problem.

 - The time displayed on the timer widget does not display the same as
the sum in the timesheet list.
 - The difference between the start date and end date of a timesheet
is not always equal to its duration.

Expected behavior:

 - The sum of duration should be the same as the one displayed on the
timer widget.
 - The difference between the start and end date of a timesheet
should be equal to it's duration.

The computation of the duration of a timesheet will take microseconds
into account. It's not useful in the timsheets to save microseconds
as the precision is too high and as the user cannot change it manually
anyway.

Removing this precision (i.e. setting microseconds to 0) solve this
problem as it does not trigger rounding errors in a single timesheet
and thus in the total computation of duration of a workorder.

Also, there was a precision rounding error on the timer widget.
Time is saved as minutes in db, and displayed as seconds.
So 2s is 1/30 of min => 0,0333... min.
As multiplying this by 60 will return 1,99999 and as the timer was flooring the result,
there was some difference between the time recorded and the value displayed in the
widget.

enterprise : https://github.com/odoo/enterprise/pull/41727
opw-3241156

closes odoo/odoo#130618

X-original-commit: 0172395fa60c94150609bbbfe174d5eee44525fe
Related: odoo/enterprise#45109
Signed-off-by: Tiffany Chang <tic@odoo.com>
This commit is contained in:
Martin Maes
2023-08-03 10:43:49 +02:00
parent 2b095b8b1e
commit 562114c532
3 changed files with 6 additions and 6 deletions
+2 -2
View File
@@ -412,7 +412,7 @@ class MrpWorkcenterProductivity(models.Model):
def _compute_duration(self):
for blocktime in self:
if blocktime.date_start and blocktime.date_end:
blocktime.duration = blocktime.loss_id._convert_to_duration(blocktime.date_start, blocktime.date_end, blocktime.workcenter_id)
blocktime.duration = blocktime.loss_id._convert_to_duration(blocktime.date_start.replace(microsecond=0), blocktime.date_end.replace(microsecond=0), blocktime.workcenter_id)
else:
blocktime.duration = 0.0
@@ -460,7 +460,7 @@ class MrpWorkcenterProductivity(models.Model):
underperformance_timers = self.env['mrp.workcenter.productivity']
for timer in self:
wo = timer.workorder_id
timer.write({'date_end': datetime.now()})
timer.write({'date_end': fields.Datetime.now()})
if wo.duration > wo.duration_expected:
productive_date_end = timer.date_end - relativedelta.relativedelta(minutes=wo.duration - wo.duration_expected)
if productive_date_end <= timer.date_start:
+3 -3
View File
@@ -636,7 +636,7 @@ class MrpWorkorder(models.Model):
return self.with_context(bypass_duration_calculation=True).write(vals)
def button_finish(self):
date_finished = datetime.now()
date_finished = fields.Datetime.now()
for workorder in self:
if workorder.state in ('done', 'cancel'):
continue
@@ -813,8 +813,8 @@ class MrpWorkorder(models.Model):
'workcenter_id': self.workcenter_id.id,
'description': _('Time Tracking: %(user)s', user=self.env.user.name),
'loss_id': loss_id[0].id,
'date_start': date_start,
'date_end': date_end,
'date_start': date_start.replace(microsecond=0),
'date_end': date_end.replace(microsecond=0) if date_end else date_end,
'user_id': self.env.user.id, # FIXME sle: can be inconsistent with company_id
'company_id': self.company_id.id,
}
+1 -1
View File
@@ -17,7 +17,7 @@ function formatMinutes(value) {
value = Math.abs(value);
}
let min = Math.floor(value);
let sec = Math.floor((value % 1) * 60);
let sec = Math.round((value % 1) * 60);
sec = `${sec}`.padStart(2, "0");
min = `${min}`.padStart(2, "0");
return `${isNegative ? "-" : ""}${min}:${sec}`;