Skip to content

Trigger Name: BuyerGroupPricebookTrigger

Last Updated: 2025-10-22 Source Code: https://github.com/AANP-IT/I2C.Salesforce.Metadata/blob/STAGING/force-app/main/default/triggers/BuyerGroupPricebookTrigger.trigger

API Name: BuyerGroupPricebookTrigger Object: BuyerGroupPricebook Pattern: Logic-Free Handler Pattern

Business Purpose

This trigger maintains product visibility for buyer groups by automatically updating Product2 records when BuyerGroupPricebook associations are created or modified. It ensures that products associated with specific pricebooks become visible to the corresponding buyer groups for B2B Commerce operations, enabling proper catalog segmentation across different customer segments.

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: BuyerGroupPricebookHelper.cls Pattern: Logic-Free - Trigger only routes to helper class Entry Point: Direct helper method call after insert/update

trigger BuyerGroupPricebookTrigger on BuyerGroupPricebook (after insert, after update) {
    if (Trigger.isAfter && (Trigger.isInsert || Trigger.isUpdate)) {
        BuyerGroupPricebookHelper.updateVisibleBuyerGroups(Trigger.new);
    }
}

Process Flow by Event

After Insert

Purpose: Add new buyer group visibility to products when pricebook assignments are created

Business Logic: 1. Extract pricebook IDs and buyer group IDs from new BuyerGroupPricebook records (only active records) 2. Query PricebookEntry records for these pricebooks to find associated products 3. Map products to their buyer groups across all pricebook associations 4. Query existing Product2 records to get current VisibleToBuyerGroups__c values 5. Merge new buyer group IDs with existing IDs (comma-separated) 6. Update Product2 records with expanded buyer group visibility

Methods Called: - BuyerGroupPricebookHelper.updateVisibleBuyerGroups(List<BuyerGroupPricebook> bgpbList)

Related Records Updated: - Product2 records with updated VisibleToBuyerGroups__c field


After Update

Purpose: Update product visibility when buyer group pricebook assignments are modified

Conditional Logic: - Fires When: Any field changes on BuyerGroupPricebook records - Only Processes: Records where IsActive = true AND both Pricebook2Id and BuyerGroupId are not null

Business Logic: 1. Same process as After Insert - recalculates product visibility 2. Merges with existing buyer group IDs already on products 3. Updates Product2 records accordingly

Methods Called: - BuyerGroupPricebookHelper.updateVisibleBuyerGroups(List<BuyerGroupPricebook> bgpbList)


Key Business Rules

Validation Rules

  • Only active BuyerGroupPricebook records (IsActive = true) are processed
  • Both Pricebook2Id and BuyerGroupId must be populated
  • Buyer group IDs are stored as comma-separated strings on Product2

Field Updates

  • Product2.VisibleToBuyerGroups__c: Comma-separated list of buyer group IDs that can see the product
  • Product2 records updated based on PricebookEntry associations
  • Multiple pricebooks can contribute buyer groups to the same product
  • Existing buyer groups are preserved (additive only, no removal)

Bulkification & Governor Limits

Bulkified: Yes Max Records Handled: Up to 200 BuyerGroupPricebook records SOQL Queries: 2 per transaction (PricebookEntry query, Product2 query) DML Operations: 1 per transaction (Product2 update)

Bulkification Strategy

  • Collects all pricebook IDs and buyer group IDs into Sets
  • Single SOQL query for all PricebookEntry records across all pricebooks
  • Single SOQL query for all Product2 records needing updates
  • Single DML operation to update all Product2 records
  • All processing uses maps and sets for efficient lookup

Governor Limit Considerations

  • SOQL: 2 queries per transaction regardless of record count
  • DML: 1 DML statement updating potentially many Product2 records
  • CPU Time: String parsing and manipulation for comma-separated IDs could be intensive
  • Heap Size: Large numbers of products/buyer groups could impact heap

Recursion Prevention

Strategy: None explicitly implemented

Implementation: - No static variables or recursion flags - Trigger only fires on BuyerGroupPricebook, updates Product2 - Product2 trigger (if exists) would not update BuyerGroupPricebook

Scenarios: - Low recursion risk since updates are cross-object (BuyerGroupPricebook -> Product2) - Product2 triggers should not update BuyerGroupPricebook records

Execution Order & Dependencies

Order of Execution Impact

  • After Insert/Update: Runs after validation rules and before async processes
  • Product2 updates happen synchronously in same transaction

