# ListShiftPlacementsByShift

## Overview

listShiftPlacementsByShift returns who is placed on a given Shift, paginated. It answers "who is staffing this slot" for team shifts (which may carry more than one placement), open-shift fills, and 応援/multi-site coverage.

## Business Rules

- Accepts a `shiftId` and pagination parameters
- Returns all ShiftPlacements whose `shiftId` matches; a single shift may have zero (unfilled open shift), one (typical), or more than one (team shift) placements
- A shift is considered filled when at least one ShiftPlacement references it
- Results are paginated, ordered by `assignedAt` ascending

## Process Flow

```mermaid
flowchart TD
    A[Receive shiftId and pagination params] --> B[Filter ShiftPlacement by shiftId]
    B --> C[Sort by assignedAt ascending]
    C --> D[Apply pagination]
    D --> E[Return paginated list of placements]
```

## External Dependencies

- [shiftSchedule::Shift](../model/Shift.md) — the shift whose placements are listed

## Error Scenarios

- **SHIFT_NOT_FOUND**: no Shift exists for the given id

- Returns `ACTIVE` placements by default; unlike the by-assignment queries it does **not** exclude a withdrawn slot's placements, because the caller named one shift and its detail view still has to show who had been on it

## Test Cases

- returns all ShiftPlacements for a given shiftId
- returns an empty list for an unfilled open shift
- returns more than one placement for a team shift
- throws SHIFT_NOT_FOUND for an unknown shiftId
