IAccountManagementDELETE Apex Interface

The IAccountManagementDELETE interface provides extensibility for DELETE operations through Apex-based validations, mutation-payload adjustments, and post-operation processing. Users can enforce deletion policies, apply soft-delete or metadata logic, and customize final responses without impacting TMF-compliant delete behavior.

This interface supports the following hooks.

The customiseGraphQLQuery is not applicable to DELETE, which is a write operation, so there is no read query to customize. This hook is declared on the read interface (ICommsGET), not on ICommsDELETE. To customize the soft-delete mutation payload, use customiseMutationPayload.

Note

Account Delete Operation Use Cases 

Use CaseHook(s)DescriptionExample ScenariosBenefit
Resolve an External Key to the Salesforce IDtransformRequestResolves a caller-provided business key or external identifier to the canonical Salesforce Account ID before validation and deletion processing begins.- Resolve an ERP customer number
- Map a billing-system identifier to an Account ID
- Translate a partner-specific key
- Resolve a legacy account reference
Allows callers to address Account records using their own identifiers instead of requiring a Salesforce ID.
Block Deletion Based on Business PreconditionsapplyCustomValidationsEvaluates business rules and dependent-record conditions before the delete mutation is built. The operation is rejected when the Account does not satisfy the required deletion criteria.- Prevent deletion when active subscriptions exist
- Block deletion when the Account has an open balance
- Reject deletion when active contracts or orders exist
- Protect Accounts involved in unresolved disputes
Prevents invalid deletion or deactivation of Accounts that still have active financial, contractual, or operational obligations.
Capture a Deactivation Reason or Audit FieldcustomiseMutationPayload (addFields)Adds organization-specific fields to the mutation payload without replacing the standard delete input. These fields can capture the reason, actor, source, or timestamp associated with the deactivation.- Store a deactivation reason code
- Record the user who initiated the operation
- Add a deactivation timestamp
- Capture the originating channel or system
Records why and how the Account was deactivated, improving traceability and operational reporting.
Override the Terminal StatuscustomiseMutationPayload (modifyInput)Modifies the standard mutation input to use an organization-specific terminal status instead of the default soft-delete status.- Set the status to Cancelled
- Use Closed for completed Account relationships
- Apply a region-specific terminal state
- Select a status based on Account type
Aligns soft-delete behavior with organization-specific lifecycle models by using Cancelled, Closed, or another terminal status instead of Inactive.
Cascade Cleanup or DeprovisioninghandlePostOperationRuns after the Account mutation completes and uses the operation result to clean up related resources or initiate downstream deprovisioning.- Deactivate Account-contact junctions
- Revoke associated entitlements
- Disable downstream access or services
- Publish a deprovisioning event
- Notify billing or subscription systems
Keeps related records and downstream systems consistent with the Account’s deactivated state.
Create an Audit TrailhandlePostOperationRecords the completed deletion or deactivation in an audit or compliance system after the mutation succeeds.- Write a compliance audit entry
- Record the actor, timestamp, and affected Account
- Store the mutation result and deactivation reason
- Publish an immutable deletion event
Provides a reliable compliance record of Account deletions and deactivations.

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 

Resolve an external ID to a Salesforce Contact ID.

1global class AccountMgmtTransformRequestDeleteExt implements comms_apex_ext.IAccountManagementDELETE {
2
3
4    global static Map<String, Object> transformRequest(Map<String, Object> context) {
5        if (context == null) {
6            return context;
7        }
8
9
10        // If the caller addressed the record by an external key, resolve it to the SF id.
11        Object idObj = context.get('id');
12        if (idObj instanceof String && ((String) idObj).startsWith('EXT-')) {
13            String externalKey = (String) idObj;
14            List<BillingAccount> matches = [
15                SELECT Id FROM BillingAccount WHERE ExtlBillingAccountId__c = :externalKey LIMIT 1
16            ];
17            if (!matches.isEmpty()) {
18                context.put('id', matches[0].Id);
19            }
20        }
21        return context;
22    }
23
24
25    // ... other hooks return null / empty map ...
26}

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 

Block deletion when the Account has active subscriptions.

