IOrganizationPartyManagementPATCH Apex Interface

The IOrganizationPartyManagementPATCH Apex interface provides extensibility for PATCH operations through Apex pre- and post-hooks and GraphQL query customization. Implementations can validate incoming requests, modify query structures, and refine the response to support business-specific retrieval rules while maintaining TMF-compliant behavior.

This interface supports the following hooks.

Account Update Operation Use Cases

Use Case Hook(s) Description Example Scenarios Benefit
Block Updates to Protected Fields transformRequest Examines and transforms the request before validation and mutation processing. Protected, read-only, or unauthorized fields can be removed from the update payload before the write occurs. - Remove system-managed Account identifiers<br>- Prevent clients from changing ownership fields <br>- Strip restricted financial or compliance attributes <br>- Remove fields that are read-only for the caller's role Protects controlled Account fields by stripping disallowed values before they can be persisted.
Enforce Value Policies on Update applyCustomValidations Applies organization-specific business rules to proposed Account field values before the update mutation is built. Invalid updates are rejected with an HTTP 400 response and a clear error message. - Reject invalid Account lifecycle transitions<br>- Enforce permitted values for type, status, or segment <br>- Require dependent fields when Account status changes <br>- Prevent updates that violate regional policies Rejects invalid updates early and preserves business, compliance, and data integrity.
Add Custom Validation Flags configureDefaultValidations Enables, disables, or adds validation flags for Account update requests according to organization-specific policies. - Require Account-existence validation <br>- Enable optimistic concurrency or version checks <br>- Require additional validation for protected Accounts <br>- Apply stricter checks to regulated records Supports per-organization update policies without changing the shared update implementation.
Stamp Audit Fields on Update customiseMutationPayload Adds audit and provenance fields to the GraphQL mutation payload before execution. This allows metadata beyond the TMF632 schema to be persisted with the Account update. - Add lastModifiedBy and lastModifiedAt<br>- Record the source channel or integration<br>- Store a request or correlation ID<br>- Capture the reason for the Account update Persists provenance and audit information beyond the standard TMF632 data model.
Audit or Integrate After Update handlePostOperation Runs after the update mutation completes and performs post-operation side effects using the update result. It can write audit records, publish events, or invoke downstream integrations. - Write an Account-update audit record <br>- Publish an Account-updated event<br>- Synchronize changes with billing or CRM systems <br>- Invalidate related caches or search indexes <br>- Trigger compliance or notification workflows Enables reliable auditing and downstream processing after a successful update while keeping side effects separate from the core mutation.

transformRequest

This hook transforms the request context before processing any operation. It is invoked early in the request lifecycle, allowing implementers to adjust the context for subsequent extensibility hooks.

Hook Method

Map<String, Object> transformRequest(Map<String, Object> context)

Sample Apex Implementation

Prevent updates to name.

global class OrganizationPatchTransformRequestExt implements comms_apex_ext.IOrganizationPartyManagementPATCH {
    global static Map<String, Object> transformRequest(Map<String, Object> context) {
        if (context != null && context.get('requestBody') instanceof Map<String, Object>) {
            Map<String, Object> body = (Map<String, Object>) context.get('requestBody');
            // Business rule: legal-name changes must go through a separate governance flow.
            body.remove('name');
        }
        return context;
    }
    // ... other hooks return null / empty map ...
}

configureDefaultValidations

This hook enables, disables, or modifies the built-in validation rules before they execute.

Hook Method

Map<String, Boolean> configureDefaultValidations(Map<String, Boolean> defaultValidationConfiguration, Map<String, Object> context)

Sample Apex Implementation

Add a custom flag consumed by applyCustomValidations.

global class OrganizationPatchConfigValidationsExt implements comms_apex_ext.IOrganizationPartyManagementPATCH {
    global static Map<String, Boolean> configureDefaultValidations(
        Map<String, Boolean> defaultValidationConfiguration,
        Map<String, Object> context
    ) {
        Map<String, Boolean> overrides = defaultValidationConfiguration != null
            ? defaultValidationConfiguration.clone()
            : new Map<String, Boolean>();
        overrides.put('typeTransitionCheck', true);   // your own flag, read in applyCustomValidations
        return overrides;
    }
    // ... other hooks return null / empty map ...
}

applyCustomValidations

This hook validates custom business logic before retrieving customer record. If validation fails, it rejects the request and returns an error response.

The handler processes return values as follows.

Success:

  • Return a map with validationStatus set to "pass" (case-insensitive).
  • The API request continues normally.
  • Other fields in the map are logged but not used.

Failure:

  • Return a map with validationStatus set to "fail" (case-insensitive).
  • The API request is terminated immediately.
  • Raise a ValidationException containing
    • message: value from validationMessage key (or "Validation failed" by default)
    • details: value from validationDetails key (optional)
  • The client receives an HTTP 400 error response.

Hook Method

Map<String, Object> applyCustomValidations(Map<String, Object> context)

Sample Apex Implementation

Guard an organizationType transition.

