Skip to content

Class Name: CheckoutDeliveryIntegration

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

API Name: CheckoutDeliveryIntegration Type: Commerce Cloud Cart Extension (Shipping Calculator) Test Coverage: To be determined Created: 06/26/2024 Author: Ecaterina Popa

Business Purpose

This class extends Salesforce Commerce Cloud's shipping calculator framework to implement zero-cost digital delivery for products that don't require physical shipping. It automates the checkout process for digital products (online courses, certifications, digital downloads) by automatically applying a "Digital Delivery" shipping method with $0.00 cost, eliminating shipping cost confusion and streamlining the member experience for digital purchases. This is critical for AANP's digital product offerings where physical shipping is not applicable.

Class Overview

Scope and Sharing

  • Sharing Model: Inherited from CartExtension.ShippingCartCalculator (system context)
  • Access Modifier: public
  • Interfaces Implemented: None (extends CartExtension.ShippingCartCalculator)

Key Responsibilities

  • Override Commerce Cloud shipping calculation for digital products
  • Clean up existing shipping validation outputs
  • Remove previous delivery group methods
  • Query and reference "Shipping Charge" product for Commerce Cloud compatibility
  • Create "Digital Delivery" shipping method with $0.00 cost
  • Set USPS carrier and "Digital Shipping" class of service
  • Auto-select the created delivery method
  • Validate cart delivery group existence
  • Integrate seamlessly with Commerce Cloud checkout flow

Public Methods

calculate

public virtual override void calculate(CartExtension.CartCalculateCalculatorRequest request)

Purpose: CartExtension framework callback method that executes during cart calculation to determine and apply shipping methods. Overrides base class to implement digital delivery logic.

Parameters: - request (CartExtension.CartCalculateCalculatorRequest): Commerce Cloud request object containing cart context and calculation state

Returns: - void (modifies cart state via CartExtension API)

Throws: - QueryException: If Product2 query for "Shipping Charge" fails (not handled) - NullPointerException: If shippingProducts list is empty and [0] accessed (not handled) - CartExtension exceptions: Various Commerce Cloud exceptions (not explicitly handled)

Usage Example:

// Called automatically by Commerce Cloud during cart calculation
// Configured in Commerce Setup:
// Setup → Commerce → Checkout → Shipping Calculator
// Extension Point: Commerce_Domain_Checkout_ShippingCalculator
// Implementation: CheckoutDeliveryIntegration

Business Logic:

  1. Get Cart Context:
    CartExtension.Cart cart = request.getCart();
    
  2. Extracts cart from request
  3. Cart contains all delivery groups, items, validation outputs

  4. Clean Up Shipping Validation Outputs:

  5. Gets CartValidationOutputList from cart
  6. Iterates backwards through list (to safely remove during iteration)
  7. Removes all CartValidationOutput items of type SHIPPING
  8. Clears any previous shipping errors/warnings

  9. Get Cart Delivery Groups:

  10. Retrieves CartDeliveryGroupList from cart
  11. Checks if size == 0 (no delivery groups defined)
  12. If empty: Creates ERROR validation output "No Cart Delivery Groups have been defined"
  13. Returns early if validation fails

  14. Get Cart Items:

  15. Retrieves CartItemList to get unique item count
  16. Count used for tracking/debugging (stored in numberOfUniqueItems)
  17. Not actively used in current logic

  18. Get First Delivery Group:

  19. Gets cartDeliveryGroups.get(0) (assumes single delivery group)
  20. Retrieves existing CartDeliveryGroupMethodList

  21. Clean Up Existing Delivery Methods:

  22. Iterates backwards through CartDeliveryGroupMethods
  23. Removes all existing methods
  24. Clears selected method: cartDeliveryGroup.setSelectedCartDeliveryGroupMethod(null)

  25. Query Shipping Product:

    List<Product2> shippingProducts = [
        SELECT Id
        FROM Product2
        WHERE ProductClass != 'VariationParent'
        AND Name = 'Shipping Charge'
        LIMIT 1
    ];
    

  26. Looks for product named exactly "Shipping Charge"
  27. Excludes variation parents
  28. Converts to String ID

  29. Create Digital Delivery Method:

    CartExtension.CartDeliveryGroupMethod cartDeliveryGroupMethod01 =
        new CartExtension.CartDeliveryGroupMethod(
            'Digital Delivery',  // Name
            0.00,                // Cost
            shippingProduct      // Product ID
        );
    cartDeliveryGroupMethod01.setCarrier('USPS');
    cartDeliveryGroupMethod01.setClassOfService('Digital Shipping');
    

  30. Add Method and Set as Selected:

  31. Adds method to CartDeliveryGroupMethodList
  32. Sets as delivery method: cartDeliveryGroup.setDeliveryMethodId(...)

