---
id: WF-ACC-BKS-005
title: Extend Fiscal Calendar Coverage
trigger: A controller requests one or more additional fiscal years for a unit.
product_area: accounting
module: books
revision: 1
status: draft
design_intent: proposed
implementation_evidence: observed
inference: []
source_sha:
  services-accounting: f47cb263875bbc0c5640fba7dae6785ec32695f8
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
implements:
  - CAP-ACC-BKS-009
  - CAP-ACC-BKS-010
moves:
  - STATE-ACC-BKS-002
crosses: []
idempotency: >-
  Generation has no successful-repeat deduplication. A repeated successful
  request appends further years until the horizon guard refuses it.
concurrency: >-
  Generation locks the unit before reading the latest year and planning.
  Concurrent generations serialize, but this does not establish equivalent
  coordination with year deletion or period Close.
hops:
  - 'n': 1
    actor_or_service: Books service (transaction)
    action: Lock the unit and read its fixed fiscal starting month.
    anchor: >-
      services-accounting:modules/books/services/persistence/fiscal-years.ts:generateFiscalYears
    seam: sync
    on_failure: Refuse an unknown unit with a validation response.
    left_inconsistent: No year is inserted.
    observer: the caller
    provenance: observed
    source: >-
      services-accounting:modules/books/services/persistence/fiscal-years.ts:generateFiscalYears
  - 'n': 2
    actor_or_service: Books service (fiscal rules)
    action: >-
      Plan one to five complete years after existing coverage, refusing a
      request that exceeds the workspace-date horizon.
    anchor: >-
      services-accounting:modules/books/services/rules/fiscal-year-rules.ts:planFiscalYears
    seam: sync
    on_failure: Write no years if any planned start exceeds the allowed horizon.
    left_inconsistent: Even the otherwise eligible years remain unwritten.
    observer: the caller
    provenance: test
    source: >-
      services-accounting:modules/books/tests/integration/services/persistence/fiscal-years.integration.spec.js#writes
      none of the years, not even the years within reach
  - 'n': 3
    actor_or_service: Books service and database
    action: Insert each planned year and its twelve open periods in sequence.
    anchor: >-
      services-accounting:modules/books/services/persistence/fiscal-years.ts:generateFiscalYearsInTransaction
    seam: sync
    on_failure: >-
      Translate a recognized structural refusal and roll back every requested
      year.
    left_inconsistent: No partial extension survives.
    observer: the caller
    provenance: test
    source: >-
      services-accounting:modules/books/tests/integration/db/fiscal-years.table.integration.spec.js#refuses
      a year leaving a gap after the latest, in Rhythm 1.0’s sentence
  - 'n': 4
    actor_or_service: Database (commit)
    action: Check period completeness and commit the requested extension.
    anchor: >-
      services-accounting:modules/books/db/fiscal-years.table.ts:fiscal_years_periods_trigger
    seam: sync
    on_failure: Roll back the extension if committed calendar shape is invalid.
    left_inconsistent: The prior calendar remains intact.
    observer: the caller
    provenance: observed
    source: >-
      services-accounting:modules/books/db/fiscal-years.table.ts:fiscal_years_periods_trigger
  - 'n': 5
    actor_or_service: Recurring work that needed the coverage
    action: >-
      Let later work find the new months through ordinary period lookup;
      generation starts no scheduled work itself.
    anchor: 'services-accounting:modules/books/services/persistence/fiscal-periods.ts'
    seam: sync
    on_failure: >-
      Work outside coverage still fails its lookup; an owning schedule can
      record that failure and eventually pause.
    left_inconsistent: Generating coverage does not replay already failed occurrences.
    observer: The owner’s recorded run outcome and pause summary
    provenance: test
    source: >-
      services-accounting:modules/maintenance/tests/integration/services/scheduling/schedules-end-to-end.integration.spec.js#fails
      the roll dated in no fiscal year of the unit, with the sentence naming the
      date and the unit
branches: []
waits: []
evidence:
  - >-
    services-accounting at f47cb263:
    modules/books/services/persistence/fiscal-years.ts, fiscal-periods.ts;
    services/rules/fiscal-year-rules.ts; db/fiscal-years.table.ts,
    fiscal-periods.table.ts
  - >-
    react-console at baf6dae3:
    components/accounting-config/fiscal-years/generate-fiscal-year-dialog.tsx
controls: [TC-IAM-001, TC-IAM-002, TC-IAM-004, TC-IAM-005, TC-IAM-006, TC-AZ-001, TC-AZ-002, TC-AZ-003, TC-AZ-004, TC-AZ-005, TC-AZ-006, TC-TEN-001, TC-TEN-002, TC-TEN-003, TC-DAT-001, TC-DAT-004, TC-LOG-001, TC-LOG-002, TC-LOG-003, TC-LOG-004, TC-LOG-005, TC-PI-001, TC-PI-002, TC-PI-003]
---

# Extend Fiscal Calendar Coverage

## What It Does

Explicit generation adds complete monthly fiscal years for future dated work. It continues after the current latest year, or creates the year containing the workspace date when the calendar is empty. Period lookup and scheduled work do not generate coverage on demand.

## The Flow

```mermaid
flowchart TD
  h0["Lock the unit and read its fixed fiscal starting month."]
  h1["Plan one to five complete years after existing coverage, refusing a request that exceeds the workspace-date horizon."]
  h0 --> h1
  h2["Insert each planned year and its twelve open periods in sequence."]
  h1 --> h2
  h3["Check period completeness and commit the requested extension."]
  h2 --> h3
  h4["Let later work find the new months through ordinary period lookup; generation starts no scheduled work itself."]
  h3 --> h4
```

## When Something Fails

The requested extension is atomic. Invalid reach or calendar structure writes nothing. If a roll previously failed because coverage was missing, a later extension allows subsequent work to find a period but does not restart the failed occurrence. Repeating generation after an uncertain successful response can extend the calendar twice.

## Open Design Questions

There is no examined advance coverage warning. Calendar generation, deletion and Close also need a combined concurrency assessment.
