Skip to content

ATS-CRM-ENT-004Save corrections without overwriting another change

Markdown

ATS-CRM-ENT-004

Save corrections without overwriting another change

Markdown
  • DocumentProposed

KindAcceptance test setProduct areaCRMModuleEntitiesRevision2

Read atservices-crm a8d1364freact-console baf6dae3

Coverage

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

Test Scenarios

23 scenarios proving CAP-CRM-ENT-004; 11 bound to an existing test.

01 Writes need the version read; stale writes are conflicts that name the changeconcurrencyapinegativetest
Proves
BR-CAP-CRM-ENT-004-01 INV-DOM-CRM-ENT-033-01
Preconditions
Prepare a contact at version n.
Steps
PUT without sys_version; PATCH without a test; two patches at n; a PUT at n after a colleague saved.
Expected
400 naming sys_version twice; the second patch 409 with the first value preserved; 409 record_changed naming the colleague.
Data
No additional fixtures.
Bound to
Source
services-crm:modules/entities/tests/e2e/contacts.e2e.spec.js#answers 400 naming sys_version to a patch that tests no version
02 an unmodified save changes nothinginvariantbrowsertest
Proves
BR-CAP-CRM-ENT-004-02 INV-DOM-CRM-ENT-033-02
Preconditions
Prepare a stored contact.
Steps
Replace it with exactly what was read; then with a stale version.
Expected
Same version, stamp and no revision; the stale one rejected.
Data
No additional fixtures.
Bound to
Source
services-crm:modules/entities/tests/integration/services/persistence/record-saves.no-op.integration.spec.js#writes no revision
03 a patch changes what it names and null clearsruleapitest
Proves
BR-CAP-CRM-ENT-004-03
Preconditions
Prepare a contact with a job title and two phones.
Steps
Patch replace one field, edit one element, add one, remove one, then remove a field.
Expected
Each change applied, others untouched, version advanced.
Data
No additional fixtures.
Bound to
Source
services-crm:modules/entities/tests/e2e/contacts.e2e.spec.js#sets the field the patch replaced and bumps the version
04 a replacement clears what it omits, except affiliations and custom valuesedgebrowsertest
Proves
BR-CAP-CRM-ENT-004-04
Preconditions
Prepare a contact with addresses, affiliations and custom values.
Steps
Replace it without a field, without addresses, without affiliations, without custom_fields.
Expected
Field cleared, addresses emptied, affiliations and custom values preserved.
Data
No additional fixtures.
Bound to
Source
services-crm:modules/entities/tests/integration/services/persistence/contacts.integration.spec.js#empties the collection
05 Elements keep their ids; foreign or repeated ids are rejected; types can swapinvariantapinegativetest
Proves
BR-CAP-CRM-ENT-004-05
Preconditions
Prepare a contact with home and work addresses.
Steps
Replace with home edited and work omitted; with an element id of another contact; with one id twice; swap two types.
Expected
Home preserved under its id at version 2, work removed; 400 naming the element; 400; swap accepted.
Data
Use two contacts.
Bound to
Source
services-crm:modules/entities/tests/integration/services/persistence/contacts.integration.spec.js#moves the second address into the type the first left, and the preferred flag with it
06 Read-only fields: unmodified ignored, changed rejectedvalidationbrowsernegativetest
Proves
BR-CAP-CRM-ENT-004-06
Preconditions
Prepare a contact and an organization as read.
Steps
Send each back complete; then with a changed full name, number or origin.
Expected
Unchanged read-only values are accepted, changed values are rejected, and derived ancestry and compliance values are ignored.
Data
No additional fixtures.
Bound to
Source
services-crm:modules/entities/tests/integration/services/persistence/contacts.field-rules.integration.spec.js#refuses a replacement whose contact number differs from the stored one, naming number
07 a rejected save leaves every row as it wasfailureapinegativetest
Proves
BR-CAP-CRM-ENT-004-07 INV-DOM-CRM-ENT-033-03
Preconditions
Prepare a contact with elements.
Steps
Replace it with an element of another contact.
Expected
Rejected; the contact row rolled back and every element as it was.
Data
No additional fixtures.
Bound to
Source
services-crm:modules/entities/tests/integration/services/persistence/contacts.integration.spec.js#rolls back the contact row the transaction had already updated
08 Every problem at oncevalidationapinegativetest
Proves
BR-CAP-CRM-ENT-004-08
Preconditions
No additional setup is required.
Steps
Create an organization that is its own parent with two preferred addresses.
Expected
One refusal listing both.
Data
No additional fixtures.
Bound to
Source
services-crm:modules/entities/tests/integration/services/persistence/organizations.integration.spec.js#refuses the create as ObjectInvalid, listing both problems
09 Strings are trimmed and blanks are nothingrulebrowsertest
Proves
BR-CAP-CRM-ENT-004-09
Preconditions
No additional setup is required.
Steps
Send a blank e-mail element, a padded name, an empty-string name.
Expected
Element dropped; name trimmed; required name rejected.
Data
No additional fixtures.
Bound to
Source
services-crm:modules/entities/tests/unit/api/contact-api-mapper.spec.js#drops a blank e-mail element rather than refusing the null the string standard made of it
10 a system change is a conflict naming the systeminteractionbrowsernegativetest
Proves
BR-CAP-CRM-ENT-004-10
Preconditions
Prepare a contact read by an editor; its spouse then deleted.
Steps
The editor saves at the version read.
Expected
409 naming the system.
Data
No additional fixtures.
Bound to
Source
services-crm:modules/entities/tests/e2e/contacts.e2e.spec.js#answers 409 naming the system, not a colleague, when the system cleared the spouse link while the contact was edited (M1-D6)
11 the editor patches only what changed and handles conflicts safelyconcurrencybrowsernegativetest
Proves
BR-CAP-CRM-ENT-004-11
Preconditions
Prepare two staff members on one contact.
Steps
Edit several fields through Review Changes; then save after a colleague; press Keep Editing.
Expected
One patch of the changed keys, one version bump, one revision; the conflict notice; no silent version advance.
Data
Use two personas.
Bound to
Source
react-console:acceptance/crm/playwright/journeys/contacts/CRM-ACC-0009.spec.ts#CRM-ACC-0009
13 A whole-record save must carry every replaceable propertyruleapinegativeproposed
Proves
BR-CAP-CRM-ENT-004-13
Preconditions
A contact exists with a job title and two addresses; the caller holds crm.contacts.update.
Steps
Read the contact; send it back unchanged with PUT; then send a PUT that omits job_title; then send a PUT with job_title null.
Expected
The unchanged save succeeds without changing the version; the omitting save is refused with 400 naming job_title and writes nothing; the null save clears the job title and keeps both addresses.
Data
One contact with a job title and two typed addresses in a disposable workspace.
Source
OQ-CRM-ENT-001 decided 2026-10-22: A; services-crm:docs/entities-api.md#Not yet under the complete-payload rule
14 Reject corrections without the matching update authoritypermissionapinegativeproposed
Proves
BR-CAP-CRM-ENT-004-01 BR-CAP-CRM-ENT-003-09
Preconditions
A caller can read both record kinds but has neither update permission.
Steps
Attempt a version-tested correction on a contact and an organization; repeat with each matching update grant.
Expected
Unauthorized corrections are refused and leave the saved values intact; the matching grant allows the corresponding eligible correction.
Data
Run-owned records and configuration in an isolated workspace.
Source
services-crm:modules/entities/aws/api/contacts.routes.ts; services-crm:modules/entities/aws/api/organizations.routes.ts
15 Correct a newly established personinteractionapiproposed
Proves
BR-CAP-CRM-ENT-001-02 BR-CAP-CRM-ENT-004-01
Preconditions
A person has just been created.
Steps
Read its version and correct its name parts through a version-tested save.
Expected
The corrected record retains its identity and shows the newly derived names.
Data
Run-owned records and configuration in an isolated workspace.
Source
services-crm:modules/entities/tests/e2e/contacts-names.e2e.spec.js#builds the full name from every part in order, trimmed and singly spaced; services-crm:modules/entities/tests/e2e/contacts.e2e.spec.js#answers 400 naming sys_version to a patch that tests no version
16 Correct a contact point without replacing its identityinteractionapiproposed
Proves
BR-CAP-CRM-ENT-004-05 BR-CAP-CRM-ENT-005-10
Preconditions
A person’s address has a known element identity and version.
Steps
Patch its city and read the collection and record version.
Expected
The city changes under the original element identity and the aggregate advances once.
Data
Run-owned records and configuration in an isolated workspace.
Source
services-crm:modules/entities/tests/integration/services/persistence/contacts.integration.spec.js#moves the second address into the type the first left, and the preferred flag with it; services-crm:docs/milestones/CRM-M1-contacts-and-organizations.plan.md#A9
17 Keep all values after a mixed correction failsinteractionapiproposed
Proves
BR-CAP-CRM-ENT-004-07 BR-CAP-CRM-ENT-008-03
Preconditions
A person has saved notes and a valid custom number.
Steps
Change the notes while submitting an invalid custom number in the same save.
Expected
Neither proposed change survives the refusal.
Data
Run-owned records and configuration in an isolated workspace.
Source
services-crm:modules/entities/tests/integration/services/persistence/contacts.integration.spec.js#rolls back the contact row the transaction had already updated; services-crm:modules/entities/tests/e2e/contacts-custom-fields.e2e.spec.js#refuses yes for a yes/no field: no truthiness
18 Relationship edits invalidate an open contact editinteractionapiproposed
Proves
BR-CAP-CRM-ENT-004-01 BR-CAP-CRM-ENT-009-02
Preconditions
Two editors read the same person; one uses the organization people workflow.
Steps
Save an affiliation correction from the organization, then submit the original contact edit at its old version.
Expected
The second editor receives a conflict and the relationship correction remains.
Data
Run-owned records and configuration in an isolated workspace.
Source
services-crm:modules/entities/tests/e2e/contacts.e2e.spec.js#answers 400 naming sys_version to a patch that tests no version; react-console:acceptance/crm/playwright/journeys/affiliations/CRM-ACC-0202.spec.ts#CRM-ACC-0202
19 Archive invalidates an open correctioninteractionapiproposed
Proves
BR-CAP-CRM-ENT-004-01 BR-CAP-CRM-ENT-013-05
Preconditions
An editor reads a live person while an administrator can archive it.
Steps
Archive the person; submit the editor’s pending correction.
Expected
The correction is refused and the archived record retains its pre-edit values.
Data
Run-owned records and configuration in an isolated workspace.
Source
services-crm:modules/entities/tests/e2e/contacts.e2e.spec.js#answers 400 naming sys_version to a patch that tests no version; services-crm:modules/entities/tests/e2e/archive.e2e.spec.js#refuses a replacement, 409 RecordArchived
20 A full lock blocks an ordinary correctioninteractionapiproposed
Proves
BR-CAP-CRM-ENT-004-01 BR-CAP-CRM-ENT-015-05
Preconditions
An editor has read a record and an administrator can change its lock.
Steps
Apply a full lock; attempt the pending ordinary correction; unlock and reread before saving again.
Expected
The locked attempt preserves the record; a newly based correction succeeds after release.
Data
Run-owned records and configuration in an isolated workspace.
Source
services-crm:modules/entities/tests/e2e/contacts.e2e.spec.js#answers 400 naming sys_version to a patch that tests no version; services-crm:modules/entities/tests/e2e/contacts.e2e.spec.js#answers 409 IllegalOperation, not 403, for a replacement of a contact locked against updates, the lock sent back unchanged
21 Change person standing and preserve an unavailable email reservationtransitionapinegativeproposed
Proves
BR-CAP-CRM-ENT-001-10 BR-CAP-CRM-ENT-005-02 BR-CAP-CRM-ENT-004-01
Preconditions
A person is active with a primary email; another run-owned person can claim that email after its reservation is released.
Steps
Save the first person inactive, then deceased; let the other person claim its email and attempt reactivation. Release the competing reservation and reactivate, then mark duplicate.
Expected
The stored standing follows each accepted save. The conflicting reactivation preserves deceased status; reactivation succeeds after release and duplicate status remains supported.
Data
Run-owned records and configuration in an isolated workspace.
Source
services-crm:modules/entities/tests/integration/db/contact-email-addresses.table.integration.spec.js#refuses to make an inactive contact active while another contact holds its primary address
22 Change organization status through versioned correctionstransitionapiproposed
Proves
BR-CAP-CRM-ENT-002-08 BR-CAP-CRM-ENT-004-01
Preconditions
An active organization has a known current version.
Steps
Change it to inactive, then active, then duplicate, reading each result before the next save.
Expected
Each successful status change preserves organization identity and is based on the latest saved version.
Data
Run-owned records and configuration in an isolated workspace.
Source
services-crm:modules/entities/tests/integration/db/organizations.table.integration.spec.js#refuses a status outside the closed list by organizations_status_check
23 Exercise every declared authority independentlypermissionapinegativeproposed
Proves
BR-CAP-CRM-ENT-003-07 BR-CAP-CRM-ENT-003-09
Preconditions
An eligible record and configuration fixture exist for each operation; the caller can reach only the run’s workspace.
Steps
For each declared permission, execute its matching operation with that permission, then without it while retaining the other required grants. Read affected records after every refused mutation.
Expected
The authorized case reaches the operation; the missing-grant case is refused and preserves saved data. Record access alone does not authorize the other declared actions.
Data
Run-owned records and configuration in an isolated workspace.
Source
services-crm:aws/crm.service.ts:ApplicationPermissions; services-crm:modules/entities/aws/api/entities.routes.ts
24 A stale hierarchy correction preserves the colleague’s parent moveinteractionapinegativeproposed
Proves
BR-CAP-CRM-ENT-002-07 BR-CAP-CRM-ENT-004-01
Preconditions
An organization editor has read a chapter; a colleague has a current version and can move it between two roots.
Steps
Save the colleague’s parent move; submit the first editor’s hierarchy correction at its old version and read the chapter’s ancestry.
Expected
The stale correction is refused and ancestry still follows the colleague’s committed parent move.
Data
Run-owned chapter and two roots in an isolated workspace.
Source
services-crm:modules/entities/tests/e2e/organizations.e2e.spec.js#answers 409 for a version the organization has moved past; rhythm-v2-docs:specs/crm/entities/planning/capabilities/CAP-CRM-ENT-002-record-an-organization-and-its-place-in-a-hierarchy.md

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.