# GetApprovalDecisionHistory

## Overview

GetApprovalDecisionHistory returns every `ApprovalDecision` row for a given `approvalRequestId`, chronologically ordered by `decidedAt`. Because the approval module records every actor-driven transition (APPROVE / REJECT / SEND_BACK / DELEGATE / WITHDRAW / CANCEL / RESUBMIT) as an immutable `ApprovalDecision` row, this single query is the canonical "who did what, when" timeline for a request — there is no separate audit-log join required, and the approval module does not depend on the `audit` module. Step-level decisions appear with both `approvalRequestId` and `approvalStepId` set; request-level decisions appear with `approvalStepId` null.

## Business Rules

- Accepts `approvalRequestId` as a required input
- Returns every `ApprovalDecision` row for the request, regardless of decision type or step
- Returns rows ordered by `decidedAt ASC` (oldest first) so the timeline reads left-to-right
- Returns an empty array when the request has no decisions yet (e.g., a freshly-created `PENDING` request that has not yet received a step decision) — not an error
- The request must exist; a non-existent `approvalRequestId` returns an error
- Includes WITHDRAW, CANCEL, and RESUBMIT rows (which have `approvalStepId = null`) in the same timeline as step-level rows
- FK targets (`decidedByUserId`, `delegatedToUserId`) reference `User` rows that are never hard-deleted, so actor identity is always resolvable

## Process Flow

```mermaid
flowchart TD
    A[Receive approvalRequestId] --> B{Request exists?}
    B -->|No| C[Return error: REQUEST_NOT_FOUND]
    B -->|Yes| D[SELECT ApprovalDecision<br/>where approvalRequestId = input]
    D --> E[ORDER BY decidedAt ASC]
    E --> F[Return rows]
```

## External Dependencies

- None

## Error Scenarios

- **REQUEST_NOT_FOUND**: Specified `approvalRequestId` does not exist

## Test Cases

- returns decisions ordered by decidedAt ASC
- returns mixed decision rows (APPROVE / REJECT / SEND_BACK / DELEGATE / WITHDRAW / CANCEL / RESUBMIT) verbatim
- returns multiple send-back/resubmit rounds (SEND_BACK then RESUBMIT) in chronological order
- returns an empty array when the request has no decisions yet
- returns REQUEST_NOT_FOUND when the request does not exist
