# TerminateWorkerEmployment

## Permission Scope

`employment`

## Overview

TerminateWorkerEmployment sets the termination date on an employment and closes its currently open generation, ending the employment relationship while preserving the Worker for possible re-hire.

## Business Rules

- Setting a termination date closes the open generation (`effectiveEnd` = termination date); no open generation exists beyond termination
- The termination date must not precede the current generation's `effectiveStart`
- Terminating an employment closes any open Assignment(s) tied to it so no post remains occupied by a terminated employment
- The Worker is preserved after termination; a new WorkerEmployment may later be opened for the same Worker (re-hire)

## Process Flow

```mermaid
flowchart TD
    A[Terminate employment on date T] --> B{Employment exists and open?}
    B -- No --> X[Reject: WORKER_EMPLOYMENT_NOT_FOUND / ALREADY_TERMINATED]
    B -- Yes --> C{T on or after current generation's effectiveStart?}
    C -- No --> Y[Reject: TERMINATION_DATE_BEFORE_EFFECTIVE_START]
    C -- Yes --> D[Set effectiveEnd = T on open generation]
    D --> E[Close any open Assignment(s) tied to this employment]
```

## External Dependencies

- [workforce::WorkerEmployment](../model/WorkerEmployment.md) model — the entity this command mutates
- [workforce::Assignment](../model/Assignment.md) model — open Assignments closed as a consequence of termination

## Error Scenarios

- **WORKER_EMPLOYMENT_NOT_FOUND**: the specified WorkerEmployment does not exist
- **ALREADY_TERMINATED**: the employment has no open generation to terminate
- **TERMINATION_DATE_BEFORE_EFFECTIVE_START**: the termination date precedes the current generation's `effectiveStart`

## Test Cases

- terminating an employment leaves no open generation beyond the termination date
- closing the employment also closes its open Assignments at the termination date
- terminating with a date before the employment's effectiveStart is rejected
- terminating an already-terminated employment is rejected
- terminating a non-existent WorkerEmployment returns WORKER_EMPLOYMENT_NOT_FOUND

