/** * @description Platform Event Handler/Action Class for {{EventName}}__e * * Use Case: Business logic for processing Platform Events * - Separated from trigger for testability * - TAF-compatible action pattern * - Bulkified processing * * This class is called by the {{EventName}}Subscriber trigger * and contains all business logic for event processing. * * @author {{Author}} * @date {{Date}} */ public with sharing class {{EventName}}Handler { /** * @description Handle CREATE operation events * @param event The platform event */ public static void handleCreate({{EventName}}__e event) { Map payload = parsePayload(event.Payload__c); // Example: Create a record based on event data /* {{TargetObject}}__c newRecord = new {{TargetObject}}__c(); newRecord.Name = (String) payload.get('name'); newRecord.External_Id__c = event.Record_Id__c; newRecord.Source_System__c = 'Platform Event'; insert newRecord; */ System.debug(LoggingLevel.DEBUG, 'Processed CREATE event: ' + event.Correlation_Id__c); } /** * @description Handle UPDATE operation events * @param event The platform event */ public static void handleUpdate({{EventName}}__e event) { Map payload = parsePayload(event.Payload__c); String recordId = event.Record_Id__c; // Example: Update existing record /* List<{{TargetObject}}__c> records = [ SELECT Id, Name FROM {{TargetObject}}__c WHERE External_Id__c = :recordId WITH USER_MODE LIMIT 1 ]; if (!records.isEmpty()) { {{TargetObject}}__c record = records[0]; record.Name = (String) payload.get('name'); record.Last_Sync__c = Datetime.now(); update record; } */ System.debug(LoggingLevel.DEBUG, 'Processed UPDATE event: ' + event.Correlation_Id__c); } /** * @description Handle DELETE operation events * @param event The platform event */ public static void handleDelete({{EventName}}__e event) { String recordId = event.Record_Id__c; // Example: Delete or archive record /* List<{{TargetObject}}__c> records = [ SELECT Id FROM {{TargetObject}}__c WHERE External_Id__c = :recordId WITH USER_MODE LIMIT 1 ]; if (!records.isEmpty()) { delete records; } */ System.debug(LoggingLevel.DEBUG, 'Processed DELETE event: ' + event.Correlation_Id__c); } /** * @description Handle bulk events (for optimized processing) * Call this from trigger instead of individual handlers * when processing high volumes * @param events List of events to process */ public static void handleBulk(List<{{EventName}}__e> events) { // Separate events by operation List<{{EventName}}__e> createEvents = new List<{{EventName}}__e>(); List<{{EventName}}__e> updateEvents = new List<{{EventName}}__e>(); List<{{EventName}}__e> deleteEvents = new List<{{EventName}}__e>(); for ({{EventName}}__e event : events) { switch on event.Operation__c { when 'CREATE' { createEvents.add(event); } when 'UPDATE' { updateEvents.add(event); } when 'DELETE' { deleteEvents.add(event); } } } // Process each operation type in bulk if (!createEvents.isEmpty()) { handleBulkCreate(createEvents); } if (!updateEvents.isEmpty()) { handleBulkUpdate(updateEvents); } if (!deleteEvents.isEmpty()) { handleBulkDelete(deleteEvents); } } /** * @description Bulk create handler * @param events CREATE events */ private static void handleBulkCreate(List<{{EventName}}__e> events) { List<{{TargetObject}}__c> newRecords = new List<{{TargetObject}}__c>(); for ({{EventName}}__e event : events) { Map payload = parsePayload(event.Payload__c); {{TargetObject}}__c record = new {{TargetObject}}__c(); // Map fields from payload // record.Name = (String) payload.get('name'); // record.External_Id__c = event.Record_Id__c; newRecords.add(record); } if (!newRecords.isEmpty()) { // Use Database.insert for partial success handling Database.SaveResult[] results = Database.insert(newRecords, false); logDmlResults(results, 'CREATE'); } } /** * @description Bulk update handler * @param events UPDATE events */ private static void handleBulkUpdate(List<{{EventName}}__e> events) { // Collect external IDs to query Set externalIds = new Set(); Map eventsByExternalId = new Map(); for ({{EventName}}__e event : events) { externalIds.add(event.Record_Id__c); eventsByExternalId.put(event.Record_Id__c, event); } // Query existing records /* Map recordsByExternalId = new Map(); for ({{TargetObject}}__c record : [ SELECT Id, External_Id__c, Name FROM {{TargetObject}}__c WHERE External_Id__c IN :externalIds WITH USER_MODE ]) { recordsByExternalId.put(record.External_Id__c, record); } // Update records List<{{TargetObject}}__c> toUpdate = new List<{{TargetObject}}__c>(); for (String extId : externalIds) { if (recordsByExternalId.containsKey(extId)) { {{TargetObject}}__c record = recordsByExternalId.get(extId); {{EventName}}__e event = eventsByExternalId.get(extId); Map payload = parsePayload(event.Payload__c); // Update fields // record.Name = (String) payload.get('name'); toUpdate.add(record); } } if (!toUpdate.isEmpty()) { Database.SaveResult[] results = Database.update(toUpdate, false); logDmlResults(results, 'UPDATE'); } */ } /** * @description Bulk delete handler * @param events DELETE events */ private static void handleBulkDelete(List<{{EventName}}__e> events) { Set externalIds = new Set(); for ({{EventName}}__e event : events) { externalIds.add(event.Record_Id__c); } /* List<{{TargetObject}}__c> toDelete = [ SELECT Id FROM {{TargetObject}}__c WHERE External_Id__c IN :externalIds WITH USER_MODE ]; if (!toDelete.isEmpty()) { Database.DeleteResult[] results = Database.delete(toDelete, false); logDeleteResults(results, 'DELETE'); } */ } /** * @description Parse JSON payload to Map * @param payloadJson JSON string * @return Parsed Map */ private static Map parsePayload(String payloadJson) { if (String.isBlank(payloadJson)) { return new Map(); } try { return (Map) JSON.deserializeUntyped(payloadJson); } catch (JSONException e) { System.debug(LoggingLevel.ERROR, 'Failed to parse payload: ' + e.getMessage()); return new Map(); } } /** * @description Log DML results for monitoring * @param results Database.SaveResult array * @param operation Operation name */ private static void logDmlResults(Database.SaveResult[] results, String operation) { Integer successCount = 0; Integer failCount = 0; for (Database.SaveResult sr : results) { if (sr.isSuccess()) { successCount++; } else { failCount++; for (Database.Error err : sr.getErrors()) { System.debug(LoggingLevel.ERROR, operation + ' failed: ' + err.getStatusCode() + ' - ' + err.getMessage()); } } } System.debug(LoggingLevel.INFO, operation + ' results - Success: ' + successCount + ', Failed: ' + failCount); } /** * @description Log delete results for monitoring * @param results Database.DeleteResult array * @param operation Operation name */ private static void logDeleteResults(Database.DeleteResult[] results, String operation) { Integer successCount = 0; Integer failCount = 0; for (Database.DeleteResult dr : results) { if (dr.isSuccess()) { successCount++; } else { failCount++; for (Database.Error err : dr.getErrors()) { System.debug(LoggingLevel.ERROR, operation + ' failed: ' + err.getStatusCode() + ' - ' + err.getMessage()); } } } System.debug(LoggingLevel.INFO, operation + ' results - Success: ' + successCount + ', Failed: ' + failCount); } }