# PostJournalEntry

## Permission Scope

journalEntry

## Overview

postJournalEntry transitions a journal entry from DRAFT to POSTED status and appends immutable AccountingLedger facts. Posting ensures the entry has at least two journal lines, verifies that the target accounting period is in OPEN status, validates the fundamental accounting constraint (total debits must equal total credits), confirms all referenced GL accounts exist, then copies the prepared JournalLine effects into posted-only ledger rows.

## Business Rules

- Journal entry must exist and be in DRAFT status
- Entry must have at least two journal lines
- Total debits must equal total credits (balance validation)
- An unbalanced entry cannot be posted
- The target accounting period must be in OPEN status
- Posting to a NEVER_OPENED, CLOSED, or PERMANENTLY_CLOSED period is rejected
- All referenced GL accounts must exist
- Posting creates AccountingLedger rows from the prepared JournalLine rows
- AccountingLedger rows carry company, accounting period, posting date, account, and amount fields for flat posted-fact queries
- Once posted, the entry is immutable (no field updates, no line additions or removals)
- Posted entries cannot be deleted; only reversal is permitted

## Process Flow

```mermaid
flowchart TD
    A[Receive post journal entry request] --> B{Journal entry exists?}
    B -->|No| C[Return error: journal entry not found]
    B -->|Yes| D{Entry status is DRAFT?}
    D -->|No| E[Return error: invalid status for posting]
    D -->|Yes| F{At least 2 journal lines?}
    F -->|No| G[Return error: minimum lines not met]
    F -->|Yes| L{Period OPEN?}
    L -->|No| M[Return error: invalid period status]
    L -->|Yes| N{Debits equal credits?}
    N -->|No| O[Return error: unbalanced entry]
    N -->|Yes| H{All GL accounts exist?}
    H -->|No| I[Return error: account not found]
    H -->|Yes| P[Create AccountingLedger rows]
    P --> Q[Transition entry to POSTED]
    Q --> S[Return posted journal entry and ledger facts]
```

## External Dependencies

- [coa-management::getAccount](../../../coa-management/docs/query/GetAccount.md) - Validates that all referenced GL accounts exist

## Error Scenarios

- **JOURNAL_ENTRY_NOT_FOUND**: Referenced journal entry does not exist
- **INVALID_STATUS_FOR_POSTING**: Journal entry is not in DRAFT status; only DRAFT entries can be posted
- **MINIMUM_LINES_NOT_MET**: Journal entry has fewer than two journal lines
- **UNBALANCED_ENTRY**: Total debits do not equal total credits
- **INVALID_PERIOD_STATUS**: Target accounting period is not in OPEN status
- **ACCOUNT_NOT_FOUND**: Referenced GL account does not exist

## Test Cases

- returns error when journal entry does not exist
- returns error when journal entry is already POSTED
- returns error when journal entry is REVERSED
- returns error when entry has fewer than two journal lines
- returns error when entry has only one line (debit only or credit only)
- returns error when total debits do not equal total credits
- returns error when target period is in NEVER_OPENED status
- returns error when target period is in CLOSED status
- returns error when target period is in PERMANENTLY_CLOSED status
- returns error when a GL account reference does not exist
- posts balanced DRAFT entry to OPEN period
- creates AccountingLedger rows from journal lines when posting succeeds
- entry becomes immutable after posting
