Skip to content

ATS-CRM-DQ-016Execute the approved merge atomically: Capability Test Specification

Markdown

ATS-CRM-DQ-016

Execute the approved merge atomically: Capability Test Specification

Markdown
  • DocumentProposed

Planning

Proves capability
CAP-CRM-DQ-016

Design

Executed by
TST-CRM-DQ-181, TST-CRM-DQ-183

KindAcceptance test setProduct areaCRMModuleDuplicate Review and Record MergingRevision1

Read atservices-crm a8d1364freact-console baf6dae3

Coverage

  • Rule covered
  • Transition covered
  • Validation covered
  • Permission gap: FND-CRM-DQ-067
  • Edge gap: FND-CRM-DQ-067
  • Failure covered
  • Boundary covered
  • Concurrency covered
  • Invariant covered
  • Interaction covered

Test Scenarios

38 scenarios proving CAP-CRM-DQ-016; 21 bound to an existing test.

01 An unready preview cannot executevalidationapinegativetest
Proves
BR-CAP-CRM-DQ-016-01
Preconditions
A plan has an unanswered required question.
Steps
Submit execution.
Expected
The service refuses readiness and names the question.
Data
The existing scenario setup supplies the required records.
Bound to
Source
services-crm:modules/merges/tests/e2e/merges.e2e.spec.js#refuses the execution request as a plan that is not ready
02 Execution rejects an approval with new dependent workvalidationapinegativetest
Proves
BR-CAP-CRM-DQ-016-02
Preconditions
A task arrives on an absorbed record after approval.
Steps
Execute with and without a supplied fingerprint, reopen the preview and execute again.
Expected
Both old approvals fail with the task change; renewed review permits execution.
Data
The existing scenario setup supplies the required records.
Bound to
Source
services-crm:modules/merges/tests/integration/services/merges/approval-binding.integration.spec.js#refuses the execution carrying the approved hash as plan_stale
03 Presentation changes leave approval material stableinvariantunittest
Proves
BR-CAP-CRM-DQ-016-03
Preconditions
Prepare previews differing only in wording, estimates or suggestions.
Steps
Compute their material fingerprints.
Expected
The fingerprints remain equal.
Data
The existing scenario setup supplies the required records.
Bound to
Source
services-crm:modules/merges/tests/integration/services/merges/lookup-labels.integration.spec.js#answers the same material hash, a name being no part of what staff are approving
04 Repeated confirmation returns the same durable workconcurrencyapitest
Proves
BR-CAP-CRM-DQ-016-04
Preconditions
A plan is ready.
Steps
Submit sequential and simultaneous executions.
Expected
One merge and job exist and repeat submissions report no creation.
Data
The existing scenario setup supplies the required records.
Bound to
Source
services-crm:modules/merges/tests/integration/services/merges/merge-settlement.integration.spec.js#answers both requests the same merge
05 Reconciliation settles jobs that never startedfailureapitest
Proves
BR-CAP-CRM-DQ-016-05
Preconditions
A queued merge has lost its job start.
Steps
Run reconciliation.
Expected
The job and merge record failure with an explanation and the plan reopens.
Data
The existing scenario setup supplies the required records.
Bound to
Source
services-crm:modules/merges/tests/integration/services/jobs/job-reconciliation.integration.spec.js#settles the job failed, rather than leaving it in flight for ever
06 Transaction failures leave no partial mergefailureapinegativetest
Proves
BR-CAP-CRM-DQ-016-06
Preconditions
Prepare stale-under-lock and participant-refusal cases.
Steps
Execute both.
Expected
Each failure is recorded without moved records or new aliases.
Data
The existing scenario setup supplies the required records.
Bound to
Source
services-crm:modules/merges/tests/integration/services/merges/approval-binding.integration.spec.js#fails the merge Stale inside its transaction rather than moving a task nobody approved
07 Overlapping merges have one winnerconcurrencyapinegativetest
Proves
BR-CAP-CRM-DQ-016-07
Preconditions
Two ready plans share a contact.
Steps
Run both concurrently.
Expected
One succeeds, the other names already-merged participants and its other survivor remains untouched.
Data
The existing scenario setup supplies the required records.
Bound to
Source
services-crm:modules/merges/tests/integration/services/merges/overlapping-merges.integration.spec.js#lets exactly one of the two merges happen
08 Locks prevent destructive combinationvalidationunitnegativetest
Proves
BR-CAP-CRM-DQ-016-08
Preconditions
Prepare a locked participant and a locked detail variant.
Steps
Build their plans.
Expected
Both variants are blocked.
Data
The existing scenario setup supplies the required records.
Bound to
services-crm:modules/merges/tests/unit/services/planning/merge-decisions.spec.js#blocks the merge when an element of a participant is locked
Source
services-crm:modules/merges/tests/unit/services/planning/merge-decisions.spec.js#blocks the merge when a participant is locked
09 Size limits distinguish refusal and a long-running warningboundaryunittest
Proves
BR-CAP-CRM-DQ-016-09
Preconditions
Prepare 100,001-row and 10,001-row plans.
Steps
Compute both.
Expected
The larger is blocked and the smaller is large with its duration and editing warning.
Data
The existing scenario setup supplies the required records.
Bound to
services-crm:modules/merges/tests/unit/services/planning/merge-decisions.spec.js#blocks a merge above the row ceiling of this release (decision D7)
services-crm:modules/merges/tests/unit/services/planning/merge-decisions.spec.js#calls an execution above ten thousand rows large, without blocking it
services-crm:modules/merges/tests/unit/services/planning/long-running-merge.spec.js#is raised for that plan, the execution class being the whole of the threshold
Source
services-crm:modules/merges/tests/unit/services/planning/merge-decisions.spec.js#blocks a merge above the row ceiling of this release (decision D7)
10 A failed attempt remains visible before a new attempttransitionapitest
Proves
BR-CAP-CRM-DQ-016-10
Preconditions
A participant refuses execution.
Steps
Read the restored plan and execute again.
Expected
The decisions remain and a different merge records the new attempt.
Data
The existing scenario setup supplies the required records.
Bound to
Source
services-crm:modules/merges/tests/integration/services/merges/merge-settlement.integration.spec.js#returns the plan to the status it had before it was executed, rather than leaving it executing
11 Successful merging adds record audit pointersruleapitest
Proves
BR-CAP-CRM-DQ-016-12
Preconditions
A merge has succeeded.
Steps
Read each participant's audit entry.
Expected
The pointers identify the requester, source record, survivor and time.
Data
The existing scenario setup supplies the required records.
Bound to
Source
services-crm:modules/merges/tests/integration/services/merges/merged-from-history.integration.spec.js#says who merged which record into which, and when: the merge pointer
12 Contact subscribers receive the committed outcomeinteractionapitest
Proves
BR-CAP-CRM-DQ-016-13
Preconditions
Register a contact-merge subscriber.
Steps
Execute the two-contact combination.
Expected
One workspace-scoped message identifies the survivor and absorbed identities without system fields.
Data
The existing scenario setup supplies the required records.
Bound to
Source
services-crm:modules/merges/tests/e2e/business-events.e2e.spec.js#sends one message for the merge, to the one subscriber, and deletes its queue row
13 Concurrent edits and duplicate submissions have explicit outcomesconcurrencybrowserproposed
Proves
BR-CAP-CRM-DQ-016-02 BR-CAP-CRM-DQ-016-04 BR-CAP-CRM-DQ-016-06 BR-CAP-CRM-DQ-016-07
Preconditions
An editor holds an absorbed record and two administrators prepare overlapping merges.
Steps
Edit around approval and execution, run competing merges and repeat confirmation.
Expected
Post-approval edits invalidate the preview, execution locks cause waits, one overlapping merge wins and repetition creates no duplicate.
Data
The existing scenario setup supplies the required records.
Source
FND-CRM-DQ-031
14 Duration estimates apply the measured row rateruleunittest
Proves
BR-CAP-CRM-DQ-016-15
Preconditions
Use touched-row totals of zero, 10,000 and 50,000.
Steps
Calculate the expected seconds for each total.
Expected
The estimates are one, eighteen and eighty-six seconds respectively.
Data
Use the records and caller described in this scenario.
Bound to
services-crm:modules/merges/tests/unit/services/planning/long-running-merge.spec.js#is one second for a merge that writes no rows at all, a merge that takes a moment still taking one
services-crm:modules/merges/tests/unit/services/planning/long-running-merge.spec.js#is eighteen seconds for the ten thousand rows a large execution begins above
services-crm:modules/merges/tests/unit/services/planning/long-running-merge.spec.js#is the minute and a half phase 4 measured for fifty thousand captured row changes
Source
services-crm:modules/merges/services/planning/merge-engine.ts:expectedMergeSeconds
15 Observe ready becoming executing after an execution request passes submission checkstransitionapiproposed
Proves
BR-CAP-CRM-DQ-016-01 BR-CAP-CRM-DQ-016-05
Preconditions
Arrange ready standing with the transition guard satisfied: Defaults are accepted, readiness and size checks pass, hashes match and participants remain available.
Steps
An execution request passes submission checks.
Expected
Read the executing standing and inspect the associated changes: atomically create the queued attempt and job; start workflow execution after commit.
Data
Fixtures for ready, the guard and the affected records; a fixed clock for time-dependent changes.
Source
services-crm:modules/merges/tests/integration/services/merges/approval-binding.integration.spec.js#refuses an execution that submits no hash too, because the stored plan is the one last shown
16 Observe executing becoming executed after successful execution commits the business transactiontransitionapiproposed
Proves
BR-CAP-CRM-DQ-016-06 INV-DOM-CRM-DQ-004-04
Preconditions
Arrange executing standing with the transition guard satisfied: The attempt holds its required participants under lock.
Steps
Successful execution commits the business transaction.
Expected
Read the executed standing and inspect the associated changes: mark the plan executed within that transaction.
Data
Fixtures for executing, the guard and the affected records; a fixed clock for time-dependent changes.
Source
services-crm:modules/merges/services/merges/merge-execution.ts:executeMerge
17 Observe executing becoming ready after executor or reconciliation settles a failed ready attempttransitionapiproposed
Proves
BR-CAP-CRM-DQ-016-10
Preconditions
Arrange executing standing with the transition guard satisfied: The plan remains executing and its prior preview was ready.
Steps
Executor or reconciliation settles a failed ready attempt.
Expected
Read the ready standing and inspect the associated changes: fail the attempt and reopen the plan atomically; retain decisions for the next recomputation.
Data
Fixtures for executing, the guard and the affected records; a fixed clock for time-dependent changes.
Source
services-crm:modules/merges/tests/integration/services/merges/merge-settlement.integration.spec.js#returns the plan to the status it had before it was executed, rather than leaving it executing
18 Observe executing becoming needs_decisions after failure settlement finds a different prior preview statetransitionapiproposed
Proves
BR-CAP-CRM-DQ-016-10
Preconditions
Arrange executing standing with the transition guard satisfied: The plan still has executing standing.
Steps
Failure settlement finds a different prior preview state.
Expected
Read the needs_decisions standing and inspect the associated changes: restore the stored working state or the fallback needing decisions.
Data
Fixtures for executing, the guard and the affected records; a fixed clock for time-dependent changes.
Source
services-crm:modules/merges/services/merges/merge-settlement.ts:statusBeforeExecution
19 Observe queued becoming running after the task begins the transaction and claims the queued attempttransitionapiproposed
Proves
INV-DOM-CRM-DQ-004-01 BR-CAP-CRM-DQ-016-05
Preconditions
Arrange queued standing with the transition guard satisfied: The conditional claim must still find queued standing.
Steps
The task begins the transaction and claims the queued attempt.
Expected
Read the running standing and inspect the associated changes: apply five-second lock and five-minute statement limits; acquire advisory and participant row locks in fixed order.
Data
Fixtures for queued, the guard and the affected records; a fixed clock for time-dependent changes.
Source
services-crm:modules/merges/services/merges/merge-execution.ts:executeMerge
20 Observe running becoming succeeded after the complete business transaction succeedstransitionapiproposed
Proves
BR-CAP-CRM-DQ-016-06
Preconditions
Arrange running standing with the transition guard satisfied: Replanning matches approval, participants exist, blockers clear, applications accept and the survivor validates.
Steps
The complete business transaction succeeds.
Expected
Read the succeeded standing and inspect the associated changes: settle the plan as executed; report completed job steps after commit; nudge committed contact event delivery.
Data
Fixtures for running, the guard and the affected records; a fixed clock for time-dependent changes.
Source
services-crm:modules/merges/tests/integration/services/merges/approval-binding.integration.spec.js#fails the merge Stale inside its transaction rather than moving a task nobody approved
21 Observe running becoming failed after execution catches a refusal or exceptiontransitionapinegativeproposed
Proves
BR-CAP-CRM-DQ-016-06
Preconditions
Arrange running standing with the transition guard satisfied: Conditional failure settlement still finds queued or running standing.
Steps
Execution catches a refusal or exception.
Expected
Read the failed standing and inspect the associated changes: store failure code and reason; reopen an eligible plan; report the mapped failed step and leave later steps queued.
Data
Fixtures for running, the guard and the affected records; a fixed clock for time-dependent changes.
Source
services-crm:modules/merges/tests/integration/services/merges/merge-settlement.integration.spec.js#returns the plan to the status it had before it was executed, rather than leaving it executing
22 Observe queued becoming failed after reconciliation closes an attempt whose job never completedtransitionapinegativeproposed
Proves
BR-CAP-CRM-DQ-016-05
Preconditions
Arrange queued standing with the transition guard satisfied: Settlement accepts only a still-unfinished attempt.
Steps
Reconciliation closes an attempt whose job never completed.
Expected
Read the failed standing and inspect the associated changes: record internal failure; reopen its eligible plan.
Data
Fixtures for queued, the guard and the affected records; a fixed clock for time-dependent changes.
Source
services-crm:modules/merges/services/jobs/record-merge-job.ts:markMergeFailedForLostJob
23 Observe running becoming failed after workflow failure handling or reconciliation settles unfinished executiontransitionapinegativeproposed
Proves
BR-CAP-CRM-DQ-016-05 INV-DOM-CRM-DQ-004-14
Preconditions
Arrange running standing with the transition guard satisfied: The attempt is queued or running when settlement obtains it.
Steps
Workflow failure handling or reconciliation settles unfinished execution.
Expected
Read the failed standing and inspect the associated changes: preserve existing executor failure or record internal failure; reopen its eligible plan.
Data
Fixtures for running, the guard and the affected records; a fixed clock for time-dependent changes.
Source
services-crm:modules/merges/services/merges/merge-settlement.ts:settleMergeAsFailed
24 An unanswered required conflict is identified on refusalinvariantapitest
Proves
INV-DOM-CRM-DQ-003-08
Preconditions
A preview with a required unanswered conflict.
Steps
Submit execution without answering it.
Expected
The response names the still-open conflict and queues no merge.
Data
Records, versions and caller contexts owned by the run; transaction failure injection when the invariant concerns rollback.
Bound to
Source
services-crm:modules/merges/tests/e2e/merges.e2e.spec.js#names the conflict that is still open, so a console can take the reader to it
25 An omitted client hash cannot bypass stale approvalinvariantapitest
Proves
INV-DOM-CRM-DQ-003-09
Preconditions
A reviewed plan followed by changed dependent work.
Steps
Submit execution without a client fingerprint.
Expected
The service still rejects the stale stored review and returns its changed material.
Data
Records, versions and caller contexts owned by the run; transaction failure injection when the invariant concerns rollback.
Bound to
Source
services-crm:modules/merges/tests/integration/services/merges/approval-binding.integration.spec.js#refuses an execution that submits no hash too, because the stored plan is the one last shown
26 A renamed display label does not change approval materialinvariantapitest
Proves
INV-DOM-CRM-DQ-003-10
Preconditions
A preview with a named lookup value and its material hash captured.
Steps
Rename the lookup label and replan.
Expected
The display changes while the material hash stays equal.
Data
Records, versions and caller contexts owned by the run; transaction failure injection when the invariant concerns rollback.
Bound to
Source
services-crm:modules/merges/tests/integration/services/merges/lookup-labels.integration.spec.js#answers the same material hash, a name being no part of what staff are approving
27 Simultaneous submissions return the same attemptinvariantapitest
Proves
INV-DOM-CRM-DQ-004-01
Preconditions
Two execution requests for one ready plan.
Steps
Submit both concurrently and compare their returned merge identities.
Expected
Both responses identify one merge and only one creates it.
Data
Records, versions and caller contexts owned by the run; transaction failure injection when the invariant concerns rollback.
Bound to
Source
services-crm:modules/merges/tests/integration/services/merges/merge-settlement.integration.spec.js#answers both requests the same merge
28 An attempt cannot absorb its own survivorinvariantapiproposed
Proves
INV-DOM-CRM-DQ-004-02
Preconditions
A direct merge row with the survivor included among absorbed records.
Steps
Attempt the database insertion.
Expected
The database refuses the invalid participant set.
Data
Records, versions and caller contexts owned by the run; transaction failure injection when the invariant concerns rollback.
Source
services-crm:modules/merges/db/record-merges.table.ts:record_merges_merged_ids_check
29 Terminal outcomes require their completion stampsinvariantapiproposed
Proves
INV-DOM-CRM-DQ-004-03
Preconditions
Direct rows with missing completion time or a mismatched failure code.
Steps
Attempt successful and failed rows with each incomplete terminal shape.
Expected
The database rejects the incomplete outcomes.
Data
Records, versions and caller contexts owned by the run; transaction failure injection when the invariant concerns rollback.
Source
services-crm:modules/merges/db/record-merges.table.ts:record_merges_failure_check
30 A stale-under-lock merge leaves the late task unmovedinvariantapitest
Proves
INV-DOM-CRM-DQ-004-04
Preconditions
A reviewed plan and a task added before locked execution replans.
Steps
Execute and read the task’s owner after refusal.
Expected
The merge fails as stale and the task still belongs to its original contact.
Data
Records, versions and caller contexts owned by the run; transaction failure injection when the invariant concerns rollback.
Bound to
Source
services-crm:modules/merges/tests/integration/services/merges/approval-binding.integration.spec.js#fails the merge Stale inside its transaction rather than moving a task nobody approved
31 Competing plans cannot both absorb their shared contactinvariantapitest
Proves
INV-DOM-CRM-DQ-004-05
Preconditions
Two ready plans sharing one participant.
Steps
Execute both concurrently and read each outcome.
Expected
Exactly one merge succeeds; the competing attempt reports the absorbed participant.
Data
Records, versions and caller contexts owned by the run; transaction failure injection when the invariant concerns rollback.
Bound to
Source
services-crm:modules/merges/tests/integration/services/merges/overlapping-merges.integration.spec.js#lets exactly one of the two merges happen
32 Record history names the requester and merge destinationinvariantapitest
Proves
INV-DOM-CRM-DQ-004-11
Preconditions
A successfully merged contact with captured audit entries.
Steps
Read the participant’s merge pointer.
Expected
The pointer identifies the requester, original contact, survivor and time.
Data
Records, versions and caller contexts owned by the run; transaction failure injection when the invariant concerns rollback.
Bound to
Source
services-crm:modules/merges/tests/integration/services/merges/merged-from-history.integration.spec.js#says who merged which record into which, and when: the merge pointer
33 A committed contact merge reaches its subscriberinvariantapitest
Proves
INV-DOM-CRM-DQ-004-12
Preconditions
A subscriber queue and a successful two-contact merge.
Steps
Run the merge and deliver the committed business event.
Expected
One subscriber message identifies the retained contact and absorbed identities.
Data
Records, versions and caller contexts owned by the run; transaction failure injection when the invariant concerns rollback.
Bound to
Source
services-crm:modules/merges/tests/e2e/business-events.e2e.spec.js#hands the subscriber the envelope of crm.contact.merged, about the survivor, in the merge’s tenant
34 Repeated submission cannot create another jobinvariantapiproposed
Proves
INV-DOM-CRM-DQ-004-13
Preconditions
A queued merge with its durable job already created.
Steps
Submit the same merge job again and inspect the root and step rows.
Expected
One job and one set of its watched steps remain.
Data
Records, versions and caller contexts owned by the run; transaction failure injection when the invariant concerns rollback.
Source
services-crm:modules/merges/db/record-merge-jobs.table.ts:record_merge_jobs_merge_uidx, record_merge_jobs_customer_id_check; modules/merges/services/merges/merge-plans.ts:queueTheMergeOfThisPlan
35 Business refusal is settled instead of retried as transport failureinvariantapiproposed
Proves
INV-DOM-CRM-DQ-004-14
Preconditions
A participant refusal and a separate transient task exception.
Steps
Execute the workflow with each failure and inspect the task retry and terminal handling.
Expected
The refusal produces the settled failed attempt; only the eligible transient task exception enters the retry path.
Data
Records, versions and caller contexts owned by the run; transaction failure injection when the invariant concerns rollback.
Source
services-crm:modules/merges/services/jobs/record-merge-job.ts:recordMergeWorkflow
36 Retry distinguishes transient task failure from refusalruleapinegativeproposed
Proves
BR-CAP-CRM-DQ-016-11
Preconditions
One ready merge with an injected transient task error and another with a refusing participant.
Steps
Run each workflow and inspect the retry attempts and settlement.
Expected
Only the eligible task error is retried; the refusal is recorded as a business failure.
Data
Run-owned records and caller permissions that distinguish the two cases.
Source
services-crm:modules/merges/services/jobs/record-merge-job.ts:recordMergeWorkflow
37 Confirmation and polling retain a readable execution outcomerulebrowsernegativeproposed
Proves
BR-CAP-CRM-DQ-016-14
Preconditions
A ready plan with dropped values, a delayed execution and an administrator.
Steps
Open confirmation, inspect participant labels and irreversibility, acknowledge the dropped values, submit and advance the clock beyond thirty seconds; leave and return.
Expected
The confirmation identifies what is kept and absorbed, and polling changes from one-second to five-second intervals; the result remains available after returning.
Data
Run-owned records and caller permissions that distinguish the two cases.
Source
react-console:acceptance/crm/playwright/journeys/merging/CRM-ACC-0253.spec.ts#CRM-ACC-0253
38 A completed organization merge agrees with aliases and historyinteractionapiproposed
Proves
BR-CAP-CRM-DQ-016-01 BR-CAP-CRM-DQ-016-02 BR-CAP-CRM-DQ-016-03 BR-CAP-CRM-DQ-016-04 BR-CAP-CRM-DQ-016-05 BR-CAP-CRM-DQ-016-06 BR-CAP-CRM-DQ-016-07 BR-CAP-CRM-DQ-016-08 BR-CAP-CRM-DQ-016-09 BR-CAP-CRM-DQ-016-10 BR-CAP-CRM-DQ-016-12 BR-CAP-CRM-DQ-016-13 BR-CAP-CRM-DQ-016-15 BR-CAP-CRM-DQ-016-11 BR-CAP-CRM-DQ-016-14
Preconditions
Run-owned contact and organization records, the relevant staff permissions and the related state described by the sequence.
Steps
Approve and execute an organization merge, read the surviving affiliations, follow every absorbed identity and open the recorded outcome.
Expected
The successful attempt, alias destinations and retained history describe the same committed change.
Data
An isolated workspace with related records and fixed timestamps; owned participant failure injection where requested.
Source
CAP-CRM-DQ-016; CAP-CRM-DQ-017; CAP-CRM-DQ-018; CAP-CRM-DQ-019; WF-CRM-DQ-006; WF-CRM-DQ-007

The Markdown files under specs/ in rhythmsoftware/rhythm-v2-docs are the canonical source of truth. This reader is a generated, read-only projection of them.