---
id: ATS-CRM-DQ-017
scope: CAP-CRM-DQ-017
product_area: crm
module: data-quality
revision: 1
status: proposed
source_sha:
  services-crm: a8d1364f1dd44b723bb5f9acba12f983e9ec8d69
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
scenarios:
  - id: ATS-CRM-DQ-017-01
    title: Hierarchy choices exclude cycle-producing parents
    level: unit
    proves:
      - BR-CAP-CRM-DQ-017-01
    preconditions: >-
      Participants include an ancestor/descendant pair and possible outside
      parents.
    steps: Build their plan.
    expected: >-
      Forbidden parents are absent, removed internal links are explained and
      children move to the survivor.
    negative: false
    data_needs: The existing scenario setup supplies the required records.
    bound_to:
      - >-
        services-crm:modules/merges/tests/unit/services/planning/organization-hierarchy.spec.js#leaves
        the survivor with no parent, because the two become one organization
      - >-
        services-crm:modules/merges/tests/unit/services/planning/organization-hierarchy.spec.js#says
        the link it removed would have made a cycle
      - >-
        services-crm:modules/merges/tests/unit/services/planning/organization-hierarchy.spec.js#offers
        both parents and clearing the parent
      - >-
        services-crm:modules/merges/tests/unit/services/planning/organization-hierarchy.spec.js#reports
        their reassignment to the survivor as a relationship action
    provenance: test
    source: >-
      services-crm:modules/merges/tests/unit/services/planning/organization-hierarchy.spec.js#leaves
      the survivor with no parent, because the two become one organization
    category: validation
    execution_sources:
      - >-
        services-crm:modules/merges/tests/unit/services/planning/organization-hierarchy.spec.js#leaves
        the survivor with no parent, because the two become one organization
      - >-
        services-crm:modules/merges/tests/unit/services/planning/organization-hierarchy.spec.js#says
        the link it removed would have made a cycle
      - >-
        services-crm:modules/merges/tests/unit/services/planning/organization-hierarchy.spec.js#offers
        both parents and clearing the parent
      - >-
        services-crm:modules/merges/tests/unit/services/planning/organization-hierarchy.spec.js#reports
        their reassignment to the survivor as a relationship action
    binding_note: >-
      The exact unit-test references remain bound as engineering evidence; unit
      files are not executable suite artifacts.
  - id: ATS-CRM-DQ-017-02
    title: Organization domains retain distinct alternatives
    level: unit
    proves:
      - BR-CAP-CRM-DQ-017-02
    preconditions: Participants have different primary and alternate domains.
    steps: Plan with each primary choice.
    expected: The remaining domains form the alternate union and flags combine.
    negative: false
    data_needs: The existing scenario setup supplies the required records.
    bound_to:
      - >-
        services-crm:modules/merges/tests/unit/services/planning/organization-fields.spec.js#unions
        every other distinct domain into the alternate domain names
      - >-
        services-crm:modules/merges/tests/unit/services/planning/organization-fields.spec.js#moves
        the chosen domain into the alternates when staff choose the other one
      - >-
        services-crm:modules/merges/tests/unit/services/planning/organization-fields.spec.js#unions
        every participant’s flags rather than choosing between them
    provenance: test
    source: >-
      services-crm:modules/merges/tests/unit/services/planning/organization-fields.spec.js#unions
      every other distinct domain into the alternate domain names
    category: rule
    execution_sources:
      - >-
        services-crm:modules/merges/tests/unit/services/planning/organization-fields.spec.js#unions
        every other distinct domain into the alternate domain names
      - >-
        services-crm:modules/merges/tests/unit/services/planning/organization-fields.spec.js#moves
        the chosen domain into the alternates when staff choose the other one
      - >-
        services-crm:modules/merges/tests/unit/services/planning/organization-fields.spec.js#unions
        every participant’s flags rather than choosing between them
    binding_note: >-
      The exact unit-test references remain bound as engineering evidence; unit
      files are not executable suite artifacts.
  - id: ATS-CRM-DQ-017-03
    title: Different types require review without a blocker
    level: unit
    proves:
      - BR-CAP-CRM-DQ-017-03
    preconditions: Participants have different organization types.
    steps: Compute their preview.
    expected: A type choice and warning appear without blocking the merge.
    negative: false
    data_needs: The existing scenario setup supplies the required records.
    bound_to:
      - >-
        services-crm:modules/merges/tests/unit/services/planning/organization-decisions.spec.js#asks
        which type the survivor keeps and warns that they may not be duplicates
        at all
    provenance: test
    source: >-
      services-crm:modules/merges/tests/unit/services/planning/organization-decisions.spec.js#asks
      which type the survivor keeps and warns that they may not be duplicates at
      all
    category: edge
    execution_sources:
      - >-
        services-crm:modules/merges/tests/unit/services/planning/organization-decisions.spec.js#asks
        which type the survivor keeps and warns that they may not be duplicates
        at all
    binding_note: >-
      The exact unit-test references remain bound as engineering evidence; unit
      files are not executable suite artifacts.
  - id: ATS-CRM-DQ-017-04
    title: Affiliations move and overlapping stays combine
    level: api
    proves:
      - BR-CAP-CRM-DQ-017-04
    preconditions: >-
      One employee belongs only to the absorbed organization and another belongs
      to both.
    steps: Execute.
    expected: >-
      No affiliation retains the absorbed organization and the equivalent stay
      combines into the survivor's affiliation.
    negative: false
    data_needs: The existing scenario setup supplies the required records.
    bound_to:
      - TST-CRM-DQ-181
    provenance: test
    source: >-
      services-crm:modules/merges/tests/integration/services/merges/organization-merge-execution.integration.spec.js#leaves
      no affiliation naming the organization that went
    category: transition
    execution_sources:
      - >-
        services-crm:modules/merges/tests/integration/services/merges/organization-merge-execution.integration.spec.js#leaves
        no affiliation naming the organization that went
      - >-
        services-crm:modules/merges/tests/integration/services/merges/organization-merge-execution.integration.spec.js#moves
        the affiliation of somebody who worked only at the organization that
        went
      - >-
        services-crm:modules/merges/tests/integration/services/merges/organization-merge-execution.integration.spec.js#combines
        the two stays of somebody who worked at both into the survivor’s own
        affiliation
  - id: ATS-CRM-DQ-017-05
    title: Affiliation writes enforce the ceiling
    level: unit
    proves:
      - BR-CAP-CRM-DQ-017-05
    preconditions: >-
      Prepare 100,000-row and 100,001-row plans plus a combination exceeding the
      limit.
    steps: Build the previews.
    expected: The boundary plan is allowed and both excessive variants are blocked.
    negative: true
    data_needs: The existing scenario setup supplies the required records.
    bound_to:
      - >-
        services-crm:modules/merges/tests/unit/services/planning/organization-decisions.spec.js#refuses
        a merge of 100,001 affiliations
      - >-
        services-crm:modules/merges/tests/unit/services/planning/organization-decisions.spec.js#plans
        a merge that writes exactly 100,000 affiliation rows without a blocker
      - >-
        services-crm:modules/merges/tests/unit/services/planning/organization-decisions.spec.js#refuses
        a merge whose affiliation rows rewritten and combined away pass the
        ceiling, though it moves fewer
    provenance: test
    source: >-
      services-crm:modules/merges/tests/unit/services/planning/organization-decisions.spec.js#refuses
      a merge of 100,001 affiliations
    category: boundary
    execution_sources:
      - >-
        services-crm:modules/merges/tests/unit/services/planning/organization-decisions.spec.js#refuses
        a merge of 100,001 affiliations
      - >-
        services-crm:modules/merges/tests/unit/services/planning/organization-decisions.spec.js#plans
        a merge that writes exactly 100,000 affiliation rows without a blocker
      - >-
        services-crm:modules/merges/tests/unit/services/planning/organization-decisions.spec.js#refuses
        a merge whose affiliation rows rewritten and combined away pass the
        ceiling, though it moves fewer
    binding_note: >-
      The exact unit-test references remain bound as engineering evidence; unit
      files are not executable suite artifacts.
  - id: ATS-CRM-DQ-017-06
    title: Employee links follow retained organization details
    level: api
    proves:
      - BR-CAP-CRM-DQ-017-06
    preconditions: >-
      Prepare links to kept and discarded slots and to an affiliation that
      combines.
    steps: Execute the plan.
    expected: >-
      Kept links remain, discarded slots and combined affiliations redirect
      appropriately and every change is recorded.
    negative: false
    data_needs: The existing scenario setup supplies the required records.
    bound_to:
      - TST-CRM-DQ-181
    provenance: test
    source: >-
      services-crm:modules/merges/tests/integration/services/merges/organization-merge-execution.integration.spec.js#re-points
      a link to a record that lost its slot to the record of its type the merge
      kept
    category: interaction
    execution_sources:
      - >-
        services-crm:modules/merges/tests/integration/services/merges/organization-merge-execution.integration.spec.js#re-points
        a link to a record that lost its slot to the record of its type the
        merge kept
      - >-
        services-crm:modules/merges/tests/integration/services/merges/organization-merge-execution.integration.spec.js#keeps
        a link to the record the merge kept pointing at it, now the survivor’s
      - >-
        services-crm:modules/merges/tests/integration/services/merges/organization-merge-execution.integration.spec.js#re-points
        a link through an affiliation a combination deleted to the affiliation
        it was combined into
  - id: ATS-CRM-DQ-017-07
    title: Preferred-address selection survives execution
    level: api
    proves:
      - BR-CAP-CRM-DQ-017-07
    preconditions: Two organizations prefer different address types.
    steps: Execute their chosen preview.
    expected: Only the address selected by the plan remains preferred.
    negative: false
    data_needs: The existing scenario setup supplies the required records.
    bound_to:
      - TST-CRM-DQ-181
    provenance: test
    source: >-
      services-crm:modules/merges/tests/integration/services/merges/organization-merge-preferred-address.integration.spec.js#carries
      the merge out, rather than failing on the preferred-address index
    category: invariant
    execution_sources:
      - >-
        services-crm:modules/merges/tests/integration/services/merges/organization-merge-preferred-address.integration.spec.js#carries
        the merge out, rather than failing on the preferred-address index
  - id: ATS-CRM-DQ-017-08
    title: Any added moved affiliation invalidates approval
    level: unit
    proves:
      - BR-CAP-CRM-DQ-017-09
    preconditions: Approve an organization plan whose dependent affiliations are identified.
    steps: >-
      Add a colliding affiliation, then separately add a non-colliding
      affiliation.
    expected: >-
      Both additions change the material fingerprint and require renewed
      approval.
    negative: false
    data_needs: The existing scenario setup supplies the required records.
    bound_to: []
    provenance: proposed
    source: FND-CRM-DQ-026
    category: concurrency
    execution_sources: []
  - id: ATS-CRM-DQ-017-09
    title: Organization combination works across the full console journey
    level: browser
    proves:
      - BR-CAP-CRM-DQ-017-01
      - BR-CAP-CRM-DQ-017-02
      - BR-CAP-CRM-DQ-017-04
      - BR-CAP-CRM-DQ-017-05
      - BR-CAP-CRM-DQ-017-06
    preconditions: 'Prepare children, employees, domains and linked details.'
    steps: >-
      Merge, attempt an oversized plan and combine an ancestor with its
      descendant.
    expected: >-
      Domains, hierarchy, people and links follow their choices; excessive size
      is refused and large work warns.
    negative: false
    data_needs: The existing scenario setup supplies the required records.
    bound_to: []
    provenance: proposed
    source: FND-CRM-DQ-031
    category: interaction
    execution_sources: []
  - id: ATS-CRM-DQ-017-10
    title: Organization execution refreshes computed status
    category: rule
    level: api
    proves:
      - BR-CAP-CRM-DQ-017-08
    preconditions: >-
      Organizations whose combined roles and locations change compliance and
      automatic region inputs.
    steps: >-
      Inspect the preview choices, execute and read the survivor after
      recomputation.
    expected: >-
      No choice asks for a computed compliance or region value; the survivor
      reflects recomputation from the merged records.
    negative: true
    data_needs: Run-owned records and caller permissions that distinguish the two cases.
    source: >-
      services-crm:modules/merges/tests/unit/services/planning/organization-fields.spec.js#never
      offers the contact role compliance status and recomputes it after the
      merge
    design_sources:
      - CAP-CRM-DQ-017
    bound_to: []
    provenance: proposed
    execution_sources: []
  - id: ATS-CRM-DQ-017-11
    title: Organization slot decisions preserve employee information
    category: interaction
    level: api
    proves:
      - BR-CAP-CRM-DQ-017-01
      - BR-CAP-CRM-DQ-017-02
      - BR-CAP-CRM-DQ-017-03
      - BR-CAP-CRM-DQ-017-04
      - BR-CAP-CRM-DQ-017-05
      - BR-CAP-CRM-DQ-017-06
      - BR-CAP-CRM-DQ-017-07
      - BR-CAP-CRM-DQ-017-09
      - BR-CAP-CRM-DQ-017-08
    exercises:
      - CAP-CRM-DQ-017
      - CAP-CRM-DQ-014
      - CAP-CRM-ENT-002
      - CAP-CRM-ENT-006
      - CAP-CRM-ENT-009
    workflow_sources:
      - WF-CRM-DQ-005
      - WF-CRM-DQ-006
    preconditions: >-
      Run-owned contact and organization records, the relevant staff permissions
      and the related state described by the sequence.
    steps: >-
      Merge parent-related organizations with overlapping employee affiliations
      and different address slots. Read each employee and the resulting
      hierarchy.
    expected: >-
      Employee links, merged stays and hierarchy obey the named rules while
      contact-owned information remains usable.
    negative: false
    data_needs: >-
      An isolated workspace with related records and fixed timestamps; owned
      participant failure injection where requested.
    source: >-
      CAP-CRM-DQ-017; CAP-CRM-DQ-014; CAP-CRM-ENT-002; CAP-CRM-ENT-006;
      CAP-CRM-ENT-009; WF-CRM-DQ-005; WF-CRM-DQ-006
    note: >-
      This cumulative seam scenario remains proposed until one executable
      sequence establishes all of its outcomes.
    bound_to: []
    provenance: proposed
    workflow_coverage_note: >-
      The workflows identify the handoffs under review. Separate assertions
      leave recovery and failure ordering unproved; the capability coverage
      finding records that limit.
    execution_sources: []
