Files
paliad/internal/models
mAi 705e1a2e79 feat(approvals): t-paliad-216 SuggestChanges service method
ApprovalService.SuggestChanges is the fourth approval action — in one
transaction:

  1. Validates the OLD pending row (caller satisfies canApprove,
     lifecycle in update/complete only, counter differs from old.payload
     OR note is non-empty).
  2. Closes the OLD row as 'changes_requested' with decision_note +
     counter_payload + decided_by + decided_at + decision_kind.
  3. Reverts the entity from old.pre_image (reuses applyRevert — same
     code path Reject runs).
  4. Runs the deadlock check for the NEW row (excluding the suggesting
     caller; original requester is no longer excluded).
  5. Re-applies the counter_payload to the entity row (via
     applyEntityUpdate, mirroring the write-then-approve write).
  6. INSERTs a NEW pending approval_requests row authored by the caller
     with previous_request_id pointing back at the OLD row.
  7. Marks the entity pending + pending_request_id → new row.
  8. Emits two project_events: *_approval_changes_suggested + a fresh
     *_approval_requested for the new row.

4-Augen still holds: the suggesting caller is the new row's
requested_by, so self-approval on the new row is blocked by the standard
3-layer guard. The ORIGINAL requester is no longer the requested_by of
the new row — if their profession satisfies the required_role they can
now approve the counter themselves.

Adds:
  - const RequestStatusChangesRequested = "changes_requested"
  - var  ErrSuggestionRequiresChange   = "suggestion requires counter diff or note"
  - var  ErrSuggestionLifecycleInvalid = "suggest is only valid for update/complete"
  - models.ApprovalRequest.CounterPayload + PreviousRequestID
  - Per-row read paths (getRequestForUpdate, approvalRequestViewColumns)
    populate the new columns.
2026-05-20 09:50:07 +02:00
..