# PostJournalEntry

## Permission Scope

journalEntry

## Overview

postJournalEntry transitions a journal entry from DRAFT to POSTED status. 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), and confirms all referenced GL accounts exist and are ACTIVE. After posting, the JournalLine rows under the POSTED entry are the immutable ledger surface.

## 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 and be ACTIVE
- Posting does not copy JournalLine rows into a separate ledger table
- Ledger queries use JournalLine rows whose parent JournalEntry is POSTED
- 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 active?}
    H -->|No| I[Return error: account not found]
    H -->|Yes| Q[Transition entry to POSTED]
    Q --> S[Return posted journal entry]
```

## External Dependencies

- [coa-management::ListAccounts](../../../coa-management/docs/query/ListAccounts.md) - Validates that all referenced GL accounts exist and are ACTIVE

## 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
- **ACCOUNT_INACTIVE**: Referenced GL account is not ACTIVE

## Test Cases

- returns error when journal entry does not exist
- returns error when journal entry is already POSTED
- returns error when journal entry is CANCELLED
- 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
- returns error when a GL account reference is inactive
- posts balanced DRAFT entry to OPEN period
- does not copy journal lines into a separate ledger table when posting succeeds
- entry becomes immutable after posting
