# CreateBudgetLineItem

## Permission Scope

accounting

## Overview

createBudgetLineItem adds a line item to a DRAFT budget. Each line item specifies a cost element, an accounting period, and a planned amount. The GL account is derived automatically from the primary cost element's GL account mapping. Duplicate line items (same cost element and period) within a single budget are rejected.

## Business Rules

- Budget must exist and be in DRAFT status
- Line items cannot be added to budgets in SUBMITTED, APPROVED, ACTIVE, or CLOSED status
- Requires a valid `costElementId` referencing a PRIMARY cost element in ACTIVE status
- Requires a valid `accountingPeriodId` referencing an existing accounting period from finance-ledger
- Requires a `plannedAmount` that is a positive value
- GL account is derived automatically from the referenced primary cost element's GL account mapping
- Duplicate line items (same cost element and same period) within the same budget are rejected
- Emits an audit event recording the line item creation and acting user

## Process Flow

```mermaid
flowchart TD
    A[Receive create budget line item request] --> B{Budget exists?}
    B -->|No| C[Return error: BUDGET_NOT_FOUND]
    B -->|Yes| D{Status is DRAFT?}
    D -->|No| E[Return error: INVALID_STATE]
    D -->|Yes| F{Cost element exists, is PRIMARY, and ACTIVE?}
    F -->|No| G[Return error: INVALID_COST_ELEMENT]
    F -->|Yes| H{Accounting period exists?}
    H -->|No| I[Return error: ACCOUNTING_PERIOD_NOT_FOUND]
    H -->|Yes| J{Planned amount is positive?}
    J -->|No| K[Return error: INVALID_PLANNED_AMOUNT]
    J -->|Yes| L{Duplicate line item exists?}
    L -->|Yes| M[Return error: DUPLICATE_LINE_ITEM]
    L -->|No| N[Derive GL account from cost element]
    N --> O[Create budget line item]
    O --> P[Emit audit event]
    P --> Q[Return created line item]
```

## External Dependencies

- [finance-ledger::getAccountingPeriod](../../../finance-ledger/docs/queries/GetAccountingPeriod.md) — Validates that the referenced accounting period exists

## Error Scenarios

- **BUDGET_NOT_FOUND**: Budget with the specified ID does not exist
- **INVALID_STATE**: Target entity is not in a valid status for this operation
- **INVALID_COST_ELEMENT**: Referenced cost element does not exist, is not PRIMARY type, or is not in ACTIVE status
- **ACCOUNTING_PERIOD_NOT_FOUND**: Referenced accounting period does not exist
- **INVALID_PLANNED_AMOUNT**: Planned amount is not a positive value
- **DUPLICATE_LINE_ITEM**: A line item with the same cost element and period already exists in this budget

## Test Cases

- adds a line item to a DRAFT budget with valid cost element, period, and amount
- derives GL account automatically from the primary cost element
- returns error when budget does not exist
- returns error when budget is not in DRAFT status
- returns error when cost element does not exist
- returns error when cost element is not PRIMARY type
- returns error when cost element is not in ACTIVE status
- returns error when accounting period does not exist
- returns error when planned amount is zero
- returns error when planned amount is negative
- returns error when duplicate line item exists (same cost element and period)
- emits audit event recording the line item creation and acting user
