Class Name: OrderItemSummaryTriggerHandler¶
Last Updated: 2025-10-22 Source Code: https://github.com/AANP-IT/I2C.Salesforce.Metadata/blob/STAGING/force-app/main/default/classes/OrderItemSummaryTriggerHandler.cls
API Name: OrderItemSummaryTriggerHandler Type: Trigger Handler (Change Data Capture) Test Coverage: Target 85%+
Business Purpose¶
The OrderItemSummaryTriggerHandler class handles Platform Events for OrderItemSummaryChangeEvent, specifically triggering automated logic when order items are cancelled in the Order Management system. This handler enables near-real-time processing of order cancellations by:
- Listening to OrderItemSummary change events
- Delegating to CanceledOrderLogic for cancellation processing
- Supporting asynchronous, event-driven order management workflows
Class Overview¶
- Author: Ryan O'Sullivan
- Created: 2025-01-22
- Scope/Sharing:
with sharing- Respects record-level security - Extends:
TriggerHandler- Base trigger framework class - Supported Events:
afterInsertonly (change event pattern) - Key Responsibilities:
- Receive OrderItemSummaryChangeEvent notifications
- Route events to cancellation processing logic
- Maintain separation between trigger infrastructure and business logic
Why Change Events?¶
This handler uses Salesforce Platform Events (OrderItemSummaryChangeEvent) rather than traditional triggers because:
- Decoupling: Separates event capture from processing
- Asynchronous: Processing can happen after transaction commits
- Scalability: Handles high-volume order cancellations without blocking user transactions
- Retry Logic: Failed event processing can be retried automatically
- Multi-Org: Events can be published across org boundaries
Public Methods¶
afterInsert¶
Purpose: Handles OrderItemSummaryChangeEvent after insert, delegating to cancellation logic.
Parameters:
- newRecordsMap (Map
Returns: void
Business Logic:
1. Event Reception (line 10): Receives change event map from Platform Event framework
2. Type Casting (line 11): Casts Map<Id, SObject> to Map<Id, OrderItemSummaryChangeEvent>
3. Delegation (line 11): Passes events to CanceledOrderLogic.run() for processing
Implementation Details:
protected override void afterInsert(Map<Id, SObject> newRecordsMap) {
CanceledOrderLogic.run((Map<Id,OrderItemSummaryChangeEvent>)newRecordsMap);
}
Issues/Concerns:
- ⚠️ Unchecked Type Cast: Line 11 casts without validation (could throw ClassCastException)
- ⚠️ No Null Check: Doesn't verify newRecordsMap is non-null
- ⚠️ No Error Handling: No try-catch around delegation call
- ⚠️ No Event Filtering: Passes ALL events regardless of Status or other criteria
- May process events for Active, Fulfilled, or other non-cancellation statuses
- Filtering likely happens in CanceledOrderLogic
- ✅ Clean Separation: Delegates to business logic class rather than implementing inline
- ✅ Minimal Handler: Keeps trigger handler simple and focused
Event Flow:
1. OrderItemSummary record updated (e.g., Status → 'Canceled')
↓
2. Salesforce publishes OrderItemSummaryChangeEvent
↓
3. OrderItemSummaryTriggerHandler.afterInsert() receives event
↓
4. CanceledOrderLogic.run() processes cancellation
↓
5. Business logic executes (refunds, notifications, etc.)
Recommended Improvements:
protected override void afterInsert(Map<Id, SObject> newRecordsMap) {
if (newRecordsMap == null || newRecordsMap.isEmpty()) {
return;
}
try {
// Validate event type before casting
if (newRecordsMap.values()[0] instanceof OrderItemSummaryChangeEvent) {
Map<Id, OrderItemSummaryChangeEvent> eventMap =
(Map<Id, OrderItemSummaryChangeEvent>)newRecordsMap;
CanceledOrderLogic.run(eventMap);
} else {
System.debug(LoggingLevel.ERROR, 'Unexpected event type: ' + newRecordsMap.values()[0].getSObjectType());
}
} catch (Exception e) {
System.debug(LoggingLevel.ERROR, 'Error processing OrderItemSummaryChangeEvent: ' + e.getMessage());
// Consider inserting error log record for monitoring
}
}
Trigger Context¶
Supported Operations¶
- afterInsert: ✅ Implemented (line 10)
- beforeInsert: ❌ Not applicable (change events are read-only)
- beforeUpdate: ❌ Not applicable (change events don't support updates)
- afterUpdate: ❌ Not applicable (change events are insert-only)
- beforeDelete: ❌ Not applicable (change events are immutable)
- afterDelete: ❌ Not applicable (change events are immutable)
Why Only afterInsert?¶
Platform Events (including Change Events) only support afterInsert because:
- Immutable: Events cannot be modified once published
- Fire-and-Forget: Events are published and consumed, not updated or deleted
- Asynchronous: Processing happens after the publishing transaction commits
Dependencies¶
Salesforce Objects¶
OrderItemSummaryChangeEvent (Platform Event)¶
- Type: Standard Change Event for OrderItemSummary
- Fields: Contains changed fields from OrderItemSummary record
Id,Status,OrderSummaryId, etc.- Only changed fields are populated in event payload
- Access: Subscribe (automatic via trigger)
OrderItemSummary (Standard Object - Order Management)¶
- Relationship: Change Event represents changes to this object
- Fields:
Id,Status,OrderSummaryId,Quantity, etc. - Trigger: This handler processes changes to OrderItemSummary records
Custom Settings/Metadata¶
- None directly (may be used by
CanceledOrderLogic)
Other Classes¶
- TriggerHandler (Base Class):
- Framework for trigger orchestration
- Provides
afterInsert()override method - Manages trigger context (Trigger.new, Trigger.old, etc.)
- CanceledOrderLogic:
- Business logic for order cancellations
- Processes OrderItemSummaryChangeEvents
- Likely handles refunds, notifications, inventory updates
External Services¶
- None directly (may be invoked by
CanceledOrderLogic)
Design Patterns¶
- Trigger Handler Pattern: Extends
TriggerHandlerbase class for consistent trigger management - Separation of Concerns: Delegates business logic to dedicated service class
- Event-Driven Architecture: Uses Platform Events for asynchronous processing
- Single Responsibility: Handler only routes events, doesn't implement logic
- Change Data Capture (CDC): Leverages Salesforce CDC for OrderItemSummary changes
Governor Limits Considerations¶
Current Impact (Per Event Batch)¶
- Platform Event Consumption: Receives up to 2,000 events per batch
- SOQL Queries: 0 (delegated to CanceledOrderLogic)
- DML Statements: 0 (delegated to CanceledOrderLogic)
- CPU Time: Minimal (type cast + method call only)
- Heap Size: Minimal (map reference passed)
Platform Event Limits¶
- Event Publication: 250,000 events/day (not relevant here - consumption only)
- Event Consumption: Auto-scaled by Salesforce
- Replay Window: 72 hours (events retained for replay if subscriber fails)
- Delivery: At-least-once delivery guarantee (duplicates possible)
Scalability Analysis¶
- ✅ Asynchronous Processing: Doesn't block user transactions
- ✅ Auto-Scaling: Salesforce manages event processing capacity
- ⚠️ Bulk Processing: Handler must process events in bulk efficiently
- ⚠️ Duplicate Events: At-least-once delivery means same event may process multiple times
CanceledOrderLogicmust be idempotent
Event Processing Best Practices¶
- Idempotency: Ensure
CanceledOrderLogichandles duplicate events gracefully - Error Handling: Failed events are retried automatically
- Monitoring: Track event processing latency via Event Log Files
- Replay: Use ReplayId to replay events from specific point in time
Error Handling¶
Exception Types Thrown¶
- ClassCastException: If
newRecordsMapcontains wrong event type - NullPointerException: If
newRecordsMapis null (unlikely but possible)
Exception Types Caught¶
- None - No try-catch blocks
Error Handling Strategy¶
- No Local Handling: Exceptions bubble up to Platform Event framework
- Framework Retry: Failed events automatically retried by Salesforce
- Dead Letter Queue: After 3 failed attempts, events move to error queue
- Monitoring: Use Event Log Files and Event Monitoring to track failures
Error Handling Gaps¶
- No Exception Logging: Failures not logged locally for debugging
- No Custom Retry Logic: Relies entirely on platform retry mechanism
- No Circuit Breaker: No protection against repeated failures
- No Dead Letter Handling: No custom logic for permanently failed events
Recommended Monitoring¶
// Query event delivery failures
SELECT EventType, ReplayId, CreatedDate, CreatedById
FROM EventLogFile
WHERE EventType = 'OrderItemSummaryChangeEvent'
AND LogDate = TODAY
AND Status = 'Failed'
// Monitor event processing latency
SELECT AVG(Duration), MAX(Duration)
FROM EventLogFile
WHERE EventType = 'OrderItemSummaryChangeEvent'
AND LogDate = LAST_N_DAYS:7
Security Considerations¶
Sharing Model¶
- WITH SHARING: Respects record-level security
- Implication: Event processing runs in context of automated process user
- Change Events: Delivered regardless of user's record access
- Security must be enforced in
CanceledOrderLogicif needed
Event Security¶
- Subscribe Access: Requires "View All Data" or specific event permissions
- Event Payload: Contains only changed fields (not full record)
- Sensitive Data: Change events may contain PII or financial data
- Ensure proper handling in downstream logic
Best Practices¶
- Field-Level Security: Validate FLS in
CanceledOrderLogicif exposing data - Audit Trail: Log event processing for compliance
- Data Masking: Mask sensitive fields before logging
Test Class Requirements¶
Required Test Coverage¶
@IsTest
public class OrderItemSummaryTriggerHandlerTest {
@IsTest
static void testAfterInsert_SingleEvent() {
// Note: Testing Platform Events requires specific setup
// This is a simplified example
Test.startTest();
// Create test OrderItemSummary (if possible in test context)
// Or create mock change event
// Publish change event
// OrderItemSummaryChangeEvent event = new OrderItemSummaryChangeEvent(
// Status__c = 'Canceled'
// );
// EventBus.publish(event);
Test.stopTest();
// Verify CanceledOrderLogic was called
// This requires mocking or observable side effects
}
@IsTest
static void testAfterInsert_BulkEvents() {
// Test with multiple events
Test.startTest();
// Publish multiple change events
// List<OrderItemSummaryChangeEvent> events = new List<OrderItemSummaryChangeEvent>();
// for (Integer i = 0; i < 200; i++) {
// events.add(new OrderItemSummaryChangeEvent(Status__c = 'Canceled'));
// }
// EventBus.publish(events);
Test.stopTest();
// Verify bulk processing
}
@IsTest
static void testAfterInsert_ErrorHandling() {
// Test error scenarios
// Force CanceledOrderLogic to throw exception
// Verify event retry mechanism
Test.startTest();
// Trigger error condition
Test.stopTest();
// Verify error was handled appropriately
}
@IsTest
static void testTriggerHandler_OnlyAfterInsertSupported() {
// Verify no other trigger contexts are implemented
OrderItemSummaryTriggerHandler handler = new OrderItemSummaryTriggerHandler();
// beforeInsert, afterUpdate, etc. should not be overridden
// Reflection-based test to verify only afterInsert is implemented
}
}
Test Data Requirements¶
- OrderItemSummary: Requires Commerce Cloud Order Management
- OrderItemSummaryChangeEvent: Platform Event (test framework handles)
- CanceledOrderLogic Dependencies: Any objects/data that logic requires
Testing Challenges¶
- Platform Events: Difficult to test in unit tests
- Change Events: Cannot be manually created (published by system)
- Asynchronous Processing: May need
Test.getEventBus().deliver()in tests - CanceledOrderLogic: May need mocking if complex
Changes & History¶
| Date | Author | Description |
|---|---|---|
| 2025-01-22 | Ryan O'Sullivan | Initial implementation for OrderItemSummary change event handling |
| (Current) | - | Documentation added |
Pre-Go-Live Concerns¶
CRITICAL¶
- No Error Handling: Uncaught exceptions cause event retry loop
- Add try-catch with error logging
- Prevent infinite retry on persistent errors
HIGH¶
- No Event Filtering: Processes ALL OrderItemSummary changes
- Verify
CanceledOrderLogicfilters to Status='Canceled' events only - Consider filtering in handler to reduce processing overhead
- No Duplicate Detection: At-least-once delivery guarantee
- Ensure
CanceledOrderLogicis idempotent - Add duplicate event detection logic
MEDIUM¶
- No Type Validation: Unsafe cast on line 11
- Add instanceof check before casting
- No Monitoring: No custom logging or metrics
- Add structured logging for event processing
- Track processing latency and failure rates
LOW¶
- No Comments: Minimal inline documentation
- Add javadoc comments for method
- Test Coverage: Platform Event testing may be incomplete
- Ensure integration testing covers event end-to-end
Maintenance Notes¶
📋 Monitoring Recommendations¶
- Event Delivery: Monitor Event Log Files for failed deliveries
- Processing Latency: Track time from event publication to processing completion
- Error Rate: Alert on high failure rates for this event type
- Retry Volume: Monitor events being retried (indicates persistent issues)
🔧 Debugging Tips¶
// View recent OrderItemSummaryChangeEvent records
// (Events are retained for 72 hours)
SELECT Id, ReplayId, CreatedDate, Status__c, OrderSummaryId__c
FROM OrderItemSummaryChangeEvent
WHERE CreatedDate = TODAY
ORDER BY CreatedDate DESC
LIMIT 100
// Check Platform Event Allocations
SELECT DurableId, EventType, AllocatedEventDeliveries
FROM PlatformEventUsageMetric
WHERE EventType = 'OrderItemSummaryChangeEvent'
⚠️ Breaking Change Risks¶
- Modifying
afterInsertsignature breaksTriggerHandlercontract - Changing event processing logic in
CanceledOrderLogicaffects behavior - Disabling change events stops cancellation automation
🔗 Related Components¶
- TriggerHandler: Base trigger framework class
- CanceledOrderLogic: Business logic for order cancellations
- OrderItemSummary: Source object for change events
- OrderItemSummaryChangeEvent: Platform Event for OrderItemSummary changes
- Order Management Flows: Fulfillment and cancellation workflows
Business Owner¶
Primary Contact: Order Management / Fulfillment Team Technical Owner: Ryan O'Sullivan / Salesforce Development Team Created: 2025-01-22 Last Reviewed: [Date]
Documentation Status: ✅ Complete Code Review Status: ⚠️ Requires error handling and event filtering Test Coverage: Target 85%+ (Platform Event testing may require special setup) Order Management Dependency: Requires Commerce Cloud Order Management