# AllocationCycle

## Description

AllocationCycle is the controlling entity that groups a set of allocation rules for distributing overhead costs from sender cost centers to receiver cost objects (cost centers, profit centers, or internal orders). Each cycle carries a name, allocation type (ASSESSMENT or DISTRIBUTION), company scope, accounting period reference, and a status. Assessment-type allocations post using secondary cost elements, aggregating original cost elements into a single overhead category on the receiver. Distribution-type allocations preserve the original primary cost elements on the receiver side for full cost transparency. Allocation cycles progress through a controlled lifecycle — DRAFT, VALIDATED, EXECUTED, POSTED, and optionally REVERSED — ensuring allocations are reviewed and tested before affecting the general ledger.

## Domain Model Definitions

### Model type

Stateful

#### State Transitions

```mermaid
stateDiagram-v2
    [*] --> Draft: createAllocationCycle
    Draft --> Draft: updateAllocationCycle / createAllocationRule / deleteAllocationRule
    Draft --> Validated: validateAllocationCycle
    Validated --> Draft: invalidateAllocationCycle
    Validated --> Executed: executeAllocationCycle (ACTUAL)
    Executed --> Posted: postAllocationCycle
    Posted --> Reversed: reverseAllocationCycle
    Draft --> [*]: deleteAllocationCycle
```

| Operation | From | To | Command |
|-----------|------|----|---------|
| validate | DRAFT | VALIDATED | [validateAllocationCycle](../commands/ValidateAllocationCycle.md) |
| invalidate | VALIDATED | DRAFT | [invalidateAllocationCycle](../commands/InvalidateAllocationCycle.md) |
| execute | VALIDATED | EXECUTED | [executeAllocationCycle](../commands/ExecuteAllocationCycle.md) |
| post | EXECUTED | POSTED | [postAllocationCycle](../commands/PostAllocationCycle.md) |
| reverse | POSTED | REVERSED | [reverseAllocationCycle](../commands/ReverseAllocationCycle.md) |

### Command Definitions

- [createAllocationCycle](../commands/CreateAllocationCycle.md) - Create a new allocation cycle in DRAFT status with type, name, company, and accounting period
- [updateAllocationCycle](../commands/UpdateAllocationCycle.md) - Update mutable fields of a DRAFT allocation cycle (name)
- [validateAllocationCycle](../commands/ValidateAllocationCycle.md) - Validate a DRAFT cycle, verifying all rules have percentages summing to 100% per sender
- [invalidateAllocationCycle](../commands/InvalidateAllocationCycle.md) - Return a VALIDATED cycle to DRAFT for further editing
- [executeAllocationCycle](../commands/ExecuteAllocationCycle.md) - Execute a VALIDATED cycle in ACTUAL mode, creating immutable allocation result records
- [postAllocationCycle](../commands/PostAllocationCycle.md) - Post an EXECUTED cycle, creating journal entries through finance-ledger subledger integration
- [reverseAllocationCycle](../commands/ReverseAllocationCycle.md) - Reverse a POSTED cycle by creating reversal journal entries with inverted amounts
- [deleteAllocationCycle](../commands/DeleteAllocationCycle.md) - Delete a DRAFT allocation cycle and its associated rules
- [createAllocationRule](../commands/CreateAllocationRule.md) - Add an allocation rule to a DRAFT cycle defining sender, receiver, and percentage
- [deleteAllocationRule](../commands/DeleteAllocationRule.md) - Remove an allocation rule from a DRAFT cycle

### Query Definitions

- [GetAllocationCycle](../queries/GetAllocationCycle.md) - Retrieve an allocation cycle by id with its rules and results
- [ListAllocationCycles](../queries/ListAllocationCycles.md) - List allocation cycles with filters (type, status, company, period)

### Models

- AllocationCycle
- AllocationRule
- AllocationResult

### Invariants

- Allocation cycle can only be created in DRAFT status
- Allocation cycle requires a valid type (ASSESSMENT or DISTRIBUTION)
- Allocation cycle requires a valid name
- Allocation cycle must reference a valid companyId; the company must be in ACTIVE status
- Allocation cycle must reference a valid accounting period
- Allocation rules can only be added to or removed from a DRAFT cycle
- Allocation rule percentages for a given sender must sum to exactly 100%
- Allocation rule percentage values must be positive (greater than zero)
- A sender cost center cannot also appear as a receiver within the same allocation rule set
- Validating a cycle with no allocation rules fails
- A VALIDATED cycle can be returned to DRAFT for further editing
- Executing a cycle that is not in VALIDATED status fails
- Execution in ACTUAL mode creates immutable AllocationResult records
- Posting transitions the cycle from EXECUTED to POSTED, creating journal entries
- Assessment-type allocation postings use secondary cost elements in the generated journal entries
- Distribution-type allocation postings preserve the original primary cost elements in the generated journal entries
- Posting an allocation cycle to a CLOSED or PERMANENTLY_CLOSED period is rejected
- Reversing a POSTED cycle creates reversal journal entries with inverted amounts
- A REVERSED cycle cannot be reversed again
- Updating allocation cycle fields is only permitted while in DRAFT status
- Deleting an allocation cycle is only permitted while in DRAFT status
- Allocation cycles are scoped to a company; cycles from different companies are fully isolated

### Relationships

- **References Company**: Each allocation cycle is scoped to a Company via companyId (organization module)
- **References AccountingPeriod**: Each allocation cycle references an AccountingPeriod via accountingPeriodId (finance-ledger module)
- **Has Many AllocationRule**: An allocation cycle contains one or more allocation rules defining sender-receiver-percentage mappings
- **Has Many AllocationResult**: An executed allocation cycle produces immutable allocation result records
