---
id: CAP-CRM-REG-010
title: Identify placements that need recalculation
feature: FEAT-CRM-REG-04
product_area: crm
module: regions
revision: 2
status: draft
product_intent: proposed
implementation_evidence: observed
supersedes:
  - CAP-CRM-CFG-016
source_sha:
  services-crm: a8d1364f1dd44b723bb5f9acba12f983e9ec8d69
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
intent_sources:
  - >-
    services-crm:docs/migrations/crm-regions/README.md#2026-10-08 — Final acceptance (decision 2026-10-08,
    Andrew: saving rules changes no record; staff press Recalculate)
  - >-
    services-crm:docs/migrations/crm-regions/README.md#2026-10-12 — Final acceptance (second pass), decision
    2026-10-11: rule or setting changes move no record; manual Recalculate with a recalculation-needed banner
  - >-
    services-crm:docs/migrations/crm-regions/README.md#2026-10-15 — Final acceptance (console follow-ups)
    (Andrew approved 2026-10-15: two tabs, Test an Address dialog, drawers, a read-only Assignment Rules tab
    with its own editor screen and the banner)
purpose: >-
  Staff distinguish records placed under earlier settings from records brought into line with the current
  policy.
outcomes:
  - Policy changes leave existing placement intact until recalculation.
  - Staff receive a signal when the current policy generation lacks a successful run.
concepts:
  - CON-CRM-REG-002
  - CON-CRM-REG-004
actors:
  - ACT-CRM-003
  - ACT-CRM-002
surfaces:
  - console
  - api
preconditions: []
postconditions: []
permissions:
  - key: crm.regions.read
    where_checked: api
    scope: tenant