Cart Extension API Usage: - cart.getCartValidationOutputs(): Get/modify validation messages - cart.getCartDeliveryGroups(): Access delivery groups - cart.getCartItems(): Access cart items - CartExtension.CartValidationOutput: Create validation messages - CartExtension.CartDeliveryGroupMethod: Create shipping methods

Commerce Cloud Integration: - Runs during cart calculation phase - Must be registered as shipping calculator extension - Affects order summary shipping cost - Integrated with tax and pricing calculators


Private/Helper Methods

None - All logic in single calculate method. Could benefit from extraction: - cleanupValidationOutputs(cart) - validateDeliveryGroups(cart) - getShippingProduct() - createDigitalDeliveryMethod(shippingProductId)


Dependencies

Apex Classes

  • CartExtension.ShippingCartCalculator (base class): Commerce Cloud framework class
  • No other Apex dependencies
  • Must be configured in Commerce Cloud settings

Salesforce Objects

Product2 (Standard) - Fields accessed: Id, Name, ProductClass - Query for: "Shipping Charge" product - Purpose: Reference product for shipping method

CartExtension Framework Objects (Commerce Cloud) - Cart: Main cart container - CartDeliveryGroup: Delivery group configuration - CartDeliveryGroupMethod: Shipping method options - CartValidationOutput: Error/warning messages - CartItem: Items in cart

Custom Settings/Metadata

  • None identified - Consider adding:
  • Shipping_Config__mdt: Configurable product name, carrier, class of service
  • Commerce_Settings__mdt: Enable/disable digital delivery

External Services

  • None - Pure internal Commerce Cloud processing
  • No callouts or external integrations

Commerce Cloud Configuration

  • Required Setup:
  • Product2 record with Name = 'Shipping Charge' must exist
  • Extension registered at: Commerce_Domain_Checkout_ShippingCalculator
  • Commerce store must have delivery groups configured
  • Integration must be activated in Commerce setup

Design Patterns

  • Extension Pattern: Extends CartExtension.ShippingCartCalculator
  • Strategy Pattern: Implements shipping calculation strategy for digital products
  • Template Method Pattern: Overrides calculate() to provide custom behavior
  • Commerce Cloud Pattern: Follows CartExtension framework conventions

Why These Patterns: - Extension pattern required by Commerce Cloud framework - Strategy pattern allows different shipping logic per calculator - Template method provides hook into cart calculation lifecycle - Commerce Cloud pattern ensures compatibility with platform

Governor Limits Considerations

SOQL Queries: 1 (Product2 query for shipping product) DML Operations: 0 (all changes via CartExtension API, not direct DML) CPU Time: Low (simple logic, minimal processing) Heap Size: Low (small objects, minimal data)

Bulkification: N/A (processes single cart per invocation) Async Processing: No (synchronous calculator)

Governor Limit Risks: - LOW: Single SOQL query well within limits - LOW: No DML operations - LOW: CartExtension API calls are framework-managed - NONE: No loops over large data sets

Performance Considerations: - Called during every cart calculation/recalculation - Should execute quickly (<100ms ideal) - Product query could be cached if performance becomes issue - CartExtension framework manages transaction boundaries

Recommendations: - Current implementation is efficient - Consider caching shipping product ID if called frequently - Monitor Commerce Cloud performance dashboards

Error Handling

Strategy: No explicit error handling - relies on Commerce Cloud framework

Logging: - None - No custom logging - Commerce Cloud framework logs errors - No debug statements for troubleshooting

User Notifications: - CartValidationOutput used for "No Cart Delivery Groups" error - Other errors surface as generic Commerce Cloud errors - No custom user-friendly messages

Validation: - Checks for empty cart delivery groups - Creates ERROR level validation output if no delivery groups - No validation for: - Missing shipping product - Empty shippingProducts list - Null cart items

Rollback Behavior: - Commerce Cloud manages transaction rollback - CartExtension state changes rolled back on error - Cart returns to previous valid state