global class OrganizationPatchValidationExt implements comms_apex_ext.IOrganizationPartyManagementPATCH {
    private static final Set<String> ALLOWED_TYPES = new Set<String>{ 'Customer', 'Partner', 'Prospect' };
    global static Map<String, Object> applyCustomValidations(Map<String, Object> context) {
        Map<String, Object> result = new Map<String, Object>();
        if (!(context.get('requestBody') instanceof Map<String, Object>)) {
            return result;
        }
        Map<String, Object> body = (Map<String, Object>) context.get('requestBody');

        Object typeObj = body.get('organizationType');
        if (typeObj instanceof String && !ALLOWED_TYPES.contains((String) typeObj)) {
            result.put('validationStatus', 'fail');
            result.put('validationMessage',
                'organizationType must be one of: Customer, Partner, Prospect.');
        }
        return result;   // empty => proceed; validationStatus="fail" => HTTP 400
    }
    // ... other hooks return null / empty map ...
}

customiseMutationPayload

This hook modifies the GraphQL query before execution to add fields, filters, or transformations.

Hook Method

Map<String, Object> customiseMutationPayload(Map<String, Object> graphQLAsMap,Map<String, Object> context)

Sample Apex Implementation

Stamp an audit field on update.

global class OrganizationPatchCustomMutationExt implements comms_apex_ext.IOrganizationPartyManagementPATCH {
    global static Map<String, Object> customiseMutationPayload(
        Map<String, Object> graphQLAsMap,
        Map<String, Object> context
    ) {
        Map<String, Object> node = new Map<String, Object>{
            'path' => 'organizationData',
            'addFields' => new Map<String, Object>{
                'Last_API_Update__c' => 'TMF632-PATCH'
            }
        };
        return new Map<String, Object>{
            'nodes' => new List<Object>{ node }
        };
    }
    // ... other hooks return null / empty map ...
}

handlePostOperation

This hook post-processes and transforms the API response after data retrieval.

Hook Method

Map<String, Object> handlePostOperation(Map<String, Object> graphQLQueryResultAsMap, Map<String, Object> constructedTMFResponse, Map<String, Object> context)

Sample Apex Implementation

Enrich the response in place.

global class OrganizationPatchHandlePostOpExt implements comms_apex_ext.IOrganizationPartyManagementPATCH {
    global static Map<String, Object> handlePostOperation(
        Map<String, Object> graphQLQueryResultAsMap,
        Map<String, Object> constructedTMFResponse,
        Map<String, Object> context
    ) {
        String orgId = context != null ? (String) context.get('id') : null;
        if (orgId != null) {
            EventBus.publish(new Organization_Updated__e(Account_Id__c = orgId));
        }
        return null;   // ignored for PATCH
    }
    // ... other hooks return null / empty map ...
}

Full Implementation Example

Here's a complete sample Apex implementation using all supported hooks.

/**
 * Complete TMF632 Organization (Party Management) PATCH API extension,
 * demonstrating all hooks with business logic.
 */
global class OrganizationPartyManagementPATCHExtension implements comms_apex_ext.IOrganizationPartyManagementPATCH {
    private static final Set<String> ALLOWED_TYPES = new Set<String>{ 'Customer', 'Partner', 'Prospect' };


    // Hook 1: prevent legal-name updates via the API.
    global static Map<String, Object> transformRequest(Map<String, Object> context) {
        if (context != null && context.get('requestBody') instanceof Map<String, Object>) {
            ((Map<String, Object>) context.get('requestBody')).remove('name');
        }
        return context;
    }


    // Hook 2: PATCH has no default validators; keep it that way.
    global static Map<String, Boolean> configureDefaultValidations(
        Map<String, Boolean> defaultValidationConfiguration,
        Map<String, Object> context
    ) {
        return new Map<String, Boolean>();
    }


    // Hook 3: guard the organizationType transition.
    global static Map<String, Object> applyCustomValidations(Map<String, Object> context) {
        Map<String, Object> result = new Map<String, Object>();
        if (context.get('requestBody') instanceof Map<String, Object>) {
            Map<String, Object> body = (Map<String, Object>) context.get('requestBody');
            Object typeObj = body.get('organizationType');
            if (typeObj instanceof String && !ALLOWED_TYPES.contains((String) typeObj)) {
                result.put('validationStatus', 'fail');
                result.put('validationMessage',
                    'organizationType must be one of: Customer, Partner, Prospect.');
            }
        }
        return result;
    }


    // Hook 4: stamp an audit field on update.
    global static Map<String, Object> customiseMutationPayload(
        Map<String, Object> graphQLAsMap,
        Map<String, Object> context
    ) {
        Map<String, Object> node = new Map<String, Object>{
            'path' => 'organizationData',
            'addFields' => new Map<String, Object>{ 'Last_API_Update__c' => 'TMF632-PATCH' }
        };
        return new Map<String, Object>{ 'nodes' => new List<Object>{ node } };
    }


    // Hook 5: side effect only (return ignored).
    global static Map<String, Object> handlePostOperation(
        Map<String, Object> graphQLQueryResultAsMap,
        Map<String, Object> constructedTMFResponse,
        Map<String, Object> context
    ) {
        return null;
    }
}