1global class AccountMgmtCustomValidationDeleteExt implements comms_apex_ext.IAccountManagementDELETE {
2
3
4    global static Map<String, Object> applyCustomValidations(Map<String, Object> context) {
5        Map<String, Object> result = new Map<String, Object>();
6        String billingAccountId = (String) context.get('id');
7
8
9        if (billingAccountId != null) {
10            Integer activeCount = [
11                SELECT COUNT() FROM Order
12                WHERE BillingAccountId = :billingAccountId AND Status = 'Activated'
13            ];
14            if (activeCount > 0) {
15                result.put('validationStatus', 'fail');
16                result.put('validationMessage',
17                    'Cannot delete a billing account with active subscriptions.');
18                result.put('validationDetails', new Map<String, Object>{
19                    'billingAccountId'    => billingAccountId,
20                    'activeSubscriptions' => activeCount,
21                    'rule'                => 'NO_DELETE_WITH_ACTIVE_SUBS'
22                });
23                return result;
24            }
25        }
26
27
28        result.put('validationStatus', 'pass');
29        return result;
30    }
31    // ... other hooks return null / empty map ...
32}

customiseMutationPayload 

This hook modifies the mutation payload before deleting a customer record. Use this to add deletion metadata, set soft-delete flags, or apply business logic transformations.

Hook Method 

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

Sample Apex Implementation 

Add a custom field alongside the Status = Inactive change so the soft delete captures why the account was deactivated.

1global class AccountMgmtMutationPayloadDeleteExt implements comms_apex_ext.IAccountManagementDELETE {
2
3
4    global static Map<String, Object> customiseMutationPayload(
5        Map<String, Object> mutationGraphQLPayload,
6        Map<String, Object> context
7    ) {
8        Map<String, Object> node = new Map<String, Object>{
9            'path'      => 'softDeleteBillingAccount',
10            'addFields' => new Map<String, Object>{
11                'ExtlDeactivationReason__c' => 'Deleted via TMF666 API'
12            }
13        };
14        return new Map<String, Object>{ 'nodes' => new List<Object>{ node } };
15    }
16
17
18    // ... other hooks return null / empty map ...
19}

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 

Audit-log the soft delete and cascade cleanup.

1global class IndividualDeleteHandlePostOpExt implements comms_apex_ext.IIndividualPartyManagementDELETE {
2
3
4    global static Map<String, Object> handlePostOperation(
5        Map<String, Object> graphQLQueryResultAsMap,
6        Map<String, Object> constructedTMFResponse,
7        Map<String, Object> context
8    ) {
9        Object dr = context != null ? context.get('deleteResult') : null;
10        if (dr instanceof Map<String, Object>) {
11            Map<String, Object> deleteResult = (Map<String, Object>) dr;
12            if (Boolean.TRUE.equals(deleteResult.get('success'))) {
13                insert new Individual_Deletion_Log__c(
14                    Individual_Id__c = (String) deleteResult.get('deletedId'),
15                    Deleted_By__c    = UserInfo.getUserId()
16                );
17            }
18        }
19        return null;   // no body for HTTP 204
20    }
21
22
23    // customiseMutationPayload still REQUIRED — see HOOK 4 ...
24}

Full Implementation Example 

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

1global class AccountMgmtPostOpAuditDeleteExt implements comms_apex_ext.IAccountManagementDELETE {
2
3
4    global static Map<String, Object> handlePostOperation(
5        Map<String, Object> graphQLResult,
6        Map<String, Object> deleteResult,
7        Map<String, Object> context
8    ) {
9        try {
10            Boolean success = deleteResult != null
11                && Boolean.TRUE.equals(deleteResult.get('success'));
12            String deletedId = deleteResult != null
13                ? (String) deleteResult.get('deletedId')
14                : (String) context.get('id');
15
16
17            System.debug('BillingAccount soft-deleted via TMF666 DELETE by '
18                + UserInfo.getName() + ': ' + deletedId + ' (success=' + success + ')');
19
20
21            // Example cascade: mark related junction records inactive (bulk-safe single DML).
22            if (success && deletedId != null) {
23                // ... enqueue or perform cleanup keyed on deletedId ...
24            }
25        } catch (Exception e) {
26            System.debug('Post-delete handling failed: ' + e.getMessage());
27        }
28        // Return value is ignored for DELETE.
29        return null;
30    }
31
32
33    // ... other hooks return null / empty map ...
34}