# CreateJournalEntry

## Permission Scope

journalEntry

## Overview

createJournalEntry establishes a new journal entry in DRAFT status within the general ledger. The journal entry header carries a company reference, accounting period reference, journal type (Sales, Purchase, Cash, Bank, Miscellaneous, Opening), reference number, entry date, optional description, and optional source document reference. Journal entries are the fundamental transactional unit of double-entry bookkeeping; lines are added separately via addJournalLine before the entry can be posted.

## Business Rules

- Journal entry is always created in DRAFT status
- Requires a valid `companyId` referencing an ACTIVE company from the organization module
- Requires a valid `accountingPeriodId` referencing an existing accounting period
- Requires a valid journal type: Sales, Purchase, Cash, Bank, Miscellaneous, or Opening
- Requires a reference number that is unique within the company scope
- Requires a valid entry date
- Description is optional and can be set on creation
- Source document reference is optional and can be set on creation
- Journal entries are scoped to a company; entries from different companies are fully isolated
- Emits an audit event via the audit module recording the acting user, timestamp, and initial field values

## Process Flow

```mermaid
flowchart TD
    A[Receive create journal entry request] --> B{Company exists and is ACTIVE?}
    B -->|No| C[Return error: company not found]
    B -->|Yes| D{Accounting period exists?}
    D -->|No| E[Return error: period not found]
    D -->|Yes| F{Valid journal type?}
    F -->|No| G[Return error: invalid journal type]
    F -->|Yes| H{Reference number unique within company?}
    H -->|No| I[Return error: duplicate reference number]
    H -->|Yes| J{Valid entry date?}
    J -->|No| K[Return error: invalid entry date]
    J -->|Yes| L[Create journal entry in DRAFT status]
    L --> M[Emit audit event]
    M --> N[Return created journal entry]
```

## External Dependencies

- [organization::getCompany](../../../organization/docs/queries/GetCompany.md) - Validates that the referenced company exists and is ACTIVE

## Error Scenarios

- **COMPANY_NOT_FOUND**: Referenced company does not exist or is not in ACTIVE status
- **ACCOUNTING_PERIOD_NOT_FOUND**: Referenced accounting period does not exist
- **INVALID_JOURNAL_TYPE**: Journal type is not one of the recognized values (Sales, Purchase, Cash, Bank, Miscellaneous, Opening)
- **DUPLICATE_REFERENCE_NUMBER**: A journal entry with the same reference number already exists within the company
- **INVALID_ENTRY_DATE**: Entry date is not a valid date

## Test Cases

- returns error when company does not exist
- returns error when company is not ACTIVE
- returns error when accounting period does not exist
- returns error when journal type is invalid
- returns error when reference number already exists within the company
- returns error when entry date is invalid
- creates journal entry in DRAFT status with required fields
- creates journal entry with optional description
- creates journal entry with optional source document reference
- journal entries from different companies are isolated
- emits audit event recording acting user, timestamp, and initial field values
