# EndAssignment

## Permission Scope

`appointment`

## Overview

EndAssignment closes the current open Assignment generation — for example on termination, post abolition, or return from a concurrent post — without creating a replacement generation.

## Business Rules

- Closing sets `effectiveEnd` on the current open generation; the generation is preserved, not deleted
- Only an open (`effectiveEnd IS NULL`) Assignment can be closed
- The end date must not precede the generation's `effectiveStart`
- Closing the sole primary Assignment leaves the employment with no current post until a new Assignment is created
- Ending due to Position abolition or WorkerEmployment termination closes the generation in lockstep with that event

## Process Flow

```mermaid
flowchart TD
    A[End Assignment on date] --> B{Assignment generation currently open?}
    B -- No --> X[Reject: ASSIGNMENT_ALREADY_CLOSED]
    B -- Yes --> C{End date on or after effectiveStart?}
    C -- No --> Y[Reject: END_DATE_BEFORE_EFFECTIVE_START]
    C -- Yes --> D[Set effectiveEnd on the generation]
    D --> E[Employment now has no open Assignment at this post]
```

## External Dependencies

- [workforce::Assignment](../model/Assignment.md) model — the generation being closed
- [workforce::WorkerEmployment](../model/WorkerEmployment.md) model — employment whose termination may trigger this
- [workforce::Position](../model/Position.md) model — post whose abolition may trigger this

## Error Scenarios

- **ASSIGNMENT_NOT_FOUND**: the specified Assignment does not exist
- **ASSIGNMENT_ALREADY_CLOSED**: the Assignment generation is already closed
- **END_DATE_BEFORE_EFFECTIVE_START**: the end date precedes the generation's `effectiveStart`

## Test Cases

- ending an open Assignment closes it with the given end date
- ending an already-closed Assignment is rejected
- ending a non-existent Assignment is rejected
- ending the primary Assignment for an employment leaves it with no current primary post

