IIndividualPartyManagementDELETE Apex Interface

The IIndividualPartyManagementDELETE 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

Deletion Lifecycle Use Cases and Hook Mapping 

This table lists common use cases and the hooks required for the DELETE operation.

Use CaseHook(s)DescriptionExample ScenariosBenefit
Supply the Soft-Delete Status FieldcustomiseMutationPayloadAdds the status field required to perform a soft delete. The hook can also include deletion metadata or additional organization-specific fields in the GraphQL mutation payload.- Set status to Deleted or Inactive
- Add a deletion timestamp
- Record the ID of the user performing the deletion
- Include custom fields or mutation snippets
Required to make the DELETE operation functional while preserving the record for auditing, recovery, and historical reporting.
Prevent Deletion Under Business RulesapplyCustomValidationsEvaluates custom business rules before the mutation is built. If a rule fails, the hook prevents deletion and returns an HTTP 422 response with a clear validation message.- Prevent deletion of an active customer
- Block deletion when dependent records exist
- Restrict deletion to authorized roles
- Protect records in locked lifecycle states
Stops invalid deletions early and provides clients with a clear, actionable explanation of the failure.
Resolve an External ID to a Contact IDtransformRequestConverts a legacy or external identifier into the canonical Contact ID expected by the delete operation and stores it in the shared request context as { id }.- Resolve a legacy customer key
- Map a partner-system identifier to a Contact ID
- Convert an account-specific reference into { id }
- Normalize migrated identifiers
Allows existing clients and legacy integrations to use familiar identifiers without changing the core delete contract.
Add Custom Validation FlagsconfigureDefaultValidationsEnables, disables, or adds validation flags for the delete operation. This supports organization-specific policies, especially because DELETE does not register built-in validations by default.- Require record-existence validation
- Enable concurrency or version checks
- Require confirmation for protected records
- Apply stricter validation in regulated organizations
Supports per-organization deletion policies without modifying the shared delete implementation.
Audit or Cascade After DeletionhandlePostOperationRuns after the delete mutation completes and receives the deleteResult summary. It can use that result to perform auditing, cascading updates, event publication, or other side effects.- Write an audit record
- Cascade the deleted status to dependent resources
- Publish a deletion event
- Invalidate related caches or search indexes
- Record deletion metrics
Enables reliable post-delete processing using the mutation’s deleteResult summary while keeping side effects separate from the core operation.

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 IndividualDeleteTransformRequestExt implements comms_apex_ext.IIndividualPartyManagementDELETE {
2
3
4    global static Map<String, Object> transformRequest(Map<String, Object> context) {
5        if (context == null || !(context.get('id') instanceof String)) {
6            return context;
7        }
8        String idValue = (String) context.get('id');
9        if (idValue.length() != 15 && idValue.length() != 18) {
10            List<Contact> matches = [
11                SELECT Id FROM Contact WHERE External_Id__c = :idValue LIMIT 1
12            ];
13            if (!matches.isEmpty()) {
14                context.put('id', matches[0].Id);
15            }
16        }
17        return context;
18    }
19
20
21    // customiseMutationPayload still REQUIRED — see HOOK 4 ...
22}

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.

1global class IndividualDeleteConfigValidationsExt implements comms_apex_ext.IIndividualPartyManagementDELETE {
2
3
4    global static Map<String, Boolean> configureDefaultValidations(
5        Map<String, Boolean> defaultValidationConfiguration,
6        Map<String, Object> context
7    ) {
8        Map<String, Boolean> overrides = defaultValidationConfiguration != null
9            ? defaultValidationConfiguration.clone()
10            : new Map<String, Boolean>();
11        overrides.put('checkOpenOrders', true);   // your own flag, read in applyCustomValidations
12        return overrides;
13    }
14
15
16    // customiseMutationPayload still REQUIRED — see HOOK 4 ...
17}

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 

Prevent deletion when the Individual party has open order.

