refactor(jobs): address code review feedback on fp.job.step.timelog (Task 1.7)

- I1: Add supervisor ACL row on fp.job.step.timelog. The other
  job-related models all have a 3-tier (operator/supervisor/
  manager) pattern; timelog had been operator+manager only with
  no comment explaining why. Adding the supervisor row for
  consistency — supervisors can write timelogs the same as
  operators.
- I2: Capture fields.Datetime.now() once in button_start and
  reuse for both the step's first-start audit timestamp and the
  new timelog's date_started. Mirrors button_finish's pattern.
  Eliminates microsecond drift between two related timestamps.
- M6: Update stale comment in fp_job_step.py that said
  'duration_actual will be sum of timelog rows once Task 1.7
  lands' — Task 1.7 has landed; replace with current behaviour.

Manifest 19.0.8.6.0 → 19.0.8.6.1.

Part of: native job model migration (spec 2026-04-25)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
gsinghpal
2026-04-24 22:34:10 -04:00
parent 28892f56b5
commit 54068b3d18
3 changed files with 11 additions and 6 deletions

View File

@@ -136,8 +136,9 @@ class FpJobStep(models.Model):
# ------------------------------------------------------------------
# Cost rollup (Task 1.6)
# cost_per_hour comes from fp.work.centre (Task 1.2 added it there).
# cost_total recomputes when duration_actual or rate changes
# duration_actual will be sum of timelog rows once Task 1.7 lands.
# cost_total recomputes when duration_actual or rate changes.
# duration_actual is set by button_finish as the sum of timelog
# row durations (see fp.job.step.timelog).
# ------------------------------------------------------------------
cost_per_hour = fields.Monetary(
related='work_centre_id.cost_per_hour',
@@ -197,16 +198,19 @@ class FpJobStep(models.Model):
raise UserError(_(
"Step '%s' is in state '%s' — only ready/paused steps can start."
) % (step.name, step.state))
now = fields.Datetime.now()
step.state = 'in_progress'
# First-start audit (mirrors button_finish first-finish guard)
if not step.date_started:
step.date_started = fields.Datetime.now()
step.date_started = now
step.started_by_user_id = self.env.user
# Open a fresh timelog row for this start interval
# Open a fresh timelog row for this start interval — uses the
# same `now` as the first-start stamp so the step and its
# first log share a single instant.
self.env['fp.job.step.timelog'].create({
'step_id': step.id,
'user_id': self.env.user.id,
'date_started': fields.Datetime.now(),
'date_started': now,
})
return True