rules:
  - id: BR-CAP-CRM-REG-010-01
    proved_by: [ATS-CRM-REG-003-08, ATS-CRM-REG-010-01, TST-CRM-REG-006, TST-CRM-REG-058, TST-CRM-REG-066]
    statement: >-
      Saving assignment settings or rules leaves contact and organization placements unchanged until staff run
      recalculation.
    kind: policy
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-crm:modules/regions/tests/integration/services/region-assignment/region-assignment.integration.spec.js#rule
      changes and the recalculation › changes no record when the rules are saved
    origin: >-
      services-crm:docs/migrations/crm-regions/README.md#2026-10-08 — Final acceptance (decision 2026-10-08,
      Andrew: saving rules changes no record; staff press Recalculate)
  - id: BR-CAP-CRM-REG-010-02
    proved_by: [ATS-CRM-REG-010-02, ATS-CRM-REG-010-08, ATS-CRM-REG-011-10, ATS-CRM-REG-012-07, TST-CRM-REG-045, TST-CRM-REG-051, TST-CRM-REG-057]
    statement: >-
      With assignment enabled, recalculation is needed after policy changes beyond the generation of a
      successful run or when no run has succeeded.
    kind: calculation
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-crm:modules/regions/tests/integration/services/region-assignment/region-assignment-rules.integration.spec.js#whether
      a recalculation is needed › says a recalculation is needed once the rules have been saved and nothing
      has recalculated
    origin: >-
      services-crm:docs/migrations/crm-regions/README.md#2026-10-12 — Final acceptance (second pass), decision
      2026-10-11: rule or setting changes move no record; manual Recalculate with a recalculation-needed
      banner
  - id: BR-CAP-CRM-REG-010-03
    proved_by: [ATS-CRM-REG-002-07, ATS-CRM-REG-003-09, ATS-CRM-REG-005-08, ATS-CRM-REG-010-03, ATS-CRM-REG-010-08, TST-CRM-REG-010, TST-CRM-REG-057]
    statement: >-
      Settings saves, individual-rule writes and deactivation of targets referenced by enabled rules increment
      the policy change count.
    kind: calculation
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-crm:modules/regions/tests/integration/services/region-assignment/region-assignment-rules.integration.spec.js#whether
      a recalculation is needed › says one is needed again as soon as a rule is added
    origin: none
  - id: BR-CAP-CRM-REG-010-04
    proved_by: [ATS-CRM-REG-010-04, TST-CRM-REG-057]
    statement: A policy change committed during a run leaves recalculation needed after that run completes.
    kind: calculation
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-crm:modules/regions/tests/integration/services/region-assignment/region-assignment-rules.integration.spec.js#whether
      a recalculation is needed › a rule saved while a recalculation is under way › says one is still needed,
      because the run was recorded under the rules as they were before
    origin: >-
      services-crm:docs/migrations/crm-regions/README.md#2026-10-12 — Final acceptance (second pass), decision
      2026-10-11: rule or setting changes move no record; manual Recalculate with a recalculation-needed
      banner
  - id: BR-CAP-CRM-REG-010-05
    proved_by: [ATS-CRM-REG-010-05, TST-CRM-REG-057]
    statement: >-
      Recalculation need compares generation counts rather than timestamps, recognizing changes even at the
      same instant as a run starts.
    kind: calculation
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-crm:modules/regions/tests/integration/services/region-assignment/region-assignment-rules.integration.spec.js#whether
      a recalculation is needed › a rule change stamped at the very instant the last run started › says one is
      needed after a rule is added at the very instant the run started
    origin: none
  - id: BR-CAP-CRM-REG-010-06
    proved_by: [ATS-CRM-REG-003-09, ATS-CRM-REG-010-06, TST-CRM-REG-051]
    statement: Disabled assignment and workspaces without saved settings do not request recalculation.
    kind: calculation
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-crm:modules/regions/tests/integration/services/persistence/region-assignment-settings.queries.integration.spec.js#a
      tenant that has saved no settings › says no recalculation is needed, because a tenant with no settings
      assigns nothing to recalculate
    origin: none
  - id: BR-CAP-CRM-REG-010-07
    proved_by: []
    statement: Settings reads include the time of the most recent recorded policy change.
    kind: policy
    enforced_at:
      - service
    must_prove: false
    provenance: test
    source: >-
      services-crm:modules/regions/tests/integration/services/persistence/region-assignment-settings.queries.integration.spec.js#the
      settings of a tenant that saved them › answers the moment the rules last changed, which is the save that
      wrote them
    origin: none
  - id: BR-CAP-CRM-REG-010-08
    proved_by: [ATS-CRM-REG-010-07, ATS-CRM-REG-010-09]
    statement: An unchanged settings replacement still increments the policy change count.
    kind: calculation
    enforced_at:
      - service
    must_prove: true
    provenance: observed
    source: >-
      services-crm:modules/regions/services/persistence/region-assignment-settings.ts:saveRegionAssignmentSettings
    origin: none
  - id: BR-CAP-CRM-REG-010-09
    proved_by: []
    statement: >-
      The Assignment Rules tab displays a recalculation-needed banner with its own action when required and
      omits it otherwise.
    kind: policy
    enforced_at:
      - console
    must_prove: false
    provenance: test
    source: >-
      react-console:components/regions/__tests__/recalculation.test.tsx#the banner › asks for a recalculation
      and carries the button to run it
    origin: >-
      services-crm:docs/migrations/crm-regions/README.md#2026-10-15 — Final acceptance (console follow-ups)
      (Andrew approved 2026-10-15: two tabs, Test an Address dialog, drawers, a read-only Assignment Rules tab
      with its own editor screen and the banner)
  - id: BR-CAP-CRM-REG-010-10
    proved_by: []
    statement: 'With automatic assignment disabled, the console neither requests nor offers recalculation.'
    kind: policy
    enforced_at:
      - console
    must_prove: false
    provenance: test
    source: >-
      react-console:components/regions/__tests__/rules-tab.test.tsx#the Assignment Rules tab while assignment
      is off › does not ask for a recalculation of records nothing is assigning
    origin: none
