# Accounting Period Management

## Overview

Accounting Period Management defines and controls the lifecycle of fiscal periods within the finance-ledger module. Each accounting period represents a discrete time segment (typically a month, quarter, or custom interval) within a fiscal year, scoped to a single company via `companyId`. Periods carry a start date, end date, period name, period type, and a five-state status that governs whether journal entries can be posted. The five-state lifecycle (NEVER_OPENED, FUTURE_ENTERABLE, OPEN, CLOSED, PERMANENTLY_CLOSED) mirrors the industry-standard model used by Oracle Financials and provides granular control over when and how transactions flow into each period.

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. This module is responsible for defining the fiscal calendar structure (including support for non-calendar fiscal years such as 4-4-5 week schemes or 13-period years), exposing period status queries that upstream modules (purchase, sales, inventory, manufacturing) use to validate posting eligibility, and enforcing the sequential integrity of period transitions. Period management is a compliance requirement under GAAP, IFRS, and most local regulations — locking closed periods prevents backdated entries that would compromise financial statement integrity.

## Business Purpose

Organizations need disciplined period management to maintain accurate, auditable, and regulation-compliant financial records:

- **Posting control**: The period status determines whether journal entries are accepted. Only periods in FUTURE_ENTERABLE or OPEN status allow postings, preventing accidental or unauthorized entries into periods that have been reconciled or reported
- **Five-state lifecycle granularity**: The NEVER_OPENED state distinguishes periods that have been defined but not yet activated from those that are FUTURE_ENTERABLE (accepting advance postings such as recurring journals or accruals). The distinction between CLOSED (reversible, allowing period reopening for adjustments) and PERMANENTLY_CLOSED (irreversible, enforcing hard cutoff for audited periods) gives finance teams flexibility while maintaining audit integrity
- **Fiscal year flexibility**: Support for non-calendar fiscal years (e.g., April-to-March, 4-4-5 week structures, 13-period years) ensures the system accommodates diverse organizational and jurisdictional requirements. A fiscal year is a logical grouping of periods scoped to a company, carrying a year name and start/end boundaries
- **Cross-module posting validation**: Upstream modules (purchase, sales, inventory, manufacturing) query the accounting period status before creating journal entries. This centralized validation ensures consistent enforcement of period restrictions across the entire ERP without duplicating temporal logic in each module
- **Period locking layers**: Periods can be locked incrementally — first for the accounting team (preventing routine postings while allowing supervisor adjustments), then fully closed, and finally permanently closed after external audit. This layered approach supports the month-end and year-end close workflow
- **Adjustment period support**: Special adjustment periods (period 13 or period 0) can be defined for year-end adjusting entries, audit adjustments, and closing entries without contaminating the regular operating periods
- **Compliance and audit trail**: Period status transitions are auditable events. Regulators and auditors rely on period locking to verify that reported financial statements were not altered after issuance. GAAP, IFRS, and local regulations require demonstrable period close controls
- **Company scoping**: Each fiscal year and its periods are isolated to a legal entity, supporting multi-entity deployments where subsidiaries may have different fiscal calendars and close schedules

## Process Flow

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

```mermaid
flowchart TD
    A[Define fiscal year for company] --> B[Generate accounting periods]
    B --> C[Periods created in NEVER_OPENED status]
    C --> D{Advance postings needed?}
    D -- Yes --> E[Transition to FUTURE_ENTERABLE]
    D -- No --> F[Transition directly to OPEN]
    E --> F[Transition to OPEN when period begins]
    F --> G[Accept journal postings]
    G --> H[Month-end reconciliation complete]
    H --> I[Close period]
    I --> J{Adjustments needed?}
    J -- Yes --> K[Reopen period]
    K --> G
    J -- No --> L{Audit finalized?}
    L -- No --> M[Period remains CLOSED]
    L -- Yes --> N[Permanently close period]
    N --> O[No further changes permitted]
```

## Scenario Patterns

