add hr_timesheet_sheet_no_review, hr_timesheet_sheet_holidays, hr_timesheet_sheet_delete_cascade

This commit is contained in:
Luis 2026-09-22 10:58:36 +02:00
parent b07082f70d
commit 8b0d0bb6cc
53 changed files with 3953 additions and 0 deletions

View file

@ -0,0 +1,39 @@
Nothing to configure. Once installed, a timesheet sheet covering a week with validated
time off can be opened, recomputed, created and saved by the employee, and the time off
lines are shown in the *Summary* matrix and in the *Details* tab with their project, task
and hours, adding up to the total of the sheet.
Time off hours are still read-only from the sheet. Trying to change them raises an error
pointing the user to the *Time Off* application, naming the sheet and the day concerned.
To change them, cancel or modify the time off request in the *Time Off* application.
A time off line may end up detached from every sheet (``sheet_id = False``) when the
period or the employee of a sheet is changed in the form. Nothing is lost: the line, the
time off request and the balance are untouched, and the line is linked again as soon as a
sheet covering that day is recomputed.
For developers, the module publishes two hooks on ``account.analytic.line``:
* ``_sheet_neutral_fields()`` returns the set of fields whose write is considered a pure
sheet link operation (``{"sheet_id"}`` by default). Widening it requires reviewing the
protection of time off hours.
* ``_detach_leave_lines_on_unlink()`` returns whether an ``unlink()`` of time off lines
must detach them instead of deleting them.
Both behaviours are driven by the internal context flags ``sheet_link_write`` and
``sheet_recompute``. The context of an RPC call is controlled by the client, so those
flags do **not** carry a boolean: they carry a module-level sentinel object, obtained
from ``_sheet_link_write_token()`` / ``_sheet_recompute_token()`` and compared by
identity. A JSON deserializer cannot produce such an object, so the flags cannot be
forged from outside the process. Never replace a token with a value that survives
serialization, and never set either flag from a view, an action or a user context.
Three tests are mandatory regression tests for any change to those flags:
* ``test_no_context_leak_after_sheet_operation`` — the flag does not escape: right after
a sheet operation, in the same transaction, a direct write or unlink on a time off line
is blocked again.
* ``test_forged_sheet_link_write_flag_does_not_unlock_write`` and
``test_forged_sheet_recompute_flag_does_not_unlock_unlink`` — the flag cannot be
injected: a boolean sent through ``odoo.api.call_kw``, the entry point the web client
uses, unlocks nothing.