ITroubleTicketManagementPOST Apex Interface

The ITroubleTicketManagementPOST interface enables customization of POST operations using Apex lifecycle hooks. Implementations can validate and enrich creation payloads, apply additional business logic, and modify the final response structure, ensuring that customer-creation workflows remain flexible maintaining TMF-compliant behavior.

This interface supports the following hooks.

These hooks are not used for the Trouble Ticket Management API. If implemented, the method may be invoked, but its return values are ignored.

  • configureDefaultValidations
  • customiseGraphQLQuery

Note

Creation Lifecycle Use Cases and Hook Mapping 

The following table lists common use cases for POST operation.

Use CaseHook(s)Description
Example Scenarios
Benefit
Enforce Business RulesapplyCustomValidationsValidates customer creation requests before processing to ensure they comply with business rules, data quality constraints, and organizational policies. Prevents invalid or duplicate customer records from entering the system.• Block creation of customers with duplicate names or identifiers• Reject requests with invalid customer types or lifecycle statuses• Enforce mandatory business validations (e.g., email/phone standards)Prevents invalid or low-quality customer records from being created, improving data integrity
Auto-Populate FieldscustomiseMutationPayloadAutomatically enriches or computes field values during customer creation. Ensures consistent and accurate population of derived or dependent fields before data is persisted.• Generate customer display name from first/last name• Auto-calculate classification, segment, or service level• Populate geo-encoding or internal routing codesReduces manual data entry, enforces consistency, and improves data accuracy
Audit TrailhandlePostOperationAdds audit metadata to newly created customer records after persistence, ensuring every creation event is traceable for security and compliance.• Stamp “createdBy”, “createdAt” values• Add system identifiers for correlation or traceability• Trigger downstream audit logging servicesMaintains a reliable and compliant audit trail across all customer creation events

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 

1public Map<String, Object> transformRequest(Map<String, Object> context) {
2    if (context == null) {
3        return context;
4    }
5
6    Map<String, Object> requestBody = (Map<String, Object>) context.get('requestBody');
7    if (requestBody == null) {
8        return context;
9    }
10
11    // Add default values if not provided
12    if (!requestBody.containsKey('status') || requestBody.get('status') == null) {
13        requestBody.put('status', 'New');
14    }
15
16    if (!requestBody.containsKey('priority') || requestBody.get('priority') == null) {
17        requestBody.put('priority', 'Medium');
18    }
19
20    // Add default origin if not provided
21    if (!requestBody.containsKey('origin') || requestBody.get('origin') == null) {
22        requestBody.put('origin', 'Web');
23    }
24
25    return context;
26}

applyCustomValidations 

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

The handler processes return values as follows.

