Class Name: I2C_AutoRenewalPriceSyncBatch¶
Last Updated: 2025-10-22 Source Code: I2C_AutoRenewalPriceSyncBatch.cls
API Name: I2C_AutoRenewalPriceSyncBatch Type: Batch (Database.Batchable, Database.AllowsCallouts) Test Coverage: Not specified
Business Purpose¶
This critical batch job automatically updates pricing for all recurring payment orders due today, ensuring that price changes for membership dues and other recurring products are reflected in Chargent recurring billing. The class maintains pricing accuracy for AANP's subscription-based revenue streams by recalculating Fellow dues based on designation types and applying current promotions before payment processing.
Class Overview¶
Scope and Sharing¶
- Sharing Model: with sharing
- Access Modifier: public
- Interfaces Implemented: Database.Batchable
, Database.AllowsCallouts
Key Responsibilities¶
- Identifies Chargent recurring orders scheduled for payment today
- Recalculates current pricing using Salesforce Commerce pricing engine
- Applies special Fellow dues pricing based on member designation (Regular, Lifetime, Retired, Other)
- Updates charge amounts with current promotions and discounts
- Chains to Chargent's batch processing for payment execution
- Maintains promotion history to ensure only previously applied promotions are considered
Public Methods¶
start¶
Purpose: Queries and returns all recurring Chargent orders scheduled for payment today.
Parameters:
- bc (Database.BatchableContext): Standard batch context provided by platform
Returns:
- List<ChargentOrders__ChargentOrder__c>: All recurring orders with payment scheduled for today, including related order products and promotion adjustments
Throws: - No explicit exception handling
Usage Example:
I2C_AutoRenewalPriceSyncBatch batch = new I2C_AutoRenewalPriceSyncBatch();
Database.executeBatch(batch);
Business Logic: - Queries ChargentOrders where Payment_Status = 'Recurring' and Next_Scheduled_Payment = TODAY - Includes subquery for related order items and their adjustment line items - Returns full dataset for execute method processing
execute¶
Purpose: Recalculates pricing for each Chargent order in the batch scope and updates charge amounts.
Parameters:
- bc (Database.BatchableContext): Standard batch context
- scope (List
Returns:
- void: No return value
Throws: - No explicit exception handling
Business Logic: 1. Builds map of order-to-promotion relationships from existing order item adjustments 2. Queries active promotion targets for all products in the batch 3. For each order: - Builds pricing input with all order line items - Calls Commerce API to get current pricing (or uses test mock) - For Fellow Dues products, applies custom pricing via calculateFellowDues() - Applies percentage and fixed discounts from promotion targets - Only applies promotions previously used on the order 4. Updates Chargent order charge amounts in bulk
finish¶
Purpose: Chains to Chargent's batch processing system after pricing synchronization completes.
Parameters:
- bc (Database.BatchableContext): Standard batch context
Returns:
- void: No return value
Throws: - No explicit exception handling
Business Logic: - Instantiates ChargentOrders.TChargentBatchProcessing - Executes with batch size of 10 to process payments
calculateFellowDues¶
public static Map<Id, Decimal> calculateFellowDues(Set<Id> productIds, Id accountId, String fellowDesignation)
Purpose: Calculates custom pricing for Fellow dues products based on member designation type.
Parameters:
- productIds (SetaccountId (Id): Account being billed (not currently used)
- fellowDesignation (String): Fellow designation type (Regular, Lifetime, Retired, or Other)
Returns:
- Map<Id, Decimal>: Map of product IDs to their calculated prices
Throws:
- QueryException: If pricebook or product queries fail
Usage Example:
Set<Id> fellowProducts = new Set<Id>{prod1Id, prod2Id};
Map<Id, Decimal> prices = I2C_AutoRenewalPriceSyncBatch.calculateFellowDues(
fellowProducts,
accountId,
'Regular'
);
Business Logic: - Maps Fellow designation to specific product SKU: - Regular → P-FELO-074 - Lifetime → P-FELO-083 - Retired → P-FELO-075 - Other → P-FELO-076 - Queries 'Fellows Fees' pricebook for the designated product - Returns unit price from pricebook entry for all product IDs in the set - Returns mock price of 100.00 in test context
Private/Helper Methods¶
No private helper methods beyond the public static calculateFellowDues method.
Dependencies¶
Apex Classes¶
I2C_GetProductPricesTest: Provides mock pricing results in test contextChargentOrders.TChargentBatchProcessing: Chargent package batch for payment processing
Salesforce Objects¶
ChargentOrders__ChargentOrder__c: Chargent payment orders- Fields: Next_Scheduled_Payment__c, Payment_Status__c, Account__c, Account__r.Fellow_Designation__c, Charge_Amount__c
OrderItem: Order line items (via Recurring_Order_Products__r relationship)- Fields: Product2Id, Order.SalesStoreId, Product2.Family
OrderItemAdjustmentLineItem: Promotion adjustments- Fields: AdjustmentCauseId
PromotionTarget: Promotion configurations- Fields: AdjustmentType, AdjustmentPercent, AdjustmentAmount, TargetId, PromotionId
Product2: Product records- Fields: Family, StockKeepingUnit
Pricebook2: Fellows Fees pricebookPricebookEntry: Fellow dues pricing entries
Custom Settings/Metadata¶
- Fellows Fees pricebook (must exist with specific name)
- Product SKUs: P-FELO-074, P-FELO-075, P-FELO-076, P-FELO-083
External Services¶
ConnectApi.CommerceStorePricing: Salesforce Commerce Cloud pricing engine- Chargent payment processing system
Design Patterns¶
- Batch Processing Pattern: Implements Database.Batchable for large-scale async operations
- Chain of Responsibility: Chains to Chargent batch in finish() method
- Strategy Pattern: Different pricing strategies for regular products vs Fellow dues
- Template Method: Uses calculateFellowDues as specialized pricing calculation
- Test Seam Pattern: Uses Test.isRunningTest() to inject mock responses
Governor Limits Considerations¶
SOQL Queries: - 1 in start() for recurring orders - 1-2 in execute() for promotion targets (per batch) - 2 in calculateFellowDues() for pricebook/product lookups (per execute)
DML Operations: 1 update statement per execute() batch
CPU Time: Potentially high due to nested loops for promotion calculation
Heap Size: Depends on number of order items and promotions per order
Bulkification: Partially bulkified - collects orders for DML but processes pricing individually
Async Processing: Yes - batch processing with callouts enabled
API Callouts: 1 callout per order to Commerce pricing API (not bulkified)
Critical Concerns: - Commerce API callout per order not bulkified - could hit callout limits with large batches - calculateFellowDues queries inside execute() could approach SOQL limit - Nested loops for promotion application could cause CPU timeout with complex promotions
Error Handling¶
Strategy: Minimal error handling Logging: Debug statements only (System.debug) User Notifications: None
Implementation: - Checks pricingResults.success but only logs failure - Failed pricing results in no update for that order - No exception handling for SOQL queries - No exception handling for DML operations
Critical Gaps: - Failed pricing API calls could result in $0 charges or skipped orders - No alerting for batch failures - No retry mechanism for failed pricing calculations - Silent failures make troubleshooting difficult
Security Considerations¶
Sharing Rules: Respects sharing (with sharing keyword) Field-Level Security: Not enforced (direct SOQL and DML) CRUD Permissions: Not explicitly checked Input Validation: No validation of pricing results
Security Notes: - Runs in batch context with elevated permissions - Direct update of Chargent financial records without validation - No validation that calculated prices are reasonable - Hard-coded product SKUs could be security risk if products change
Test Class¶
Test Class: I2C_GetProductPricesTest (implied), specific test class not documented Coverage: Not specified Test Scenarios Covered: - Uses Test.isRunningTest() checks for mock responses - Mock pricing result from I2C_GetProductPricesTest.getMockPricingResult() - Mock Fellow dues pricing returns 100.00
Additional Test Scenarios Needed: - Recurring orders scheduled for today - Orders with multiple line items - Fellow designation pricing variations - Promotion discount calculations (percentage and fixed) - Failed pricing API responses - Chain to Chargent batch processing - Edge cases: $0 orders, negative amounts, missing promotions
Changes & History¶
No change history documented.
Pre-Go-Live Concerns¶
CRITICAL - Fix Before Go-Live¶
- No error handling for pricing API failures - Failed pricing calls could result in $0 charges or batch termination
- Hard-coded product SKUs - Fellow designation pricing relies on specific SKU values (P-FELO-074, etc.) that could break if products change
- Missing bulk operation safeguards - No limits on batch size could cause heap size or timeout issues
- API callouts not bulkified - One callout per order will hit limits with large batches
- SOQL queries in execute() - calculateFellowDues queries inside execute could exceed governor limits
HIGH - Address Soon After Go-Live¶
- Limited logging for pricing failures - Only debug statements for failed pricing calculations make troubleshooting difficult
- No validation of calculated prices - Negative or extreme price values aren't validated before updating charge amounts
- Test class dependencies - Mock pricing results may not reflect actual pricing complexity
- No monitoring or alerting - Finance team not notified of pricing sync failures
- Silent failure mode - Orders with failed pricing are silently skipped
MEDIUM - Future Enhancement¶
- Fellow pricing logic should be externalized - Hard-coded designation mapping should be configurable via Custom Metadata
- Promotion calculation complexity - Complex nested loops for promotion application could be optimized
- Missing batch monitoring - No alerts or notifications for batch processing failures
- Chargent batch size hardcoded - finish() method uses batch size of 10 without explanation
- No price change audit trail - Should log old vs new prices for financial reconciliation
LOW - Monitor¶
- Debug statements in production - System.debug calls should be removed or controlled by debug flags
- Potential for data inconsistency - Gap between pricing calculation and Chargent processing could cause issues
- Fellow designation values - Should validate allowed values for Fellow_Designation__c field
- Test context detection - Multiple Test.isRunningTest() checks should be consolidated
Maintenance Notes¶
Complexity: High Recommended Review Schedule: Quarterly (before membership renewal periods)
Key Maintainer Notes: - This is a mission-critical batch job for recurring revenue - failures directly impact cash flow - Requires careful testing of pricing calculations and Chargent integration before any changes - The Fellow dues pricing logic is particularly complex and should be validated with finance team - Schedule review of product SKU dependencies quarterly to ensure they still exist - Monitor batch execution during high-volume renewal periods - Consider refactoring to bulkify Commerce API callouts if volume increases - The finish() method chains to Chargent processing - don't modify without understanding implications
Critical Dependencies: - Fellows Fees pricebook must exist with exact name - Product SKUs P-FELO-074, P-FELO-075, P-FELO-076, P-FELO-083 must exist - Commerce Cloud pricing engine must be configured - Chargent package and TChargentBatchProcessing must be available - Order.SalesStoreId must be populated with valid webstore ID
Financial Impact: - Direct impact on recurring revenue collection - Incorrect pricing could result in undercharging or overcharging members - Failed batch execution could delay payment processing - Should have manual review process for high-value transactions
Troubleshooting Guide: - Check System.debug logs for "Auto-renewal pricing could not be calculated" messages - Verify Fellows Fees pricebook exists and has active entries - Confirm product SKUs haven't changed - Review AsyncApexJob records for batch status - Check Chargent order audit logs for pricing updates