scenarios:
  - id: SC-CAP-CRM-REG-010-01
    given: The current policy has a successful recalculation.
    when: An administrator adds and saves another rule.
    then: Existing placements remain and recalculation becomes needed.
    provenance: test
    source: >-
      react-console:e2e/dev/regions.dev.spec.ts#asks for a recalculation after a rule changes, and stops
      asking once it has run
edge_cases:
  - id: SC-CAP-CRM-REG-010-02
    given: A recalculation is processing existing records.
    when: An administrator changes the policy before completion.
    then: The completed run does not clear the need for another recalculation.
    provenance: test
    source: >-
      services-crm:modules/regions/tests/integration/services/region-assignment/region-assignment-rules.integration.spec.js#whether
      a recalculation is needed › a rule saved while a recalculation is under way › says one is still needed,
      because the run was recorded under the rules as they were before
constraints: []
depends_on:
  - CAP-CRM-REG-003
related:
  - CAP-CRM-REG-002
  - CAP-CRM-REG-003
  - CAP-CRM-REG-004
  - CAP-CRM-REG-005
  - CAP-CRM-REG-011
journeys:
  - JNY-CRM-REG-002
open_questions: []
evidence:
  - >-
    services-crm: Examined the pinned regional implementation, its declared constraints and the supporting
    records.
  - 'react-console: Examined the pinned regional configuration surfaces and their available test evidence.'
  - 'services-crm:docs/migrations/crm-regions/README.md'
  - >-
    services-crm:modules/regions/tests/integration/services/region-assignment/region-assignment.integration.spec.js
  - >-
    services-crm:modules/regions/tests/integration/services/region-assignment/region-assignment-rules.integration.spec.js
  - >-
    services-crm:modules/regions/tests/integration/services/persistence/region-assignment-settings.queries.integration.spec.js
  - 'services-crm:modules/regions/services/persistence/region-assignment-settings.ts'
  - 'react-console:components/regions/__tests__/recalculation.test.tsx'
  - 'react-console:components/regions/__tests__/rules-tab.test.tsx'
  - 'react-console:e2e/dev/regions.dev.spec.ts'
controls: [TC-AZ-001, TC-AZ-002, TC-AZ-003, TC-AZ-004, TC-AZ-006, TC-DAT-001, TC-DAT-002, TC-DAT-003, TC-LOG-004, TC-LOG-005, TC-PI-001, TC-PRV-001, TC-PRV-002, TC-TEN-001, TC-TEN-002, TC-TEN-003]
exercised_by: [FAS-CRM-REG-04-01, FAS-CRM-REG-04-02, FAS-CRM-REG-04-03, FAS-CRM-REG-04-04, FAS-CRM-REG-04-05]
suites: [TST-CRM-REG-006, TST-CRM-REG-010, TST-CRM-REG-045, TST-CRM-REG-051, TST-CRM-REG-057, TST-CRM-REG-058, TST-CRM-REG-066]
---

# Identify placements that need recalculation

## Purpose

Staff distinguish records placed under earlier settings from records brought into line with the current policy.

## How It Works

Saving a policy records a change without moving existing records. The settings read compares its policy generation with successful recalculations. The console uses the resulting signal to show a banner on the Assignment Rules tab. A successful run clears that signal only if its recorded generation covers the current policy. A rule changed during processing leaves the signal set after completion. Counting generations recognizes changes that share a timestamp with the start of a run. An unchanged settings save still raises the count and can request unnecessary recalculation. Disabled assignment suppresses the request. Staff use the explicit recalculation action to bring older placements into line.

## Relationships

- Configure automatic placement and its address sources establishes participation and address-source choices for placement.
- Retire regions while preserving their references handles retirement and reference-sensitive removal of regional definitions.
- Build the geographic assignment policy maintains the geographic policy that other regional workflows evaluate.
- Maintain individual rules alongside the shared policy provides individual-rule API maintenance alongside whole-policy editing.
- Apply the current policy across existing records applies policy changes to existing records.
