---
id: WF-MBR-MEM-009
title: Transfer an affiliation to another unit
trigger: >-
  Staff or an officer submit a target unit, effective date and affiliation
  version.
product_area: membership
module: memberships
revision: 1
status: draft
design_intent: proposed
implementation_evidence: observed
inference: []
source_sha:
  services-membership: 5994c270e8a37a30f848e99ba5b5ee6b87c08893
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
implements:
  - CAP-MBR-MEM-007
  - CAP-MBR-MEM-008
  - CAP-MBR-MEM-015
moves:
  - STATE-MBR-MEM-005
crosses:
  - SVC-MBR-MEM-memberships
  - SVC-MBR-MEM-events
idempotency: >-
  A completed transfer advances the predecessor version. An optional request key
  returns its original response; otherwise the old version is stale.
concurrency: >-
  Affiliation changes acquire the membership lock. Shared unit locking also
  orders unit selection against a merge.
hops:
  - 'n': 1
    actor_or_service: Staff or officer through the API
    action: >-
      Lock the membership and check visibility and access to both units before
      revealing version details.
    anchor: >-
      services-membership:modules/memberships/services/access/scope-checks.ts:requireUnitsInScope
    seam: sync
    on_failure: >-
      Hide inaccessible holdings as not found; report the refused units for an
      otherwise visible holding.
    left_inconsistent: No partial local change remains.
    observer: Caller-visible API result
    provenance: test
    source: >-
      services-membership:modules/memberships/tests/unit/unit-scope.spec.ts#answers
      not_found, not allowed, for a membership whose chain the set does not
      reach
  - 'n': 2
    actor_or_service: Memberships service
    action: >-
      Check affiliation version, target activity, effective dates, unit counts
      and whether the target requires dues.
    anchor: >-
      services-membership:modules/memberships/services/affiliations/affiliation-operations.ts:transferAffiliation
    seam: sync
    on_failure: >-
      Reject a dues-bearing move as amendment-required or return the violated
      unit rule.
    left_inconsistent: No partial local change remains.
    observer: Caller-visible API result
    provenance: test
    source: >-
      services-membership:tests/e2e/s06-midterm-transfer.e2e.spec.ts#refuses the
      console’s transfer 409 requires_amendment
  - 'n': 3
    actor_or_service: Memberships service
    action: >-
      End the predecessor, create the successor and record transfer plus started
      and ended business events.
    anchor: >-
      services-membership:modules/memberships/services/affiliations/affiliation-operations.ts:writeAffiliationTransfer
    seam: sync
    on_failure: An error aborts the transaction and reverses its writes.
    left_inconsistent: No partial local change remains.
    observer: Operation result and published-event log
    provenance: observed
    source: >-
      services-membership:modules/memberships/services/affiliations/affiliation-operations.ts:writeAffiliationTransfer
branches:
  - >-
    The direct transfer requires a date after the predecessor starts; it rejects
    a move on the same start day.
waits: []
evidence:
  - >-
    services-membership at 5994c270:
    modules/memberships/services/affiliations/affiliation-operations.ts;
    services/access/scope-checks.ts, unit-scope.ts
controls: [TC-AVL-002, TC-AVL-003, TC-AVL-004, TC-AZ-001, TC-AZ-002, TC-AZ-003, TC-AZ-004, TC-AZ-006, TC-CHG-001, TC-CHG-002, TC-CHG-003, TC-CHG-004, TC-CRY-001, TC-CRY-002, TC-CRY-003, TC-DAT-001, TC-DAT-002, TC-DAT-003, TC-DAT-004, TC-DAT-007, TC-IAM-001, TC-IAM-002, TC-IAM-004, TC-IAM-005, TC-IAM-006, TC-LOG-001, TC-LOG-002, TC-LOG-003, TC-LOG-004, TC-LOG-005, TC-MON-001, TC-MON-002, TC-MON-004, TC-PI-001, TC-PI-002, TC-PI-003, TC-PI-004, TC-PI-005, TC-PRV-001, TC-PRV-002, TC-SEC-001, TC-SEC-004, TC-TEN-001, TC-TEN-002, TC-TEN-003, TC-TEN-004]
---

# Transfer an affiliation to another unit

## What It Does

A transfer preserves chapter history by ending the earlier span immediately before a successor begins. The successor retains primary selection and predecessor lineage.

## The Flow

```mermaid
flowchart TD
  H1["Lock the membership and check visibility and access to both units before revealing version details"]
  H2["Check affiliation version, target activity, effective dates, unit counts and whether the target requires dues"]
  H1 --> H2
  H3["End the predecessor, create the successor and record transfer plus started and ended business events"]
  H2 --> H3
```

## When Something Fails

The entire move rolls back on refusal. A target charging package dues requires an amendment, which remains unimplemented; ending and adding does not provide a bypass.
