# WithdrawLeave

## Permission Scope

`request`

## Overview

The requester unilaterally withdraws their own still-PENDING `LeaveRequest`, moving it to CANCELLED without any approval step, restoring any reserved ledger days.

## Business Rules

- Only reachable from PENDING; unlike rejection this requires no approval decision (unilateral, ADR-011)
- Only the original requester (`workerId`) may withdraw their own request
- Restores all non-restored `LeaveConsumption` rows for this request, crediting each row's `days` back to its exact `leaveGrantId` and stamping `restoredAt` — this is the side effect this command has on the `LeaveGrant`/`LeaveConsumption` ledger
- CANCELLED is terminal and does not block a later request for the same worker/date
- If the mirrored approval-module request is still pending, it is closed as withdrawn; no approval decision is required

## Process Flow

```mermaid
flowchart TD
    A[Requester withdraws their own PENDING LeaveRequest] --> B{Caller is the original requester?}
    B -- No --> R1[Reject: NOT_REQUESTER]
    B -- Yes --> C{Request status is PENDING?}
    C -- No --> R2[Reject: INVALID_STATE_TRANSITION]
    C -- Yes --> D[Transition LeaveRequest to CANCELLED]
    D --> E[Restore all non-restored LeaveConsumption rows to their originating grants, stamp restoredAt]
    E --> F[Close the mirrored approval request as withdrawn]
```

## External Dependencies

- [leave-management::LeaveRequest](../model/LeaveRequest.md) - PENDING -> CANCELLED transition
- [leave-management::LeaveGrant](../model/LeaveGrant.md) / [leave-management::LeaveConsumption](../model/LeaveConsumption.md) - days restored to the exact grants drawn from, as a side effect of withdrawal

## Error Scenarios

- **LEAVE_REQUEST_NOT_FOUND**: no LeaveRequest exists for the given id
- **INVALID_STATE_TRANSITION**: the LeaveRequest's current status does not permit this transition
- **NOT_REQUESTER**: the caller is not the worker who filed the request

## Test Cases

- withdrawing a request restores every reserved day to its original grant
- a withdrawn request does not block a later request for the same date
- withdrawing a request that is not PENDING is rejected
- withdrawing a request filed by another worker is rejected