evidence:
  - repository: services-crm
    source_sha: a8d1364f1dd44b723bb5f9acba12f983e9ec8d69
    paths:
      - >-
        modules/merges/tests/integration/services/merges/organization-merge-execution.integration.spec.js
      - >-
        modules/merges/tests/integration/services/merges/organization-merge-preferred-address.integration.spec.js
      - >-
        modules/merges/tests/unit/services/planning/organization-decisions.spec.js
      - modules/merges/tests/unit/services/planning/organization-fields.spec.js
      - >-
        modules/merges/tests/unit/services/planning/organization-hierarchy.spec.js
    note: >-
      Bindings identify authored proof; empty bindings remain proposed and
      findings record known limitations.
  - repository: react-console
    source_sha: baf6dae382d6f41dce976c7f848667ccc37e076f
    paths:
      - acceptance/crm/playwright/journeys/merging/CRM-ACC-0270.spec.ts
      - acceptance/crm/playwright/journeys/merging/CRM-ACC-0271.spec.ts
      - acceptance/crm/playwright/journeys/merging/CRM-ACC-0282.spec.ts
    note: >-
      Bindings identify authored proof; empty bindings remain proposed and
      findings record known limitations.
coverage:
  rule: covered
  transition: covered
  validation: covered
  permission: 'gap: FND-CRM-DQ-068'
  edge: covered
  failure: 'gap: FND-CRM-DQ-068'
  boundary: covered
  concurrency: covered
  invariant: covered
  interaction: covered
