Trigger Name: SubscriptionTrigger¶
Last Updated: 2025-10-22 Source Code: https://github.com/AANP-IT/I2C.Salesforce.Metadata/blob/STAGING/force-app/main/default/triggers/SubscriptionTrigger.trigger
API Name: SubscriptionTrigger Object: Subscription__c (Custom Object) Pattern: Handler Pattern with Switch Statement
Business Purpose¶
This trigger manages Subscription__c lifecycle events to synchronize community memberships with Higher Logic. When subscriptions for community products are created or updated, it automatically enqueues async jobs to update the Account.Higher_Logic_Communities__c field, ensuring community access is properly provisioned in the external Higher Logic platform.
Trigger Events¶
This trigger fires on the following events: - ☐ Before Insert - ☐ Before Update - ☐ Before Delete - ☑️ After Insert - ☑️ After Update - ☐ After Delete - ☐ After Undelete
Trigger Handler¶
Handler Class: SubscriptionTriggerHandler.cls Pattern: Handler with Static Methods and Switch Statement Entry Point: Switch statement calls static handler method
trigger SubscriptionTrigger on Subscription__c (
after insert, after update
) {
switch on Trigger.operationType{
when AFTER_Insert,AFTER_Update {
SubscriptionTriggerHandler.syncCommunities(Trigger.newMap);
}
}
}
Process Flow by Event¶
After Insert¶
Purpose: Sync new subscriptions to Higher Logic communities
Business Logic: 1. Check if handler already ran (recursion prevention) 2. Create I2C_QueueableCommunitiesSync with subscription records 3. Enqueue Queueable job to sync communities asynchronously
Methods Called:
- SubscriptionTriggerHandler.syncCommunities(Map<Id, Subscription__c> subscriptionNewMap)
- I2C_QueueableCommunitiesSync (Queueable class)
After Update¶
Purpose: Sync subscription updates to Higher Logic communities
Business Logic: 1. Same process as After Insert 2. Queueable job processes subscription changes 3. Updates Account.Higher_Logic_Communities__c field
Methods Called:
- SubscriptionTriggerHandler.syncCommunities(Map<Id, Subscription__c> subscriptionNewMap)
- I2C_QueueableCommunitiesSync (Queueable class)
Key Business Rules¶
Validation Rules¶
- Only processes subscriptions for community products (Family = 'Communities')
- Subscription Product2 Name added to Account.Higher_Logic_Communities__c
- Multiple communities stored as semicolon-separated list
Field Updates¶
Account.Higher_Logic_Communities__c: Semicolon-separated list of community namesAccount.HL__c: Boolean flag set to true if communities exist
Related Record Operations¶
- Account records updated with community memberships
- Higher Logic platform provisioned with community access (external)
Bulkification & Governor Limits¶
Bulkified: Partial Max Records Handled: Limited by Queueable job limits SOQL Queries: 2 in handler (Product2 and Account queries) DML Operations: 1 in handler (Account update)
Bulkification Strategy¶
- Trigger passes all subscriptions to handler as map
- Handler enqueues single Queueable job
- Queueable processes subscriptions in bulk
- Queries Product2 and Account records in bulk
- Single DML to update Accounts
Governor Limit Considerations¶
- Queueable Limit: 1 Queueable job per trigger execution
- SOQL: 2 queries (Product2, Account)
- DML: 1 DML statement (Account update)
- Recursion: Static boolean prevents re-execution
Recursion Prevention¶
Strategy: Static boolean flag in handler class
Implementation:
public static Boolean alreadyRan = false;
public static void syncCommunities(Map<Id, Subscription__c> subscriptionNewMap){
if(!alreadyRan){
alreadyRan = true;
I2C_QueueableCommunitiesSync q = new I2C_QueueableCommunitiesSync(subscriptionNewMap);
System.enqueueJob(q);
}
}
Scenarios: - Prevents re-execution within same transaction - Does not prevent cross-transaction recursion - Queueable runs in separate transaction (avoids same-transaction recursion)
Execution Order & Dependencies¶
Order of Execution Impact¶
- After Insert/Update: Runs after validation rules
- Queueable execution happens asynchronously after transaction commits
Dependent Triggers¶
- AccountTrigger: Could be impacted by Account updates
- Risk: AccountTrigger might update Accounts, creating potential circular dependency
Dependent Processes¶
- I2C_QueueableCommunitiesSync: Async community sync logic
- Higher Logic Integration: External platform for community access
- Account community provisioning
Error Handling¶
Strategy: Static boolean flag prevents errors from recursion
User Experience: - Success: Subscription saves, communities synced asynchronously - Validation Error: Standard Salesforce errors - System Error: Full transaction rollback, Queueable not enqueued
Logging: - Logging likely in I2C_QueueableCommunitiesSync - No explicit logging in trigger/handler
Rollback Behavior: - Subscription save rollback on errors - Queueable job not enqueued if transaction fails - Queueable failures don't rollback subscription
Dependencies¶
Apex Classes¶
SubscriptionTriggerHandler: Handler with static methodsI2C_QueueableCommunitiesSync: Queueable job for community syncSubscriptionTriggerHandler.updateAccountCommunities: Helper method
Salesforce Objects¶
Subscription__c: Custom object (primary)Account: Standard object (updated)Product2: Standard object (queried for community names)
Custom Settings/Metadata¶
- None visible
External Systems¶
- Higher Logic: Community management platform
Testing¶
Test Class: SubscriptionTriggerHandlerTest.cls (likely) Coverage: Unknown
Test Scenarios: - Single subscription insert for community product - Bulk subscription insert (200 records) - Subscription update - Non-community product subscriptions (should be skipped) - Multiple subscriptions per Account - Queueable job execution - Recursion prevention
Performance Considerations¶
Average Execution Time: Fast (enqueues Queueable) Max Records Processed: Queueable limit of 50 per transaction (org-wide) Async Processing: Yes - Queueable for community sync
Optimization Opportunities: - Already optimized with Queueable pattern - Monitor Queueable job limits in high-volume scenarios - Consider Platform Events for complete decoupling
Changes & History¶
- Author: Original implementation (team maintained)
- Pattern: Hybrid switch statement with handler static methods
Pre-Go-Live Concerns¶
CRITICAL - Fix Before Go-Live¶
- Queueable Limit Risk: Only 50 Queueable jobs per transaction org-wide. High subscription volume could hit limits
- No Error Handling: No try-catch around Queueable enqueue
- Recursion Risk: Static boolean only prevents same-transaction recursion
HIGH - Address Soon After Go-Live¶
- No Logging: No audit trail of community sync operations
- Hard-coded Product Family: 'Communities' product family hard-coded in handler
- Higher Logic Failure Handling: No retry if Higher Logic integration fails
- Account Update Recursion: AccountTrigger could update Subscription__c creating circular dependency
MEDIUM - Future Enhancement¶
- Trigger Settings: Custom metadata to enable/disable trigger
- Event-Driven Architecture: Consider Platform Events instead of Queueable
- Better Error Messages: User-friendly messages for sync failures
- Community Sync Status: Track sync status on Subscription records
LOW - Monitor¶
- Queueable Job Queue: Monitor Queueable job execution times
- Higher Logic API Performance: Track external API response times
- Account Field Length: Monitor Higher_Logic_Communities__c doesn't exceed field length
Maintenance Notes¶
Complexity: Medium Recommended Review Schedule: Quarterly
Key Maintainer Notes: - This trigger uses Queueable for async Higher Logic integration - Static boolean prevents same-transaction recursion only - Handler method is static (no instance state) - I2C_QueueableCommunitiesSync contains actual sync logic - Queueable jobs have org-wide limit of 50 per transaction - Always test with bulk operations and Queueable job monitoring - Higher Logic integration may have its own rate limits
Deactivation Instructions: Add custom metadata check in trigger:
trigger SubscriptionTrigger on Subscription__c (after insert, after update) {
if (TriggerSettings__mdt.getInstance('Subscription')?.Disabled__c == true) {
return;
}
switch on Trigger.operationType{
when AFTER_Insert,AFTER_Update {
SubscriptionTriggerHandler.syncCommunities(Trigger.newMap);
}
}
}
Higher Logic Integration Notes: - External platform for community management - API credentials/configuration likely in Custom Metadata or Named Credentials - Test integration thoroughly in sandbox - Document Higher Logic API error codes and handling - Monitor API limits and quotas