- **Standard Monthly Close**: A company operates on a calendar fiscal year with 12 monthly periods. At month-end, the accounting team completes reconciliations, posts final accruals, and transitions the period from OPEN to CLOSED. After the external auditor reviews Q1, periods January through March are permanently closed
- **Non-Calendar Fiscal Year Setup**: A retailer with a February-to-January fiscal year (aligned to post-holiday reporting) defines a fiscal year starting February 1. Twelve monthly periods are generated with date boundaries matching the non-calendar cycle. Each period follows the same five-state lifecycle regardless of the calendar alignment
- **4-4-5 Week Period Structure**: A retail organization uses a 4-4-5 week fiscal calendar where each quarter consists of two 4-week periods followed by one 5-week period (13 periods per year). Custom period boundaries are defined rather than calendar month boundaries, and all period lifecycle rules apply identically
- **Advance Posting for Recurring Journals**: Before a new fiscal year begins, the controller transitions upcoming periods to FUTURE_ENTERABLE to allow automated recurring journal entries (e.g., monthly rent, depreciation) to be posted in advance. The periods remain in FUTURE_ENTERABLE until the actual period start date, when they transition to OPEN
- **Year-End Adjustment Period**: An adjustment period (period 13) is created for year-end closing entries and audit adjustments. This period shares the same end date as the final regular period but is designated as an adjustment type, isolating audit-related entries from operating activity
- **Period Reopen for Late Invoice**: After closing March, the AP team discovers an unrecorded vendor invoice dated March 15. The controller reopens March (CLOSED to OPEN), posts the invoice, and re-closes the period. This is only possible because March was not yet permanently closed
- **Multi-Entity Close Coordination**: A parent company with three subsidiaries coordinates period close across all entities. Each subsidiary's periods are independently managed — subsidiary A closes March on April 5, while subsidiary B closes on April 8 — reflecting their separate fiscal period scoping by companyId
- **Preventing Backdated Entries**: A sales team attempts to post a revenue entry to a permanently closed period to inflate prior-quarter results. The system rejects the posting because the period status is PERMANENTLY_CLOSED, enforcing financial statement integrity

## Test Cases

- Accounting period lifecycle follows NEVER_OPENED -> FUTURE_ENTERABLE -> OPEN -> CLOSED -> PERMANENTLY_CLOSED state machine
- Accounting period 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
- Transitioning a NEVER_OPENED period to FUTURE_ENTERABLE succeeds and allows advance postings
- Transitioning a NEVER_OPENED period directly to OPEN succeeds (skipping FUTURE_ENTERABLE)
- Transitioning a FUTURE_ENTERABLE period to OPEN succeeds
- Transitioning an OPEN period to CLOSED succeeds
- Transitioning a CLOSED period back to OPEN (reopen) succeeds
- Transitioning a CLOSED period to PERMANENTLY_CLOSED succeeds
- Transitioning a PERMANENTLY_CLOSED period to any other status is rejected with an irreversible status error
- Transitioning an OPEN period directly to PERMANENTLY_CLOSED (skipping CLOSED) is rejected with an invalid status transition error
- Transitioning a NEVER_OPENED period directly to CLOSED is rejected with an invalid status transition error
- Journal entries can be posted to a period in OPEN status
- Journal entries can be posted to a period in FUTURE_ENTERABLE status (advance postings)
- Journal entries are rejected when the target period is in NEVER_OPENED status
- Journal entries are rejected when the target period is in CLOSED status
- Journal entries are rejected when the target period is in PERMANENTLY_CLOSED status
- A period cannot be deleted if it has any associated journal entries regardless of status
- Reopening a CLOSED period emits an audit event recording the status transition and acting user
- Closing a period emits an audit event recording the status transition from OPEN to CLOSED
- Permanently closing a period emits an audit event recording the irreversible transition
- Creating a fiscal year with 12 monthly periods generates periods with correct start and end date boundaries
- Creating a fiscal year with 13 periods (adjustment period) generates 12 operating periods and 1 adjustment period
- Adjustment periods share the same end date as the final regular period but are typed as adjustment
- A non-calendar fiscal year (e.g., April-to-March) generates periods with correct non-calendar date boundaries
- Period status query returns the current status for a given date and company, enabling upstream modules to validate posting eligibility
- Periods are scoped to a company; period records from different companies are isolated
- Two periods in the same fiscal year cannot have identical start and end dates unless one is an adjustment period
- All period status transitions emit audit events via the audit module recording the acting user, timestamp, and previous and new status values

## Reference Links

- [Oracle Fusion Open and Close Periods](https://docs.oracle.com/en/cloud/saas/financials/24d/oafcf/manage-accounting-periods.html)
- [SAP S/4HANA Fiscal Year and Posting Periods](https://help.sap.com/docs/SAP_S4HANA_ON-PREMISE/ee3509643e954b3da2e0ebfa846c02e1/4cf37e593e3d2944e10000000a42189b.html)
- [Odoo Fiscal Year and Period Lock](https://www.odoo.com/documentation/19.0/applications/finance/accounting/get_started/opening.html)
- [NetSuite Accounting Period Management](https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_N1553839.html)
- [Oracle EBS Open and Close Periods Overview](https://docs.oracle.com/en/applications/jd-edwards/cross-application/9.2/eoagl/opening-and-closing-fiscal-periods.html)
