The IProductInventoryManagementGET Apex interface provides extensibility for TMF637 GET 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 table lists common use cases and the hooks required for the GET operation.
Use Case
Hook(s)
Description
Example Scenarios
Benefit
Role-Based Data Filtering
applyCustomValidations, handlePostOperation
Enforces access rules by validating user permissions before execution and filtering sensitive data after retrieval. Supports role-based visibility at field and record levels.
• Restrict access to VIP or high-value customer profiles• Hide sensitive fields (e.g., credit score) for frontline agents• Enforce region-based access boundaries
Strengthens data governance and ensures secure, compliant access to trouble tickets
Custom Field Enrichment
handlePostOperation
Adds calculated or derived fields to API responses without changing the base TMF schema, allowing customers to extend or modify as needed. Enables enrichment using internal business rules or external systems.
• Add customer health score• Flag “preferred customer” status• Include aggregated financial or usage insights
Delivers richer, more contextual responses while preserving TMF schema integrity
Dynamic Query Customization
customiseGraphQLQuery
Modifies GraphQL queries dynamically based on client or request context by adding fields, filters, or transformations.
• Mobile app requests only essential fields• Portal requires additional entitlement or hierarchy fields• Apply filters automatically for partner channels
Supports diverse client requirements using a single API and reduces need for API versioning
Business Rule Validation
applyCustomValidations
Applies business and eligibility rules before processing requests, stopping invalid operations early in the lifecycle.
• Ensure customer is “active” before retrieving services• Reject unauthorized or unverified channel requests• Enforce lifecycle or dependency checks
Provides strong business consistency and reduces downstream errors by blocking invalid requests early
ProductSerialNumber to Asset Id Resolution
transformRequest
Resolve ProductSerialNumber identifiers to Asset Id for API compatibility.
• An external system sends a ProductSerialNumber (e.g., SN-12345), which is resolved to a Salesforce Asset ID (e.g.,02ixx0000004HHiAAM) for API processing
Support external systems that use ProductSerialNumber instead of Salesforce Asset Id
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.
Sample Apex Implementation: Resolve ProductSerialNumber to Asset Id
1global static Map<String, Object> transformRequest(Map<String, Object> context) {2 if (context == null) {3 return context;4 }56 Object idObj = context.get('id');7 if (idObj == null || !(idObj instanceof String)) {8 return context;9 }1011 String idValue = (String) idObj;1213 // Check if the ID looks like a Salesforce ID (starts with 02i for Asset)14 // If not, assume it's a ProductSerialNumber and resolve it15 if (idValue.length() == 15 || idValue.length() == 18) {16 return context;17 }1819 // Query Asset objects where SerialNumber matches the provided ID20 List<Asset> assets = [21 SELECT Id, SerialNumber22 FROM Asset23 WHERE SerialNumber = :idValue24 LIMIT 125 ];2627 // If found, replace the ID in context with the Salesforce Asset Id28 if (!assets.isEmpty()) {29 context.put('id', assets[0].Id);30 }3132 return context;33}
configureDefaultValidations
This hook controls whether built-in validation rules execute. Use it to disable specific validation checks (such as field name validation) when you need to allow custom or non-standard field names in the request.
1global static Map<String, Boolean> configureDefaultValidations(2 Map<String, Boolean> defaultValidationConfiguration,3 Map<String, Object> context4) {5 // Return empty map to disable all default validations6 // This allows custom/non-standard field names in the request7 return new Map<String, Boolean>();8}
applyCustomValidations
This hook validates custom business logic before retrieving trouble ticket data. 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)
Sample Apex Implementation: Validate Product Inventory Access Based on User Role and Status
1global static Map<String, Object> applyCustomValidations(Map<String, Object> context) {2 // Input context:3 // {4 // api: 'ProductInventoryManagement',5 // version: '5.0',6 // id: '02ixx0000004HHiAAM',7 // userId: '005xx000001Sv5',8 // status: 'Active',9 // fields: ['name', 'status', 'description']10 // }1112 String assetId = (String) context.get('id');13 String userId = (String) context.get('userId');1415 if (String.isBlank(assetId) || String.isBlank(userId)) {16 return null; // Pass - let default behavior handle17 }1819 Map<String, Object> validationResult = new Map<String, Object>();2021 try {22 User currentUser = [SELECT Id, Profile.Name FROM User WHERE Id = :userId LIMIT 1];23 Asset inventoryItem = [SELECT Id, Status FROM Asset WHERE Id = :assetId LIMIT 1];2425 Set<String> authorizedProfiles = new Set<String>{26 'System Administrator', 'Asset Manager', 'Comms Admin'27 };2829 if (!authorizedProfiles.contains(currentUser.Profile.Name)) {30 if ('Obsolete'.equals(inventoryItem.Status) || 'Suspended'.equals(inventoryItem.Status)) {31 validationResult.put('validationStatus', 'FAIL');32 validationResult.put('validationMessage', 'User does not have access to terminated/suspended product inventory items');33 validationResult.put('validationDetails', new Map<String, Object>{34 'denialReason' => 'STATUS_RESTRICTION',35 'userProfile' => currentUser.Profile.Name,36 'assetStatus' => inventoryItem.Status37 });38 return validationResult;39 }40 }4142 // PASS: User is authorized or asset is not in a restricted status43 return null;4445 } catch (Exception e) {46 validationResult.put('validationStatus', 'FAIL');47 validationResult.put('validationMessage', 'Validation error: ' + e.getMessage());48 validationResult.put('validationDetails', new Map<String, Object>{49 'errorType' => e.getTypeName()50 });51 return validationResult;52 }53}
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.
Query transformations provide the ability to enhance GraphQL queries by adding fields, applying filters, or modifying the sort order, while preserving the original query definition.
For the Customer Management API, use the uiapi.query.Account path to reference the primary Account field.