646 — Skip a billed record in a bulk edit but apply it to the rest¶
Description¶
Partial-update path. A fully invoiced (billed) time record is locked for edits — the backend checkModificationsPermissions throws TIME_RECORD_BILLED for that record. The bulk patch is not transactional: the billed record is skipped while the rest of the selection updates, returning a partial result (success toast + "N updated, M could not be updated" + the per-record reason).
Preconditions¶
- Signed in to a freshly seeded test organization.
- Three time records seeded via the GraphQL API, each on a different client/project/task.
- One of the records is fully billed via the API (billing-report settings set to skip-draft, then a billing report is created from it so it gets an issued invoice item).
- Time Records page open in the Reports view.
Steps¶
- Tick the selection checkbox on all three rows. Expected: the floating bar shows "3 selected".
- Open the bulk-edit modal and set Project → Replace with record #2's project (a project that differs from the billed record's own).
- Click Save. Expected: a success toast, an info toast "2 time record(s) updated, 1 could not be updated.", and an error toast "This time record cannot be edited because it has already been invoiced."; the modal stays open.
- Cancel the modal.
- Inspect the rows by record id. Expected: the billed record keeps its own original project; the other two now carry the replacement project.
Related¶
- Spec:
playwright/tests/integration/timerecord.spec.ts(describe "Timerecord - Bulk edit") - Page object:
assertTimeRecordProjectById,bulkReplaceProject,clickBulkSaveButton,clickBulkCancel(timerecord.page.ts) - Backend guard:
TimeRecordService.checkModificationsPermissions→TIME_RECORD_BILLED