# GetTimeEntryCodeByKey

## Overview

GetTimeEntryCodeByKey resolves a `TimeEntryCode` by its stable `key`. It is the lookup calculation, premium determination, and pay mapping use to bind logic to a machine-stable identifier rather than a display label.

## Business Rules

- Resolves by the stable business key `key`, not the surrogate id — `key` is unique and immutable once any rule references it (ADR-015, issue #14)
- Never resolves by `displayName`; a renamed display name does not change the result of this lookup
- `TimeEntryCode` is master data, not effective-dated — the lookup always reflects the current catalog entry, with no `asOf` history to reconstruct

## Process Flow

```mermaid
flowchart TD
    A[Caller provides a key] --> B[Look up TimeEntryCode by key]
    B --> C{Found?}
    C -- Yes --> D[Return TimeEntryCode: category, displayName, payMapKey]
    C -- No --> E[Return TIME_ENTRY_CODE_NOT_FOUND]
    D --> F[Calculation applies category-driven premium/treatment]
```

## External Dependencies

- [time-tracking::TimeEntryCode](../model/TimeEntryCode.md) model — entity being queried
- Consumed by time-tracking calculation (Reported → Calculated) to resolve a time type by key and stamp the CalculationTag on each CalculatedTimeBlock

## Error Scenarios

- **TIME_ENTRY_CODE_NOT_FOUND**: no TimeEntryCode exists for the given id
- **VALIDATION_ERROR**: the supplied input is malformed, out of range, or references an unrecognized enum value

## Test Cases

- calculation resolves a time type via `getTimeEntryCodeByKey`, not via display name
- returns TIME_ENTRY_CODE_NOT_FOUND when no code matches the given key
- renaming `displayName` does not change the result returned for the same `key`
- a code's `payMapKey` is preserved verbatim for downstream pay routing
- returns VALIDATION_ERROR when the key is empty
