---
id: STATE-ACC-BKS-001
title: Business unit lifecycle
object: DOM-ACC-BKS-001
product_area: accounting
module: books
revision: 1
status: draft
design_intent: proposed
implementation_evidence: observed
source_sha:
  services-accounting: f47cb263875bbc0c5640fba7dae6785ec32695f8
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
states:
  - name: absent
    meaning: The workspace has no unit with this code.
  - name: active
    meaning: >-
      The unit is available in active-only selectors; this flag is not a general
      prohibition on financial service work.
  - name: inactive
    meaning: 'The record remains stored, but active-only choices omit it.'
  - name: deleted
    meaning: The unit and eligible owned configuration have been physically removed.
transitions:
  - from: absent
    to: active
    trigger: Create an active unit
    guard: >-
      Required founding fields and identifier are valid; the supported set and
      any supplied fee-product selection pass their checks
    side_effects:
      - Insert the base-currency row through the database trigger
      - Write the requested supported currencies
      - Generate two initial years with twelve open periods each
    who: Administrator with unit creation permission
    provenance: test
    source: >-
      services-accounting:modules/books/tests/integration/services/persistence/fiscal-years.integration.spec.js#gives
      the new unit exactly its two years, the one containing today and the next
  - from: absent
    to: inactive
    trigger: Create an inactive unit
    guard: The creation checks also apply when availability is false
    side_effects:
      - >-
        Create the same currency setup and initial calendar as for active
        creation
    who: Administrator with unit creation permission
    provenance: observed
    source: >-
      services-accounting:modules/books/services/persistence/business-units.ts:createBusinessUnit
  - from: active
    to: inactive
    trigger: Deactivate the unit
    guard: >-
      The loaded version is current, updates are not locked and founding values
      are unchanged
    side_effects:
      - Remove the unit from active-only selections
    who: Administrator with unit update permission
    provenance: observed
    source: >-
      services-accounting:modules/books/services/persistence/business-units.ts:updateBusinessUnit
  - from: inactive
    to: active
    trigger: Reactivate the unit
    guard: 'The replacement passes version, lock and fixed-value checks'
    side_effects:
      - Offer the unit in active-only choices again
    who: Administrator with unit update permission
    provenance: observed
    source: >-
      services-accounting:modules/books/services/persistence/business-units.ts:updateBusinessUnit
  - from: active
    to: deleted
    trigger: Remove an active unit
    guard: >-
      No lock or restricting dependency prevents deletion; accounts and projects
      must be gone
    side_effects:
      - >-
        Cascade eligible owned currency rows, defaults, departments and calendar
        records
    who: Administrator with unit deletion permission
    provenance: test
    source: >-
      services-accounting:modules/books/tests/integration/services/persistence/business-units.integration.spec.js#refuses
      a unit with GL, bank and merchant accounts, naming all three
  - from: inactive
    to: deleted
    trigger: Remove an inactive unit
    guard: The same dependency and lock checks apply to inactive records
    side_effects:
      - Apply the same owned-record cascades as active deletion
    who: Administrator with unit deletion permission
    provenance: observed
    source: >-
      services-accounting:modules/books/services/persistence/business-units.ts:deleteBusinessUnit
invalid:
  - from: active
    to: active
    why: >-
      A same-state edit is allowed, but changing the base currency or fiscal
      boundary is refused with the offending field.
  - from: deleted
    to: active
    why: >-
      Physical deletion does not restore the earlier unit; creation under a free
      code produces a new record.
  - from: inactive
    to: deleted
    why: >-
      Deactivation preserves dependencies, so it does not make a referenced unit
      eligible for deletion.
concurrency: >-
  Replacement and deletion lock the unit row. Expected-version replacement
  prevents ordinary lost edits, and foreign keys coordinate currency removal
  with new references. The method-change guard performs a plain read of
  current-period batches and can miss concurrent posting.
invariants:
  - INV-DOM-ACC-BKS-001-01
  - INV-DOM-ACC-BKS-001-02
  - INV-DOM-ACC-BKS-001-08
evidence:
  - >-
    services-accounting at f47cb263:
    modules/books/services/persistence/business-units.ts (create, update,
    delete, lockBusinessUnit, assertAccountingMethodChangeable)
  - >-
    react-console at baf6dae3: components/configuration/standard.tsx (row and
    bulk activate, deactivate and delete)
---

# Business unit lifecycle

## The Lifecycle

```mermaid
stateDiagram-v2
  state "absent" as s0
  state "active" as s1
  state "inactive" as s2
  state "deleted" as s3
  s0 --> s1: Create an active unit
  s0 --> s2: Create an inactive unit
  s1 --> s2: Deactivate the unit
  s2 --> s1: Reactivate the unit
  s1 --> s3: Remove an active unit
  s2 --> s3: Remove an inactive unit
```

## Transitions Explained

Units default to active and can also be created inactive. Creation commits the currency setup and two initial fiscal years together. Availability changes are ordinary record replacements; row and bulk console actions use the same single-record operation.

Removal is physical. Accounts and projects must be removed first, and other restricting references can still block the owned cascades. A freed code can identify a later new unit without restoring the original record.

## What Cannot Happen

Founding currency and fiscal boundary do not change through an update. Deactivation retains the configuration and its dependencies. Calendar coverage is atomic at creation, but subsequent eligible year deletion can remove the initial years.

## Concurrency and Timing

A stale replacement is refused. Record locks protect their stated operations. Currency foreign keys constrain racing references, while the accounting-method guard has no equivalent lock on the batches it counts.
