# UpdateCostElement

## Permission Scope

accounting

## Overview

updateCostElement modifies fields on an existing cost element that is in DRAFT or ACTIVE status. Description and name can be updated in both DRAFT and ACTIVE status. Category and GL account reference changes are only permitted while the element is in DRAFT status. Type changes are never permitted. The command enforces field-level mutability rules based on the current lifecycle status to preserve referential integrity of downstream cost postings and allocations.

## Business Rules

- Cost element must exist and be in DRAFT or ACTIVE status
- Description can be updated in both DRAFT and ACTIVE status
- Name can be updated in both DRAFT and ACTIVE status
- Category change is not permitted when the cost element is in ACTIVE status
- GL account reference change is not permitted after activation (only updatable in DRAFT)
- Type change (PRIMARY to SECONDARY or vice versa) is never permitted
- When updating category, the new category must still match the element's type
- When updating GL account reference on a DRAFT PRIMARY element, the new GL account must be active in an active CoA
- When updating GL account reference, no other PRIMARY element in the same company may reference the new GL account
- When updating validFrom/validTo, validFrom must be less than or equal to validTo when both are set
- INACTIVE cost elements cannot be updated
- Emits an audit event recording previous and new field values

## Process Flow

```mermaid
flowchart TD
    A[Receive update cost element request] --> B{Cost element exists?}
    B -->|No| C[Return error: COST_ELEMENT_NOT_FOUND]
    B -->|Yes| D{Status is DRAFT or ACTIVE?}
    D -->|No| E[Return error: INVALID_STATE]
    D -->|Yes| F{Type change attempted?}
    F -->|Yes| G[Return error: TYPE_CHANGE_NOT_ALLOWED]
    F -->|No| H{Status is ACTIVE and category change attempted?}
    H -->|Yes| I[Return error: CATEGORY_CHANGE_NOT_ALLOWED]
    H -->|No| J{Status is ACTIVE and GL account change attempted?}
    J -->|Yes| K[Return error: GL_ACCOUNT_CHANGE_NOT_ALLOWED]
    J -->|No| L{Category matches type if changed?}
    L -->|No| M[Return error: INVALID_CATEGORY_FOR_TYPE]
    L -->|Yes| N{GL account valid if changed?}
    N -->|No| O[Return error: GL_ACCOUNT_NOT_FOUND]
    N -->|Yes| P{Duplicate GL account reference?}
    P -->|Yes| Q[Return error: DUPLICATE_GL_ACCOUNT_REFERENCE]
    P -->|No| R{validFrom <= validTo when both set?}
    R -->|No| S[Return error: INVALID_VALIDITY_PERIOD]
    R -->|Yes| T[Apply updates to cost element]
    T --> U[Emit audit event]
    U --> V[Return updated cost element]
```

## External Dependencies

- [coa-management::getAccount](../../../coa-management/docs/queries/GetAccount.md) — Validates updated GL account reference if changed

## Error Scenarios

- **COST_ELEMENT_NOT_FOUND**: Referenced cost element does not exist
- **INVALID_STATE**: Target entity is not in a valid status for this operation
- **TYPE_CHANGE_NOT_ALLOWED**: Changing the type (PRIMARY/SECONDARY) is never permitted
- **CATEGORY_CHANGE_NOT_ALLOWED**: Category cannot be changed when the cost element is in ACTIVE status
- **GL_ACCOUNT_CHANGE_NOT_ALLOWED**: GL account reference cannot be changed after activation
- **INVALID_CATEGORY_FOR_TYPE**: Category does not match the cost element type
- **GL_ACCOUNT_NOT_FOUND**: Referenced GL account does not exist or is not active within an active Chart of Accounts
- **DUPLICATE_GL_ACCOUNT_REFERENCE**: Another PRIMARY cost element within the same company already references the specified GL account
- **INVALID_VALIDITY_PERIOD**: validFrom is after validTo

## Test Cases

- updates description on a DRAFT cost element
- updates description on an ACTIVE cost element
- updates name on a DRAFT cost element
- updates name on an ACTIVE cost element
- updates category on a DRAFT cost element
- returns error when changing category on an ACTIVE cost element
- returns error when changing type on any cost element
- returns error when changing GL account on an ACTIVE cost element
- updates GL account on a DRAFT PRIMARY cost element
- returns error when updated GL account does not exist
- returns error when updated GL account is already referenced by another PRIMARY element
- returns error when new category does not match the element type
- returns error when cost element does not exist
- returns error when cost element is INACTIVE
- returns error when validFrom is after validTo
- emits audit event recording previous and new field values
