# ListCalculatedBlocksByTimeEntryCode

## Overview

Lists `CalculatedTimeBlock`s matching a given `timeEntryCodeKey` over a date range, paginated. This is the aggregation input for downstream consumers such as payroll and Article-36 agreement threshold evaluation, which need every block of a given category (e.g. overtime) across a period.

## Business Rules

- Filters by `timeEntryCodeKey` (stable key, not display name) and an inclusive `workDate` range
- Only current CalculatedTimeBlocks are returned; superseded/discarded prior calculations are not included
- Results are paginated
- Intended consumers are payroll, costing, and Article-36 agreement monitoring, which read this layer exclusively and never TimeClockEvent or ReportedTimeBlock directly

## Process Flow

```mermaid
flowchart TD
    A[Caller supplies timeEntryCodeKey + date range + pagination params] --> B{Valid key and range?}
    B -- No --> C[Return INVALID_QUERY_PARAMS]
    B -- Yes --> D[Look up current CalculatedTimeBlocks matching timeEntryCodeKey within date range]
    D --> E[Return paginated page of blocks]
```

## External Dependencies

- [time-tracking::CalculatedTimeBlock](../model/CalculatedTimeBlock.md) model — entity being queried

## Error Scenarios

- **INVALID_QUERY_PARAMS**: a required query parameter is missing or malformed
- **INVALID_PAGINATION_CURSOR**: supplied pagination cursor is not valid for this query

## Test Cases

- returns CalculatedTimeBlocks matching the given timeEntryCodeKey within the date range
- excludes blocks with a different timeEntryCodeKey
- returns an empty page when no blocks match the key/range
- returns INVALID_QUERY_PARAMS when the date range start is after the end
- returns INVALID_QUERY_PARAMS when timeEntryCodeKey is missing
- relabeling a TimeEntryCode's display name does not change which blocks match the query, since matching is by key
