Trigger Name: WorksiteTrigger¶
Last Updated: 2025-10-22 Source Code: https://github.com/AANP-IT/I2C.Salesforce.Metadata/blob/STAGING/force-app/main/default/triggers/WorksiteTrigger.trigger
API Name: WorksiteTrigger Object: PracticeSite__c (Custom Object - Worksite) Pattern: Monolithic (Logic in Trigger)
Business Purpose¶
This trigger geocodes PracticeSite__c (worksite) addresses by calling an external geocoding service to populate latitude and longitude coordinates. When practice sites are created or their addresses are updated, it automatically initiates batch geocoding to enable location-based features like maps, proximity searches, and territory management.
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: None (Monolithic pattern) Pattern: Monolithic - All logic in trigger file Entry Point: Direct trigger logic execution
trigger WorksiteTrigger on PracticeSite__c (after insert, after update) {
// Logic directly in trigger (not extracted to handler)
}
Process Flow by Event¶
After Insert¶
Purpose: Geocode newly created practice sites with complete addresses
Conditional Logic: - Filters: Only non-anonymized practice sites (Anonymized__c = false) - Address Validation: Only sites with complete addresses (Street, City, Country populated)
Business Logic: 1. Filter out anonymized practice sites 2. Call SObjectTriggerHandler.getObjectsWithAddresses() to find sites with complete addresses 3. If sites with addresses exist, create GeolocationServiceBatchable instance 4. Execute batch job with 100 records per batch 5. Batch job calls external geocoding service to populate Latitude and Longitude
Methods Called:
- SObjectTriggerHandler.getObjectsWithAddresses() - Filters for complete addresses
- GeolocationServiceBatchable - Batch class for geocoding
Field Updates:
- Address__Latitude__s: Populated by batch job
- Address__Longitude__s: Populated by batch job
After Update¶
Purpose: Re-geocode practice sites when address fields change
Conditional Logic: - Fires When: Street, City, State, or Country fields change - Filters: Only non-anonymized practice sites (Anonymized__c = false) - Address Validation: Only sites with complete addresses
Business Logic: 1. Call SObjectTriggerHandler.getObjectsWithUpdatedAddresses() to find sites with address changes 2. Filter out anonymized practice sites 3. If sites with changed addresses exist, create GeolocationServiceBatchable instance 4. Execute batch job with 100 records per batch 5. Batch job calls external geocoding service to update Latitude and Longitude
Methods Called:
- SObjectTriggerHandler.getObjectsWithUpdatedAddresses() - Detects address field changes
- GeolocationServiceBatchable - Batch class for geocoding
Key Business Rules¶
Validation Rules¶
- Only geocode non-anonymized practice sites (Anonymized__c = false)
- Address must have Street, City, and Country populated
- State is optional for geocoding
Field Updates¶
Address__Latitude__s: Decimal coordinate from geocoding serviceAddress__Longitude__s: Decimal coordinate from geocoding service
Related Record Operations¶
- No direct related record updates
- Geocoded coordinates enable downstream location-based features
Bulkification & Governor Limits¶
Bulkified: Yes (via Batch Apex) Max Records Handled: Unlimited (batch processing) SOQL Queries: 0 in trigger DML Operations: 0 in trigger (DML in batch job)
Bulkification Strategy¶
- Trigger filters and collects worksites needing geocoding
- Batch Apex processes geocoding asynchronously
- Batch size of 100 worksites per batch
- External service callouts handled in batch context
Governor Limit Considerations¶
- Batch Apex: No limit on total records (batched)
- Callouts: 100 callouts per batch execution (batch size matches)
- Async Jobs: 5 active batch jobs per org
- DML: Batch job performs DML on worksites
Recursion Prevention¶
Strategy: None explicitly implemented
Implementation: - No static variables or recursion flags - Batch job updates cause trigger to fire again - RECURSION RISK: If batch updates latitude/longitude, trigger fires again on address fields
Scenarios: - Insert -> Batch geocode -> Update lat/long -> Trigger fires again (possible loop) - Need to verify SObjectTriggerHandler.getObjectsWithUpdatedAddresses() doesn't include lat/long changes
Execution Order & Dependencies¶
Order of Execution Impact¶
- After Insert/Update: Runs after validation rules
- Batch job executes asynchronously after transaction commits
Dependent Triggers¶
- None directly
Dependent Processes¶
- GeolocationServiceBatchable: Batch job for geocoding
- SObjectTriggerHandler: Helper for address filtering
- External geocoding service (Google Maps API, similar)
- Location-based features consuming coordinates
Error Handling¶
Strategy: Batch Apex error handling
User Experience: - Success: Practice site saves, geocoding happens asynchronously - Validation Error: Standard Salesforce errors - Geocoding Error: Batch job failures logged, coordinates not populated
Logging: - Batch job logging (Apex Jobs monitoring) - Geocoding service errors logged in batch execute method
Rollback Behavior: - Practice site insert/update commits regardless of batch outcome - Batch failures don't rollback practice site changes - Failed batches can be monitored and retried
Dependencies¶
Apex Classes¶
SObjectTriggerHandler: Address filtering utilitiesGeolocationServiceBatchable: Batch geocoding logic
Salesforce Objects¶
PracticeSite__c: Custom object (primary)
Custom Settings/Metadata¶
- Geocoding service credentials (Named Credential or Custom Setting)
External Systems¶
- Geocoding Service: External API (e.g., Google Maps Geocoding API)
Testing¶
Test Class: GeolocationServiceTest.cls, SObjectTriggerHandlerTest.cls Coverage: Unknown
Test Scenarios: - Single practice site insert with address - Bulk practice site insert (200+ records) - Practice site address update - Non-anonymized vs anonymized practice sites - Complete vs incomplete addresses - Batch job execution and callout mocking - Geocoding service error handling
Performance Considerations¶
Average Execution Time: Fast (trigger enqueues batch) Max Records Processed: Unlimited (batch processing) Async Processing: Yes - Batch Apex for geocoding
Optimization Opportunities: - Already optimized with batch processing - Monitor batch job queue - Consider batch size adjustment based on geocoding service rate limits - Cache frequently geocoded addresses
Changes & History¶
- Author: Original implementation (team maintained)
- Pattern: Monolithic trigger (anti-pattern, should be refactored)
Pre-Go-Live Concerns¶
CRITICAL - Fix Before Go-Live¶
- Recursion Risk: Batch updates could trigger recursion if address fields modified
- Monolithic Pattern: All logic in trigger file (anti-pattern, difficult to test/maintain)
- No Error Handling: Batch job failures not handled in trigger context
- External Service Dependency: Geocoding service failure causes coordinate population failure
HIGH - Address Soon After Go-Live¶
- No Trigger Bypass: Cannot disable geocoding without trigger deployment
- Rate Limiting: No protection against geocoding service rate limits
- Cost Management: External API calls may have costs per geocode
- Anonymous Sites Filter: Anonymized__c filter happens after batch creation (inefficient)
MEDIUM - Future Enhancement¶
- Refactor to Handler Pattern: Move logic to handler class for testability
- Add Trigger Settings: Custom metadata to enable/disable
- Selective Geocoding: Only geocode if coordinates empty (avoid re-geocoding)
- Error Notifications: Alert admins when geocoding fails
- Caching: Cache geocoded addresses to reduce API calls
LOW - Monitor¶
- Batch Job Queue: Monitor batch job execution times and failures
- API Costs: Track geocoding API usage and costs
- Coordinate Accuracy: Validate geocoding accuracy
- Performance: Monitor with high-volume practice site creation
Maintenance Notes¶
Complexity: Medium-High (due to batch processing and external service) Recommended Review Schedule: Quarterly
Key Maintainer Notes: - ANTI-PATTERN: Logic directly in trigger (should be in handler class) - Geocoding happens asynchronously via batch job - coordinates not immediate - Batch size is 100 (matches callout governor limit) - External service dependency - test with mock callouts - Anonymized sites never geocoded (privacy feature) - Address must have Street, City, Country minimum (State optional) - Recursion risk if batch job modifies address fields - Always test batch job execution with Test.startTest()/Test.stopTest()
Deactivation Instructions: Monolithic triggers are difficult to disable. Options:
-
Add conditional at start:
-
Deploy empty trigger body to disable
Refactoring Recommendations: - Extract logic to WorksiteTriggerHandler class - Implement TriggerHandler framework pattern - Add recursion prevention with static boolean - Move batch job creation to handler - Add comprehensive test coverage - Implement error logging