coverage_notes:
  permission: >-
    No complete scenario currently isolates this category; the finding lists the
    remaining proof obligation.
  failure: >-
    No complete scenario currently isolates this category; the finding lists the
    remaining proof obligation.
permission_coverage:
  - key: crm.organizations.merge
    scenario_ids: []
    finding: FND-CRM-DQ-068
  - key: crm.organizations.read
    scenario_ids: []
    finding: FND-CRM-DQ-068
proof_matrix:
  - rule: BR-CAP-CRM-DQ-017-01
    scenarios:
      - ATS-CRM-DQ-017-01
      - ATS-CRM-DQ-017-09
      - ATS-CRM-DQ-017-11
  - rule: BR-CAP-CRM-DQ-017-02
    scenarios:
      - ATS-CRM-DQ-017-02
      - ATS-CRM-DQ-017-09
      - ATS-CRM-DQ-017-11
  - rule: BR-CAP-CRM-DQ-017-03
    scenarios:
      - ATS-CRM-DQ-017-03
      - ATS-CRM-DQ-017-11
  - rule: BR-CAP-CRM-DQ-017-04
    scenarios:
      - ATS-CRM-DQ-017-04
      - ATS-CRM-DQ-017-09
      - ATS-CRM-DQ-017-11
  - rule: BR-CAP-CRM-DQ-017-05
    scenarios:
      - ATS-CRM-DQ-017-05
      - ATS-CRM-DQ-017-09
      - ATS-CRM-DQ-017-11
  - rule: BR-CAP-CRM-DQ-017-06
    scenarios:
      - ATS-CRM-DQ-017-06
      - ATS-CRM-DQ-017-09
      - ATS-CRM-DQ-017-11
  - rule: BR-CAP-CRM-DQ-017-07
    scenarios:
      - ATS-CRM-DQ-017-07
      - ATS-CRM-DQ-017-11
  - rule: BR-CAP-CRM-DQ-017-08
    scenarios:
      - ATS-CRM-DQ-017-10
      - ATS-CRM-DQ-017-11
  - rule: BR-CAP-CRM-DQ-017-09
    scenarios:
      - ATS-CRM-DQ-017-08
      - ATS-CRM-DQ-017-11