1global class IndividualDeletePreventExt implements comms_apex_ext.IIndividualPartyManagementDELETE {
2
3
4    global static Map<String, Object> applyCustomValidations(Map<String, Object> context) {
5        Map<String, Object> result = new Map<String, Object>();
6        String individualId = (String) context.get('id');
7        if (individualId != null) {
8            Integer openOrders = [
9                SELECT COUNT() FROM Order
10                WHERE (BillToContactId = :individualId OR ShipToContactId = :individualId)
11                  AND Status = 'Activated'
12            ];
13            if (openOrders > 0) {
14                result.put('validationStatus', 'fail');
15                result.put('validationMessage',
16                    'Cannot delete this Individual - deletion prevented by custom validation');
17            }
18        }
19        return result;   // empty => proceed; validationStatus="fail" => HTTP 422
20    }
21
22
23    // customiseMutationPayload still REQUIRED — see HOOK 4 ...
24}

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 

Supply the soft-delete status field.

1global class IndividualDeleteCustomMutationExt implements comms_apex_ext.IIndividualPartyManagementDELETE {
2
3
4    global static Map<String, Object> customiseMutationPayload(
5        Map<String, Object> graphQLAsMap,
6        Map<String, Object> context
7    ) {
8        Map<String, Object> node = new Map<String, Object>{
9            'path'      => 'softDeleteIndividual',
10            'addFields' => new Map<String, Object>{
11                'Status__c'          => 'Inactive',
12                'Deletion_Reason__c' => 'Deleted via TMF632 Individual API'
13            }
14        };
15        return new Map<String, Object>{
16            'nodes' => new List<Object>{ node }
17        };
18    }
19    // ... other hooks return null / empty map ...
20}

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 the deletion.

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.

1/**
2 * Complete TMF632 Individual (Party Management) DELETE API extension,
3 * demonstrating all hooks. customiseMutationPayload supplies the required soft-delete field.
4 */
5global class IndividualPartyManagementDELETEExtension implements comms_apex_ext.IIndividualPartyManagementDELETE {
6
7
8    // Hook 1: normalize / resolve the id.
9    global static Map<String, Object> transformRequest(Map<String, Object> context) {
10        return context;
11    }
12
13
14    // Hook 2: DELETE has no default validators; keep it that way.
15    global static Map<String, Boolean> configureDefaultValidations(
16        Map<String, Boolean> defaultValidationConfiguration,
17        Map<String, Object> context
18    ) {
19        return new Map<String, Boolean>();
20    }
21
22
23    // Hook 3: block deletion when there are active orders.
24    global static Map<String, Object> applyCustomValidations(Map<String, Object> context) {
25        Map<String, Object> result = new Map<String, Object>();
26        String individualId = (String) context.get('id');
27        if (individualId != null) {
28            Integer openOrders = [
29                SELECT COUNT() FROM Order
30                WHERE (BillToContactId = :individualId OR ShipToContactId = :individualId)
31                  AND Status = 'Activated'
32            ];
33            if (openOrders > 0) {
34                result.put('validationStatus', 'fail');
35                result.put('validationMessage',
36                    'Cannot delete this Individual - deletion prevented by custom validation');
37            }
38        }
39        return result;
40    }
41
42
43    // Hook 4 (REQUIRED): supply the soft-delete status field on the softDeleteIndividual node.
44    global static Map<String, Object> customiseMutationPayload(
45        Map<String, Object> graphQLAsMap,
46        Map<String, Object> context
47    ) {
48        Map<String, Object> node = new Map<String, Object>{
49            'path'      => 'softDeleteIndividual',
50            'addFields' => new Map<String, Object>{ 'Status__c' => 'Inactive' }
51        };
52        return new Map<String, Object>{ 'nodes' => new List<Object>{ node } };
53    }
54
55
56    // Hook 5: audit the deletion (no response body).
57    global static Map<String, Object> handlePostOperation(
58        Map<String, Object> graphQLQueryResultAsMap,
59        Map<String, Object> constructedTMFResponse,
60        Map<String, Object> context
61    ) {
62        Object dr = context != null ? context.get('deleteResult') : null;
63        if (dr instanceof Map<String, Object>
64            && Boolean.TRUE.equals(((Map<String, Object>) dr).get('success'))) {
65            // audit / downstream cleanup
66        }
67        return null;
68    }
69}