# AccountingPeriod

## Description

AccountingPeriod represents a discrete time segment (typically a month, quarter, or custom interval) within a fiscal year, scoped to a single company via companyId. Each period carries a start date, end date, period name, period type (OPERATING or ADJUSTMENT), and a four-state status that governs whether journal entries can be posted. The lifecycle (NEVER_OPENED, OPEN, CLOSED, PERMANENTLY_CLOSED) keeps actual ledger posting tied to the OPEN state. Accounting periods are the temporal backbone of the general ledger — every journal entry must reference a valid period, and the period's current status determines whether that posting is accepted or rejected.

## Domain Model Definitions

### Model type

Stateful

#### State Transitions

```mermaid
stateDiagram-v2
    [*] --> NeverOpened: createAccountingPeriod
    NeverOpened --> Open: openPeriod
    Open --> Closed: closePeriod
    Closed --> Open: reopenPeriod
    Closed --> PermanentlyClosed: permanentlyClosePeriod
    PermanentlyClosed --> [*]
```

| Operation | From | To | Command |
|-----------|------|----|---------|
| openPeriod | NEVER_OPENED | OPEN | [openPeriod](../command/OpenPeriod.md) |
| closePeriod | OPEN | CLOSED | [closePeriod](../command/ClosePeriod.md) |
| reopenPeriod | CLOSED | OPEN | [reopenPeriod](../command/ReopenPeriod.md) |
| permanentlyClosePeriod | CLOSED | PERMANENTLY_CLOSED | [permanentlyClosePeriod](../command/PermanentlyClosePeriod.md) |

### Command Definitions

- [createAccountingPeriod](../command/CreateAccountingPeriod.md) - Create a new accounting period in NEVER_OPENED status within a fiscal year
- [openPeriod](../command/OpenPeriod.md) - Transition a NEVER_OPENED period to OPEN
- [closePeriod](../command/ClosePeriod.md) - Transition an OPEN period to CLOSED
- [reopenPeriod](../command/ReopenPeriod.md) - Transition a CLOSED period back to OPEN for adjustments
- [permanentlyClosePeriod](../command/PermanentlyClosePeriod.md) - Transition a CLOSED period to PERMANENTLY_CLOSED (irreversible)
- [deleteAccountingPeriod](../command/DeleteAccountingPeriod.md) - Delete an accounting period with no associated journal entries

### Query Definitions

- [GetAccountingPeriod](../query/GetAccountingPeriod.md) - Retrieve an accounting period by id
- [ListAccountingPeriods](../query/ListAccountingPeriods.md) - List accounting periods for a fiscal year or company with optional status filter
- [GetPeriodByDate](../query/GetPeriodByDate.md) - Find the accounting period for a given date and company

### Models

- AccountingPeriod

### Invariants

- Accounting periods can only be created in NEVER_OPENED status
- Period name is required and must be non-empty
- Period must have a valid start date and end date, with start date strictly before end date
- Period must reference a valid companyId from the organization module
- Period must belong to a fiscal year that is scoped to the same company
- Periods within the same fiscal year must not have overlapping date ranges
- Periods within the same fiscal year must cover the full fiscal year date range without gaps
- Two periods in the same fiscal year cannot have identical start and end dates unless one is an adjustment period
- Period type must be OPERATING or ADJUSTMENT
- Adjustment periods share the same end date as the final regular period but are typed as ADJUSTMENT
- A PERMANENTLY_CLOSED period cannot transition to any other status (irreversible)
- An OPEN period cannot transition directly to PERMANENTLY_CLOSED (must go through CLOSED first)
- A NEVER_OPENED period cannot transition directly to CLOSED
- A period cannot be deleted if it has any associated journal entries regardless of status
- Journal entries can only be posted to periods in OPEN status

### Relationships

- **References Company**: Each accounting period is scoped to a Company via companyId (organization module)
- **References FiscalYear**: Each accounting period belongs to a FiscalYear via fiscalYearId
- **Has Many JournalEntry**: An accounting period may have journal entries posted to it
