# CalculateBudgetAvailability

## Overview

CalculateBudgetAvailability computes the available budget for a given cost element, cost object, and accounting period using the formula: Available = Budget - (Actual + Commitments + Encumbrances). The budget amount is sourced from the matching BudgetLineItem in the ACTIVE budget for the cost object. Actual amounts are sourced from posted journal entries in the finance-ledger module. Commitment amounts are sourced from outstanding purchase order commitment records received from the purchase module. Encumbrances are reserved for future extension and treated as zero in the current implementation. This query is the foundation for budgetary control (funds check) and is invoked during transaction validation to prevent overspending.

## Business Rules

- Accepts required parameters: `{ costElementId, costObjectId, costObjectType, accountingPeriodId }`
- Locates the ACTIVE budget matching the cost object and fiscal year containing the given accounting period
- Retrieves the BudgetLineItem matching the cost element and accounting period
- If no matching budget or line item exists, returns available as null with a flag indicating no budget is defined
- Budget amount is the planned amount from the matching BudgetLineItem
- Actual amount is the sum of posted journal entry line amounts matching the cost element, cost object, and accounting period
- Commitment amount is the sum of outstanding purchase order commitment records matching the cost element, cost object, and accounting period
- Encumbrance amount is zero (future extension placeholder)
- Available = Budget - (Actual + Commitments + Encumbrances)
- Returns the computed availability along with each component amount (budget, actual, commitments, encumbrances, available)

## Process Flow

```mermaid
flowchart TD
    A[Receive input: costElementId, costObjectId, costObjectType, accountingPeriodId] --> B[Find ACTIVE budget for cost object and fiscal year]
    B --> C{ACTIVE budget found?}
    C -->|No| D[Return null availability with NO_BUDGET_DEFINED flag]
    C -->|Yes| E[Find BudgetLineItem matching cost element and period]
    E --> F{Line item found?}
    F -->|No| G[Return null availability with NO_BUDGET_LINE_ITEM flag]
    F -->|Yes| H[Retrieve budget amount from line item]
    H --> I[Sum actual amounts from posted journal entries]
    I --> J[Sum commitment amounts from commitment records]
    J --> K[Set encumbrance amount to zero]
    K --> L[Compute Available = Budget - Actual + Commitments + Encumbrances]
    L --> M[Return budget, actual, commitments, encumbrances, and available amounts]
```

## External Dependencies

- [finance-ledger::listJournalEntries](../../../finance-ledger/docs/queries/ListJournalEntries.md) - Actual amounts sourced from posted journal entries

## Error Scenarios

- **NO_BUDGET_DEFINED**: No ACTIVE budget exists for the specified cost object and fiscal year — caller receives null availability
- **NO_BUDGET_LINE_ITEM**: ACTIVE budget exists but no line item matches the specified cost element and period — caller receives null availability
- **COST_ELEMENT_NOT_FOUND**: Provided costElementId does not reference an existing cost element
- **COST_OBJECT_NOT_FOUND**: Provided costObjectId does not reference an existing cost object of the specified type
- **ACCOUNTING_PERIOD_NOT_FOUND**: Provided accountingPeriodId does not reference an existing accounting period

## Test Cases

- returns error when cost element does not exist
- returns error when cost object does not exist
- returns error when accounting period does not exist
- returns budget availability with all component amounts when budget and line item exist
- computes available as budget minus actual plus commitments plus encumbrances
- returns actual amount aggregated from posted journal entries only
- excludes draft journal entries from actual amount calculation
- returns commitment amount from outstanding purchase order records
- returns encumbrance amount as zero
- returns null availability with NO_BUDGET_DEFINED flag when no active budget exists
- returns null availability with NO_BUDGET_LINE_ITEM flag when line item does not exist for cost element and period
- handles zero budget amount gracefully
- handles case where actual exceeds budget resulting in negative availability