Recommended Improvements: - Add try-catch around Product2 query - Validate shippingProducts not empty before accessing [0] - Add validation output if shipping product not found - Log calculation steps for troubleshooting - Add null checks for cart objects

Security Considerations

Sharing Rules: SYSTEM CONTEXT - CartExtension runs as system - No sharing declaration (inherits from framework) - Runs with system privileges - Appropriate for checkout automation

Field-Level Security: NOT ENFORCED - CartExtension framework bypasses FLS - Appropriate for checkout process - Products must be accessible to cart

CRUD Permissions: NOT ENFORCED - System context allows all operations - Appropriate for automated checkout

Input Validation: MINIMAL - Validates delivery groups exist - No validation of cart state - No validation of product existence - No validation of cart items

Security Risks: - LOW: System context appropriate for checkout - MEDIUM: Hardcoded product name could be exploited if product deleted/renamed - LOW: No input from users (framework-driven)

Commerce Security: - Cart belongs to authenticated user - Commerce Cloud enforces user permissions - Extension operates on user's cart only

Mitigation Recommendations: 1. Add validation that shipping product exists 2. Log security-relevant events (cart modifications) 3. Consider using custom metadata for configuration 4. Regular audits of shipping product configuration

Test Class

Test Class: CheckoutDeliveryIntegrationTest.cls (assumed - verify in codebase) Coverage: To be determined

Test Scenarios That Should Be Covered: - ✓ Cart with delivery group applies digital delivery successfully - ✓ Cart without delivery groups shows error validation - ✓ Shipping product "Shipping Charge" exists and is used - ✓ Existing delivery methods are cleaned up - ✓ Existing validation outputs are cleaned up - ✓ Digital delivery method created with $0.00 cost - ✓ Carrier set to 'USPS' - ✓ Class of service set to 'Digital Shipping' - ✓ Delivery method automatically selected - ✓ Multiple cart items handled correctly - ✓ Empty cart handling - ✓ Missing shipping product (should fail gracefully) - ✓ Multiple delivery groups (only first processed)

Testing Challenges: - Commerce Cloud CartExtension mocking is complex - Requires Commerce Cloud test data setup - Must configure test store and products - CartExtension.Cart object difficult to mock - Framework behavior testing requires integration tests

Test Data Requirements: - Product2 record named "Shipping Charge" - WebCart with Status = 'Active' - CartDeliveryGroup configured - CartItems in cart - Commerce store configuration

Mock Patterns:

// Create test cart
WebCart testCart = new WebCart(/*...*/);
CartDeliveryGroup testGroup = new CartDeliveryGroup(/*...*/);

// Mock CartExtension request
CartExtension.CartCalculateCalculatorRequest mockRequest = /*...*/;

// Call calculator
CheckoutDeliveryIntegration calculator = new CheckoutDeliveryIntegration();
calculator.calculate(mockRequest);

// Assert delivery method created
// Assert validation outputs correct

Changes & History

  • Created: 06/26/2024
  • Author: Ecaterina Popa
  • Purpose: Digital delivery shipping calculation for Commerce Cloud
  • Last Modified: Check git log

Related Changes: - Part of Commerce Cloud checkout implementation - Supports digital product strategy - Integrates with pricing and tax calculators

⚠️ Pre-Go-Live Concerns

CRITICAL - Fix Before Go-Live

  • Hardcoded Product Dependency: Class relies on exact product name "Shipping Charge" - if product doesn't exist, rename, or is deleted, checkout BREAKS. Add existence check and error handling.
  • No Error Handling on Query: Line 52-60 queries Product2 without try-catch - query exceptions will break checkout with cryptic errors.
  • Array Index Risk: shippingProducts[0] accessed without checking list size - will throw NullPointerException if no products found.
  • No Product Validation: If "Shipping Charge" product is deactivated or wrong ProductClass, checkout silently fails or breaks.

HIGH - Address Soon After Go-Live

  • No Logging: Zero logging makes troubleshooting checkout issues impossible. Can't determine why delivery methods fail.
  • Single Delivery Group Assumption: Only processes first delivery group (.get(0)) - multi-shipment orders will fail.
  • No Configuration: All values hardcoded ('USPS', 'Digital Shipping', product name) - requires code deployment to change.
  • Missing Validation Outputs: Should add validation output if shipping product not found (user sees generic error).