interaction_coverage:
  related:
    - CAP-CRM-DQ-014
    - CAP-CRM-ENT-002
    - CAP-CRM-ENT-006
    - CAP-CRM-ENT-009
  workflow_sources:
    - WF-CRM-DQ-005
    - WF-CRM-DQ-006
  scenarios:
    - ATS-CRM-DQ-017-06
    - ATS-CRM-DQ-017-09
    - ATS-CRM-DQ-017-11
---

# Combine organizations and their connections safely: Capability Test Specification

## Coverage

The rule matrix names the authored checks. A covered category means that a scenario exists; it does not report a passing execution. The coverage notes and findings identify missing checks, while execution sources retain the exact assertions inspected.

| Required Rule | Scenarios |
|---|---|
| `BR-CAP-CRM-DQ-017-01` | `ATS-CRM-DQ-017-01`, `ATS-CRM-DQ-017-09`, `ATS-CRM-DQ-017-11` |
| `BR-CAP-CRM-DQ-017-02` | `ATS-CRM-DQ-017-02`, `ATS-CRM-DQ-017-09`, `ATS-CRM-DQ-017-11` |
| `BR-CAP-CRM-DQ-017-03` | `ATS-CRM-DQ-017-03`, `ATS-CRM-DQ-017-11` |
| `BR-CAP-CRM-DQ-017-04` | `ATS-CRM-DQ-017-04`, `ATS-CRM-DQ-017-09`, `ATS-CRM-DQ-017-11` |
| `BR-CAP-CRM-DQ-017-05` | `ATS-CRM-DQ-017-05`, `ATS-CRM-DQ-017-09`, `ATS-CRM-DQ-017-11` |
| `BR-CAP-CRM-DQ-017-06` | `ATS-CRM-DQ-017-06`, `ATS-CRM-DQ-017-09`, `ATS-CRM-DQ-017-11` |
| `BR-CAP-CRM-DQ-017-07` | `ATS-CRM-DQ-017-07`, `ATS-CRM-DQ-017-11` |
| `BR-CAP-CRM-DQ-017-08` | `ATS-CRM-DQ-017-10`, `ATS-CRM-DQ-017-11` |
| `BR-CAP-CRM-DQ-017-09` | `ATS-CRM-DQ-017-08`, `ATS-CRM-DQ-017-11` |

## Interactions With Related Capabilities

Execute the plan. Merge, attempt an oversized plan and combine an ancestor with its descendant. Merge parent-related organizations with overlapping employee affiliations and different address slots. Read each employee and the resulting hierarchy.

These sequences test the handoffs named in the interaction coverage record. A proposed sequence remains unbound until an executable run checks its combined outcome; component assertions alone leave that obligation open.
