# CostElement

## Description

CostElement is the foundational classification entity of the accounting module, defining the types of costs that can be recorded, allocated, and analyzed across cost centers, profit centers, and internal orders. Each cost element carries a code, name, type (PRIMARY or SECONDARY), category, optional description, optional GL account reference (mandatory for primary elements), company scope, and optional validity period. Primary cost elements are mapped one-to-one to GL accounts from coa-management and represent costs visible in both financial and management accounting (e.g., material costs, labor costs, depreciation). Secondary cost elements exist exclusively within the controlling domain for internal cost allocation activities such as assessment, distribution, and settlement. Cost elements follow a lifecycle from DRAFT through ACTIVE to INACTIVE, ensuring that only validated cost types are available for postings.

## Domain Model Definitions

### Model type

Stateful

#### State Transitions

```mermaid
stateDiagram-v2
    [*] --> Draft: createCostElement
    Draft --> Draft: updateCostElement
    Draft --> Active: activateCostElement
    Active --> Inactive: deactivateCostElement
    Inactive --> Active: reactivateCostElement
    Draft --> [*]: deleteCostElement
```

| Operation | From | To | Command |
|-----------|------|----|---------|
| activate | DRAFT | ACTIVE | [activateCostElement](../commands/ActivateCostElement.md) |
| deactivate | ACTIVE | INACTIVE | [deactivateCostElement](../commands/DeactivateCostElement.md) |
| reactivate | INACTIVE | ACTIVE | [reactivateCostElement](../commands/ReactivateCostElement.md) |

### Command Definitions

- [createCostElement](../commands/CreateCostElement.md) - Create a new cost element in DRAFT status with code, name, type, category, and optional GL account reference
- [updateCostElement](../commands/UpdateCostElement.md) - Update mutable fields of a cost element (name, description, validity dates)
- [activateCostElement](../commands/ActivateCostElement.md) - Activate a DRAFT cost element, making it available for cost postings and allocations
- [deactivateCostElement](../commands/DeactivateCostElement.md) - Deactivate an ACTIVE cost element, preventing new postings while preserving historical data
- [reactivateCostElement](../commands/ReactivateCostElement.md) - Reactivate an INACTIVE cost element back to ACTIVE status
- [deleteCostElement](../commands/DeleteCostElement.md) - Delete a DRAFT cost element that has not been activated

### Query Definitions

- [GetCostElement](../queries/GetCostElement.md) - Retrieve a cost element by id
- [ListCostElements](../queries/ListCostElements.md) - List cost elements with filters (type, category, status, company)

### Models

- CostElement

### Invariants

- Cost elements can only be created in DRAFT status
- Cost element requires a unique code within the company scope
- Cost element requires a name and a type (PRIMARY or SECONDARY)
- Cost element requires a category appropriate to its type: overhead, material, labor, depreciation for PRIMARY; assessment, distribution, internal_activity_allocation, settlement for SECONDARY
- A primary cost element must reference a valid GL account from an ACTIVE Chart of Accounts; the GL account must be active
- A secondary cost element must not reference a GL account
- Two primary cost elements within the same company cannot reference the same GL account
- A primary cost element's GL account must belong to the same company's chart of accounts
- Cost element valid-from date must be before or equal to valid-to date when both are provided; omitting them means the element is valid indefinitely
- Only DRAFT cost elements can be deleted; ACTIVE and INACTIVE elements cannot be deleted
- Changing the type of a cost element (PRIMARY to SECONDARY or vice versa) after activation is not permitted
- Changing the GL account reference of a primary cost element after activation is not permitted
- Updating the category of an ACTIVE cost element is not permitted
- Cost postings referencing a cost element that is INACTIVE or outside its validity period are rejected
- Secondary cost elements can only be used in internal allocation contexts (assessment, distribution, activity allocation, settlement)
- Cost elements are scoped to a company; elements from different companies are fully isolated
- Cost element must reference a valid companyId; the company must be in ACTIVE status

### Relationships

- **References Company**: Each cost element is scoped to a Company via companyId (organization module)
- **References GLAccount**: Primary cost elements reference a GLAccount via glAccountId (coa-management module); secondary cost elements have no GL account reference