Success:

  • Return a map with validationStatus set to any value other than “fail” (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 

1public Map<String, Object> applyCustomValidations(Map<String, Object> context) {
2    // Input context:
3    // {
4    //   api: 'TroubleTicketManagement',
5    //   version: '5.0',
6    //   requestBody: {
7    //     name: 'Network Issue',
8    //     severity: 'InvalidSeverity',
9    //     status: 'New'
10    //   }
11    // }
12
13    Map<String, Object> requestBody = (Map<String, Object>) context.get('requestBody');
14
15    if (requestBody == null) {
16        return null;
17    }
18
19    String severity = (String) requestBody.get('severity');
20
21    // If severity is not provided, validation passes (it's optional)
22    if (severity == null || severity.trim().isEmpty()) {
23        return null;
24    }
25
26    Map<String, Object> validationResult = new Map<String, Object>();
27
28    // Validate severity is one of allowed values
29    Set<String> allowedSeverities = new Set<String>{'Critical', 'Major', 'Minor', 'Warning', 'Informational'};
30
31    if (!allowedSeverities.contains(severity)) {
32        validationResult.put('validationStatus', 'FAIL');
33        validationResult.put('validationMessage', 'Invalid severity value: ' + severity + '. Allowed values are: Critical, Major, Minor, Warning, Informational');
34        validationResult.put('validationDetails', new Map<String, Object>{
35            'denialReason' => 'INVALID_SEVERITY_VALUE',
36            'providedValue' => severity,
37            'allowedValues' => new List<String>(allowedSeverities)
38        });
39    } else {
40        // Validation passes
41        validationResult.put('validationStatus', 'PASS');
42        validationResult.put('validationMessage', 'Severity validation passed');
43    }
44
45    return validationResult;
46}

customiseGraphQLQuery 

This hook modifies the GraphQL query before execution to add fields, filters, or transformations. Returns a map with a nodes key containing a list of QueryTransformationNode objects.

Hook Method 

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

  • When to use the hook: Use it when you need to fetch or customize related data before record creation, especially for complex business logic.
  • When not to use the hook: Avoid it for standard POST operations, simple payload changes (use customiseMutationPayload), or validations (use applyCustomValidations).

Note

customiseMutationPayload 

This hook modifies the mutation payload before creating a customer record. Use this to add computed fields, set defaults, or transform the payload based on business logic.

Hook Method 

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

Sample Apex Implementation 

1public Map<String, Object> customiseMutationPayload(
2    Map<String, Object> mutationGraphQLPayload,
3    Map<String, Object> context
4) {
5    // Create mutation transformation specification
6    List<Map<String, Object>> transformationNodes = new List<Map<String, Object>>();
7
8    // Node 1: Add custom input fields to the Case mutation
9    // Path: troubleTicket (the Case mutation alias)
10    Map<String, Object> modifyInputNode = new Map<String, Object>{
11        'path' => 'troubleTicket',
12        'modifyInput' => new Map<String, Object>{
13            'addInputFields' => new Map<String, Object>{
14                'Reason' => 'Created via POST API',
15                'Origin' => 'Web',
16                'Type' => 'Technical Issue'
17            }
18        }
19    };
20    transformationNodes.add(modifyInputNode);
21
22    // Return transformation specification
23    return new Map<String, Object>{
24        'nodes' => transformationNodes
25    };
26}

handlePostOperation 

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

Hook Method 

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

Sample Apex Implementation 

1public Map<String, Object> handlePostOperation(
2    Map<String, Object> graphQLQueryResultAsMap,
3    Map<String, Object> constructedTMFResponse,
4    Map<String, Object> context
5) {
6    // Input TMF response:
7    // {
8    //   id: '00001027',
9    //   name: 'Network connectivity issue',
10    //   status: 'New',
11    //   type: 'TroubleTicket'
12    // }
13
14    String ticketId = (String) constructedTMFResponse.get('id');
15
16    if (ticketId != null) {
17        // Fetch additional data for enrichment
18        Case caseRecord = [SELECT Id, CaseNumber, CreatedDate, CreatedById FROM Case WHERE CaseNumber = :ticketId LIMIT 1];
19
20        // Add audit information
21        constructedTMFResponse.put('createdAt', caseRecord.CreatedDate.format('yyyy-MM-dd\'T\'HH:mm:ss\'Z\''));
22        constructedTMFResponse.put('createdBy', UserInfo.getName());
23
24        // Add calculated fields
25        constructedTMFResponse.put('ticketAge', 0); // New ticket, age is 0
26        constructedTMFResponse.put('isNewTicket', true);
27    }
28
29    // Return enriched response
30    return constructedTMFResponse;
31
32    // Output response:
33    // {
34    //   id: '00001027',
35    //   name: 'Network connectivity issue',
36    //   status: 'New',
37    //   type: 'TroubleTicket',
38    //   createdAt: '2024-01-17T10:30:00Z',
39    //   createdBy: 'John Smith',
40    //   ticketAge: 0,
41    //   isNewTicket: true
42    // }
43}

Full Implementation Example 

1/**
2 * Complete Trouble Ticket Management POST API Extension
3 * Demonstrates all applicable lifecycle hooks with business logic
4 */
5public class TroubleTicketManagementPOSTExtension implements comms_apex_ext.ITroubleTicketManagementPOST {
6
7    /**
8     * Hook 1: Transform request
9     */
10    public Map<String, Object> transformRequest(Map<String, Object> context) {
11        if (context == null) {
12            return context;
13        }
14
15        Map<String, Object> requestBody = (Map<String, Object>) context.get('requestBody');
16        if (requestBody == null) {
17            return context;
18        }
19
20        // Add default values if not provided
21        if (!requestBody.containsKey('status') || requestBody.get('status') == null) {
22            requestBody.put('status', 'New');
23        }
24
25        if (!requestBody.containsKey('priority') || requestBody.get('priority') == null) {
26            requestBody.put('priority', 'Medium');
27        }
28
29        return context;
30    }
31
32    /**
33     * Hook 2: Apply custom validations
34     */
35    public Map<String, Object> applyCustomValidations(Map<String, Object> context) {
36        Map<String, Object> requestBody = (Map<String, Object>) context.get('requestBody');
37
38        if (requestBody == null) {
39            return null;
40        }
41
42        String severity = (String) requestBody.get('severity');
43
44        if (severity == null || severity.trim().isEmpty()) {
45            return null;
46        }
47
48        Set<String> allowedSeverities = new Set<String>{'Critical', 'Major', 'Minor', 'Warning', 'Informational'};
49
50        if (!allowedSeverities.contains(severity)) {
51            return new Map<String, Object>{
52                'validationStatus' => 'FAIL',
53                'validationMessage' => 'Invalid severity value: ' + severity,
54                'validationDetails' => new Map<String, Object>{
55                    'denialReason' => 'INVALID_SEVERITY_VALUE',
56                    'providedValue' => severity,
57                    'allowedValues' => new List<String>(allowedSeverities)
58                }
59            };
60        }
61
62        return null;
63    }
64
65    /**
66     * Hook 3: Customize GraphQL query (optional, rarely used)
67     */
68    public Map<String, Object> customiseGraphQLQuery(
69        Map<String, Object> graphQLAsMap,
70        Map<String, Object> context
71    ) {
72        // Most POST operations don't need to customize the query
73        return null;
74    }
75
76    /**
77     * Hook 4: Customize mutation payload
78     */
79    public Map<String, Object> customiseMutationPayload(
80        Map<String, Object> mutationGraphQLPayload,
81        Map<String, Object> context
82    ) {
83        List<Map<String, Object>> transformationNodes = new List<Map<String, Object>>();
84
85        // Add custom input fields
86        Map<String, Object> modifyInput = new Map<String, Object>{
87            'addInputFields' => new Map<String, Object>{
88                'Reason' => 'Created via POST API',
89                'Origin' => 'Web'
90            }
91        };
92
93        transformationNodes.add(new Map<String, Object>{
94            'path' => 'troubleTicket',
95            'modifyInput' => modifyInput
96        });
97
98        return new Map<String, Object>{ 'nodes' => transformationNodes };
99    }
100
101    /**
102     * Hook 5: Post-process response
103     */
104    public Map<String, Object> handlePostOperation(
105        Map<String, Object> graphQLQueryResultAsMap,
106        Map<String, Object> constructedTMFResponse,
107        Map<String, Object> context
108    ) {
109        String ticketId = (String) constructedTMFResponse.get('id');
110
111        if (ticketId != null) {
112            try {
113                Case caseRecord = [SELECT Id, CaseNumber, CreatedDate FROM Case WHERE CaseNumber = :ticketId LIMIT 1];
114
115                constructedTMFResponse.put('createdAt', caseRecord.CreatedDate.format('yyyy-MM-dd\'T\'HH:mm:ss\'Z\''));
116                constructedTMFResponse.put('createdBy', UserInfo.getName());
117                constructedTMFResponse.put('ticketAge', 0);
118                constructedTMFResponse.put('isNewTicket', true);
119            } catch (Exception e) {
120                System.debug('Error enriching trouble ticket data: ' + e.getMessage());
121            }
122        }
123
124        return constructedTMFResponse;
125    }
126
127    /**
128     * NOT APPLICABLE: configureDefaultValidations is not used for Trouble Ticket Management API
129     * If implemented, this method will be invoked but return values will be ignored.
130     */
131    public Map<String, Boolean> configureDefaultValidations(
132        Map<String, Boolean> defaultValidationConfiguration,
133        Map<String, Object> context
134    ) {
135        // This hook is not applicable for Trouble Ticket Management API
136        // Return the configuration unchanged
137        return defaultValidationConfiguration;
138    }
139}

GraphQL Mutation - Create Operations 

Create mutations add new records and return the created record with the specified output fields.

Create Enhancements: Add Output Fields 

Original Mutation (GraphQL):

1mutation CreateCustomerAndRelatedEntities {
2uiapi {
3customerAccount: AccountCreate(input: {
4Account: { Name: "Acme Corp" }
5}) {
6Record {
7Id
8Name { value }
9}
10}
11}
12}

Transformation Instructions (JSON):

1{
2"nodes": [{
3"path": "customerAccount",
4"addFields": {
5"Industry": "Technology",
6"Revenue": 5000000,
7"Status": "Active"
8}
9}]
10}

Result (GraphQL):

1mutation CreateCustomerAndRelatedEntities {
2uiapi {
3customerAccount: AccountCreate(input: {
4Account: { Name: "Acme Corp" }
5}) {
6Record {
7Id
8Name { value }
9Industry
10Revenue
11Status
12}
13}
14}
15}

Create Enhancements: Modify Input Payload 

Original Mutation (GraphQL):

1mutation CreateCustomerAndRelatedEntities {
2  uiapi {
3    customerAccount: AccountCreate(input: {
4      Account: { Name: "Acme Corp" }
5    }) {
6      Record {
7        Id
8        Name { value }
9      }
10    }
11  }
12}

Transformation Instructions (JSON - Modify Input):

1{
2  "nodes": [{
3    "path": "customerAccount",
4    "modifyInput": {
5      "addInputFields": {
6        "Industry": "Technology",
7        "Status": "Active"
8      }
9    }
10  }]
11}

Result (GraphQL):

1mutation CreateCustomerAndRelatedEntities {
2  uiapi {
3    customerAccount: AccountCreate(input: {
4      Account: {
5        Name: "Acme Corp",
6        Industry: "Technology",
7        Status: "Active"
8      }
9    }) {
10      Record {
11        Id
12        Name { value }
13      }
14    }
15  }
16}

Using modifyInput with addInputFields adds new fields to the input payload. These fields are added to the Account object within the input wrapper and are sent to the mutation.

Note

Create Enhancements: Modify Existing Input Fields 

Original Mutation (GraphQL):

1mutation CreateCustomerAndRelatedEntities {
2  uiapi {
3    customerAccount: AccountCreate(input: {
4      Account: { Name: "Acme Corp" }
5    }) {
6      Record {
7        Id
8        Name { value }
9      }
10    }
11  }
12}

Transformation Instructions (JSON - Modify Existing Fields):

1{
2  "nodes": [{
3    "path": "customerAccount",
4    "modifyInput": {
5      "inputModifications": {
6        "Name": "Updated Company Name"
7      }
8    }
9  }]
10}

Result (GraphQL):

1mutation CreateCustomerAndRelatedEntities {
2  uiapi {
3    customerAccount: AccountCreate(input: {
4      Account: { Name: "Updated Company Name" }
5    }) {
6      Record {
7        Id
8        Name { value }
9      }
10    }
11  }
12}

The inputModifications replaces the values of existing input fields. The transformer identifies the wrapper key, for example Account and applies the changes at the correct nested level.

Note