MEDIUM - Future Enhancement

  • Hardcoded Carrier/Service: 'USPS' and 'Digital Shipping' should be configurable via custom metadata.
  • Product Name Dependency: Use Product Code or custom metadata instead of Name for better reliability.
  • No Caching: Queries shipping product every time - could cache for performance.
  • Limited Error Messages: Generic Commerce Cloud errors don't help users understand issues.
  • Unused Variable: numberOfUniqueItems captured but never used - remove or implement logic.

LOW - Monitor

  • Code Organization: Single 77-line method should be refactored into smaller methods.
  • Virtual Override: Method is virtual but no subclasses exist - remove virtual if not needed.
  • Documentation: Inline comments are good but could be more detailed for complex Cart Extension API.
  • Test Coverage: Verify comprehensive test coverage exists for all scenarios.

Maintenance Notes

Complexity: Medium (Commerce Cloud framework complexity) Recommended Review Schedule: Quarterly, before Commerce Cloud upgrades

Key Maintainer Notes:

🛒 COMMERCE CLOUD CRITICALITY: - This class is REQUIRED for checkout to function - Failures block all digital product purchases - Must be tested in full Commerce Cloud sandbox - Changes require Commerce Cloud expertise - Test with actual products and checkout flow

📋 Usage Patterns: - Called automatically during cart calculation - Runs every time cart is modified - Runs during checkout flow - Must be registered in Commerce Cloud settings: Setup → Commerce → Checkout - Extension point: Commerce_Domain_Checkout_ShippingCalculator

🧪 Testing Requirements: - Test in Commerce Cloud sandbox with real products - Test complete checkout flow end-to-end - Verify "Shipping Charge" product exists and is configured correctly - Test with multiple cart items - Test with different product types - Verify $0.00 shipping cost appears correctly - Test in mobile and desktop checkout

🔧 Commerce Cloud Configuration: - Product2 with Name = 'Shipping Charge' MUST exist - Product must have ProductClass != 'VariationParent' - Extension must be activated in Commerce setup - Must be associated with correct store - Delivery groups must be configured in store

⚠️ Gotchas and Warnings: - Renaming "Shipping Charge" product breaks checkout immediately - Deleting shipping product breaks checkout immediately - Only first delivery group processed - multi-shipment not supported - CartExtension errors are cryptic - add detailed logging - Changes require Commerce Cloud redeployment - Must test in full Commerce environment (not just unit tests)

📅 When to Review This Class: - Before any Commerce Cloud upgrades - When adding new product types - If checkout failures reported - When modifying shipping logic - During annual Commerce Cloud reviews - If "Shipping Charge" product changes - When implementing physical shipping

🛑 Emergency Deactivation:

If digital delivery needs to be disabled:

// Option 1: Deactivate extension in Commerce setup
// Setup → Commerce → Checkout → Shipping Calculator
// Deactivate CheckoutDeliveryIntegration

// Option 2: Add metadata check at start of calculate():
public virtual override void calculate(CartExtension.CartCalculateCalculatorRequest request) {
    Commerce_Settings__mdt settings = Commerce_Settings__mdt.getInstance('Shipping');
    if (settings != null && !settings.Digital_Delivery_Enabled__c) {
        // Fall back to default shipping calculator
        super.calculate(request);
        return;
    }
    // ... rest of method
}

🔍 Debugging Tips: - Enable Commerce Cloud debug logs - Check Setup → Commerce → Checkout configuration - Verify extension is active and associated with store - Query for "Shipping Charge" product directly - Check cart delivery groups are configured - Review Commerce Cloud transaction logs - Test in scratch org or full sandbox

📊 Monitoring Checklist: - Daily: Checkout success rate - Weekly: Shipping calculation errors - Monthly: "Shipping Charge" product configuration validation - Monitor: Commerce Cloud performance dashboards - Alert: Any CartExtension exceptions

🔗 Related Components: - Product2: "Shipping Charge" product (CRITICAL dependency) - Commerce Cloud Store: Store configuration - Cart Delivery Groups: Must be configured - Commerce pricing calculator: Works alongside this - Commerce tax calculator: Works alongside this - Order creation: Uses shipping method from this class

💡 Future Enhancements: - Make shipping product configurable via metadata - Support multiple delivery groups - Add detailed logging - Implement product caching - Add comprehensive validation - Support mixed physical/digital shipments

Business Owner

Primary: E-Commerce / Digital Products Team Secondary: IT Operations / Commerce Cloud Admin Stakeholders: Product Management, Customer Experience, Development Team, Member Services