# CreateCostElement

## Permission Scope

accounting

## Overview

createCostElement establishes a new cost element in DRAFT status within the management accounting module. The cost element carries a company reference, a unique code within the company scope, a name, a type (PRIMARY or SECONDARY), a category that must match the type, an optional GL account reference (required for PRIMARY, forbidden for SECONDARY), optional validity dates (validFrom, validTo), and an optional description. Cost elements are the foundational classification for all cost postings and allocations in the accounting module.

## Business Rules

- Cost element is always created in DRAFT status
- Requires a valid `companyId` referencing an ACTIVE company from the organization module
- Requires a `code` that is unique within the company scope
- Requires a `name`
- Requires a `type` of either PRIMARY or SECONDARY
- Requires a `category` appropriate to its type: overhead, material, labor, or depreciation for PRIMARY; assessment, distribution, internal_activity_allocation, or settlement for SECONDARY
- PRIMARY cost elements must provide a `glAccountId` referencing an active GL account from an active Chart of Accounts
- SECONDARY cost elements must not provide a `glAccountId`; supplying one is rejected
- Two PRIMARY cost elements within the same company cannot reference the same GL account
- When both `validFrom` and `validTo` are provided, `validFrom` must be less than or equal to `validTo`
- `validFrom` and `validTo` are optional; omitting them means the element is valid indefinitely
- `description` is optional and can be set on creation
- Cost elements are scoped to a company; elements from different companies are fully isolated
- Emits an audit event recording the acting user, timestamp, and initial field values

## Process Flow

```mermaid
flowchart TD
    A[Receive create cost element request] --> B{Company exists and is ACTIVE?}
    B -->|No| C[Return error: COMPANY_NOT_FOUND]
    B -->|Yes| D{Code unique within company?}
    D -->|No| E[Return error: DUPLICATE_COST_ELEMENT_CODE]
    D -->|Yes| F{Valid type: PRIMARY or SECONDARY?}
    F -->|No| G[Return error: INVALID_COST_ELEMENT_TYPE]
    F -->|Yes| H{Category matches type?}
    H -->|No| I[Return error: INVALID_CATEGORY_FOR_TYPE]
    H -->|Yes| J{Type is PRIMARY?}
    J -->|Yes| K{glAccountId provided?}
    K -->|No| L[Return error: GL_ACCOUNT_REQUIRED]
    K -->|Yes| M{GL account exists and is active in active CoA?}
    M -->|No| N[Return error: GL_ACCOUNT_NOT_FOUND]
    M -->|Yes| O{Another PRIMARY element references same GL account?}
    O -->|Yes| P[Return error: DUPLICATE_GL_ACCOUNT_REFERENCE]
    O -->|No| Q[Validate dates]
    J -->|No| R{glAccountId provided?}
    R -->|Yes| S[Return error: GL_ACCOUNT_NOT_ALLOWED]
    R -->|No| Q
    Q --> T{validFrom <= validTo when both set?}
    T -->|No| U[Return error: INVALID_VALIDITY_PERIOD]
    T -->|Yes| V[Create cost element in DRAFT status]
    V --> W[Emit audit event]
    W --> X[Return created cost element]
```

## External Dependencies

- [organization::getCompany](../../../organization/docs/queries/GetCompany.md) — Validates that the referenced company exists and is ACTIVE
- [coa-management::getAccount](../../../coa-management/docs/queries/GetAccount.md) — Validates that the referenced GL account exists and is active within an active Chart of Accounts

## Error Scenarios

- **COMPANY_NOT_FOUND**: Referenced company does not exist or is not in ACTIVE status
- **DUPLICATE_COST_ELEMENT_CODE**: A cost element with the same code already exists within the company
- **INVALID_COST_ELEMENT_TYPE**: Type is not PRIMARY or SECONDARY
- **INVALID_CATEGORY_FOR_TYPE**: Category does not match the cost element type
- **GL_ACCOUNT_REQUIRED**: PRIMARY cost element is missing the required glAccountId
- **GL_ACCOUNT_NOT_FOUND**: Referenced GL account does not exist or is not active within an active Chart of Accounts
- **GL_ACCOUNT_NOT_ALLOWED**: SECONDARY cost element must not reference a GL account
- **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

- creates cost element in DRAFT status with required fields
- returns error when company does not exist
- returns error when company is not ACTIVE
- returns error when code already exists within the company
- returns error when type is not PRIMARY or SECONDARY
- returns error when category does not match the type (primary category on secondary element)
- returns error when category does not match the type (secondary category on primary element)
- returns error when PRIMARY element is missing glAccountId
- returns error when GL account does not exist
- returns error when GL account is not active
- returns error when GL account is not in an active Chart of Accounts
- returns error when SECONDARY element provides a glAccountId
- returns error when another PRIMARY element in the same company references the same GL account
- returns error when validFrom is after validTo
- creates cost element with optional description
- creates cost element with validFrom and validTo dates
- creates cost element without validity dates (indefinitely valid)
- cost elements from different companies are isolated
- emits audit event recording acting user, timestamp, and initial field values