Dependent Triggers

  • ProductTrigger: May be impacted by Product2 updates from this trigger
  • Risk: ProductTrigger could perform additional operations when VisibleToBuyerGroups__c changes

Dependent Processes

  • B2B Commerce catalog visibility
  • Product catalog filtering in storefronts
  • Any workflows/flows on Product2 object

Error Handling

Strategy: No explicit error handling

User Experience: - Success: BuyerGroupPricebook saves, Product2 updates happen synchronously - Validation Error: Standard Salesforce error messages - System Error: Full transaction rollback, error shown to user

Logging: - No logging implemented - Errors only visible in standard Salesforce error messages

Rollback Behavior: - Full transaction rollback on any error - BuyerGroupPricebook records not saved if Product2 updates fail

Dependencies

Apex Classes

  • BuyerGroupPricebookHelper: Contains all business logic

Salesforce Objects

  • BuyerGroupPricebook: Primary object being triggered
  • Pricebook2: Referenced for pricebook associations
  • PricebookEntry: Queried to find product associations
  • Product2: Updated with buyer group visibility
  • BuyerGroup: Referenced via IDs

Custom Settings/Metadata

  • None currently implemented

External Systems

  • B2B Commerce Cloud (visibility rules consumed by storefront)

Testing

Test Class: BuyerGroupPricebookHelperTest.cls Coverage: Unknown

Test Scenarios: - Single BuyerGroupPricebook insert - Bulk BuyerGroupPricebook insert (200 records) - Update existing BuyerGroupPricebook - Multiple pricebooks with same products - Multiple buyer groups per product - Inactive BuyerGroupPricebook records (should be skipped) - Products with existing VisibleToBuyerGroups__c values - String parsing with comma-separated IDs

Performance Considerations

Average Execution Time: Unknown Max Records Processed: 200 BuyerGroupPricebook records affecting potentially thousands of products Async Processing: None - all synchronous

Optimization Opportunities: - Consider async processing for large product updates - Add caching for frequently accessed pricebook/product associations - Implement batch processing for extremely large catalogs - Add field change detection to only process when relevant fields change

Changes & History

  • Author: Original implementation (team maintained)
  • Pattern: Simple logic-free trigger with helper class

Pre-Go-Live Concerns

CRITICAL - Fix Before Go-Live

  • No Error Handling: Any exception in helper class will cause full transaction rollback with no logging
  • String Parsing Vulnerability: Parsing comma-separated IDs assumes well-formed data; malformed data could cause exceptions
  • Data Integrity: No validation that parsed IDs are valid 18-character Salesforce IDs

HIGH - Address Soon After Go-Live

  • Additive Only Logic: Buyer groups are added but never removed when pricebook associations are deleted. Need delete trigger or cleanup logic
  • No Null Checks: Missing defensive null checks on Product2.VisibleToBuyerGroups__c could cause NullPointerException
  • Field Length Limits: VisibleToBuyerGroups__c could exceed field length limit with many buyer groups
  • Performance: Synchronous Product2 updates could cause timeout with large catalogs

MEDIUM - Future Enhancement

  • No Trigger Framework: Could benefit from TriggerHandler framework pattern
  • No Trigger Settings: Add Custom Metadata to enable/disable trigger
  • No Logging: Implement Custom Object logging for troubleshooting
  • Missing Before Delete: Should handle removal of buyer group associations

LOW - Monitor

  • CPU Time: String manipulation and set operations with large datasets
  • Test Coverage: Verify comprehensive test coverage exists
  • Documentation: Helper class methods need better inline documentation

Maintenance Notes

Complexity: Medium Recommended Review Schedule: Quarterly

Key Maintainer Notes: - This trigger is additive only - does NOT remove buyer groups when associations are deleted - VisibleToBuyerGroups__c is a comma-separated string field - consider changing to proper relationship - No recursion prevention since cross-object updates (BuyerGroupPricebook -> Product2) - All logic is in BuyerGroupPricebookHelper class - trigger is just a router - Always test with bulk operations (200+ records) and large product catalogs - Monitor Product2 trigger to ensure it doesn't cause cascading issues

Deactivation Instructions: Add conditional at start of trigger:

// Check custom metadata for bypass
if (TriggerSettings__mdt.getInstance('BuyerGroupPricebook')?.Disabled__c == true) {
    return;
}

Data Load Considerations: - Disable trigger during bulk pricebook loads - Pre-calculate VisibleToBuyerGroups__c values for bulk insert - Re-enable trigger after data load completes