Skip to content

Class Name: DisablePlaceOrder

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

API Name: DisablePlaceOrder Type: Lightning Component Controller (AuraEnabled) Test Coverage: DisablePlaceOrderTest.cls Author: Unknown Created: Unknown

Business Purpose

This class implements a critical membership-first business rule that prevents non-members from purchasing community access products without first obtaining membership. It enforces AANP's business model by checking whether users attempting to purchase community products are either existing members or have membership products in their current cart. This ensures proper revenue flow, maintains membership requirements, and prevents invalid purchase combinations that would violate business rules.

Class Overview

Scope and Sharing

  • Sharing Model: with sharing (respects record-level security)
  • Access Modifier: public
  • Interfaces Implemented: None

Key Responsibilities

  • Validate user has contact association
  • Check account membership status
  • Analyze cart contents for community products
  • Detect membership products in cart
  • Enforce membership-first purchase rule
  • Return boolean to control Place Order button enablement
  • Support cacheable Lightning component integration

Public Methods

getWebCart

@AuraEnabled(cacheable=true)
public static Boolean getWebCart(Id userId, Integer refreshKey)

Purpose: Determines whether the Place Order button should be disabled for a user attempting to purchase community products without proper membership. Returns true to disable (prevent order), false to allow order.

Parameters: - userId (Id): Salesforce User ID to check - refreshKey (Integer): Cache-busting parameter to force re-evaluation (not used in logic)

Returns: - Boolean: - true = Disable Place Order (non-member buying community without membership in cart) - false = Allow Place Order (member, no community products, or has membership in cart)

Throws: - QueryException: If any SOQL queries fail (not handled) - NullPointerException: If account query returns no results (not handled)

Usage Example:

// Called from Lightning Web Component
import getWebCart from '@salesforce/apex/DisablePlaceOrder.getWebCart';

// In LWC JavaScript
getWebCart({ userId: this.userId, refreshKey: Date.now() })
    .then(result => {
        this.disablePlaceOrder = result;
    })
    .catch(error => {
        console.error('Error:', error);
    });

Business Logic:

  1. Query User Contact:
    User user = [SELECT Id, ContactId FROM User WHERE Id = :userId LIMIT 1];
    
  2. Gets user's associated contact ID
  3. LIMIT 1 for governor limit safety

  4. Validate ContactId:

    if (user.ContactId == null) {
        return false;  // Allow order (edge case - user has no contact)
    }
    

  5. If no contact, allow order (permissive fallback)

  6. Query Account by PersonContactId:

    Account account = [
        SELECT Id, Is_Member__c
        FROM Account
        WHERE PersonContactId = :user.ContactId
        LIMIT 1
    ];
    

  7. Finds person account via contact
  8. Gets membership status

  9. Query WebCarts with Community Products:

    List<WebCart> webCarts = [
        SELECT Id
        FROM WebCart
        WHERE AccountId = :account.Id
        AND Status = 'Checkout'
        AND Id IN (SELECT CartId FROM CartItem WHERE product2.Family = 'Communities')
    ];
    

  10. Finds checkout carts containing community products
  11. Uses subquery for efficient filtering

  12. Query WebCarts with Membership Products:

    List<WebCart> webCartsWithMembershipCartItem = [
        SELECT Id
        FROM WebCart
        WHERE AccountId = :account.Id
        AND Status = 'Checkout'
        AND Id IN (SELECT CartId FROM CartItem WHERE product2.Family = 'Membership')
    ];
    

  13. Checks if cart contains membership products

  14. Apply Business Rule:

    return !webCarts.isEmpty() && account.Is_Member__c == false && webCartsWithMembershipCartItem.isEmpty();
    

  15. Returns TRUE (disable order) when ALL conditions met:
    • Cart contains community products (webCarts not empty)
    • Account is not a member (Is_Member__c = false)
    • Cart does NOT contain membership products (webCartsWithMembershipCartItem empty)
  16. Otherwise returns FALSE (allow order)

Business Rule Truth Table: | Has Community Products | Is Member | Has Membership in Cart | Result | Meaning | |------------------------|-----------|------------------------|--------|---------| | Yes | No | No | TRUE | Disable - Must add membership | | Yes | No | Yes | FALSE | Allow - Membership in cart | | Yes | Yes | No | FALSE | Allow - Already member | | Yes | Yes | Yes | FALSE | Allow - Member buying more | | No | No | No | FALSE | Allow - No community products | | No | Yes | No | FALSE | Allow - Member buying other products |


Private/Helper Methods

None - All logic in single method. Could benefit from extraction: - getUserContact(userId) - getAccountByContact(contactId) - hasProductFamily(accountId, productFamily) - shouldDisablePlaceOrder(hasC ommunity, isMember, hasMembership)


Dependencies

Apex Classes

  • None - Standalone controller

Salesforce Objects

User (Standard) - Fields accessed: Id, ContactId - Purpose: Link user to contact

Account (Standard - Person Account) - Fields accessed: Id, Is_Member__c, PersonContactId - Purpose: Check membership status

WebCart (Commerce Cloud) - Fields accessed: Id, AccountId, Status - Purpose: Identify checkout carts

CartItem (Commerce Cloud) - Fields accessed: CartId, product2.Family - Purpose: Identify products in cart

Product2 (Standard) - Fields accessed: Family (via relationship) - Product Families used: - 'Communities': Community access products - 'Membership': Membership products

Custom Settings/Metadata

  • None identified - Consider adding:
  • Cart_Business_Rules__mdt: Configurable product families and rules
  • Membership_Settings__mdt: Enable/disable rule enforcement

External Services

  • None - Pure internal Salesforce processing

Design Patterns

  • Controller Pattern: AuraEnabled for Lightning component integration
  • Business Rule Pattern: Encapsulates complex business logic
  • Query Pattern: Multiple queries to gather decision data
  • Guard Clause Pattern: Early return for null contact

Why These Patterns: - Controller pattern enables LWC integration - Business rule pattern centralizes membership validation - Query pattern gathers all necessary data - Guard clause handles edge cases early

Governor Limits Considerations

SOQL Queries: 3 (User, Account, 2x WebCart queries) DML Operations: 0 (read-only) CPU Time: Low (simple logic) Heap Size: Low (small result sets)

Bulkification: N/A (single user per call) Async Processing: No (synchronous)

Governor Limit Risks: - LOW: 3 SOQL queries well within 100 limit - LOW: No DML operations - MEDIUM: Subqueries in WebCart queries could be optimized - LOW: Cacheable attribute helps reduce repeated calls

Performance Considerations: - Called on every cart page refresh/update - Cacheable reduces server load but may show stale data - refreshKey parameter suggests need for cache busting - Could combine WebCart queries into single query with OR condition

Recommendations: - Combine WebCart queries into one with OR logic - Add query result caching if called frequently - Monitor query performance with cart analytics

Error Handling

Strategy: No explicit error handling - relies on system exceptions

Logging: - None - No logging of rule enforcement - No tracking of disabled orders - No business analytics on rule triggers

User Notifications: - None from this class - UI must handle - No error messages to explain why order disabled - No guidance on how to fix (add membership)

Null Handling: - Returns false if ContactId null (permissive) - No null check for account (could throw exception) - Assumes WebCart queries always safe

Recommended Improvements: - Add try-catch around queries - Log when orders are disabled for analytics - Return structured data with reason for disability - Add null check for account query - Provide user-friendly error message

Security Considerations

Sharing Rules: RESPECTED - Uses 'with sharing' - User can only check their own cart - Record-level security enforced - Appropriate for user-facing function

Field-Level Security: RESPECTED - FLS enforced on all queries - User must have read access to all queried fields

CRUD Permissions: RESPECTED - User must have read permission on objects - Appropriate for business rule checking

Input Validation: MINIMAL - Validates ContactId not null - No validation of userId parameter - Assumes userId is current user

Security Risks: - LOW: with sharing appropriate - LOW: Read-only queries - MEDIUM: Could check any user's cart if userId manipulated (validate userId = UserInfo.getUserId())

Business Impact: - Prevents invalid purchases - Enforces membership revenue model - Could impact conversion if too restrictive

Mitigation Recommendations: 1. Validate userId matches current user 2. Add audit logging for compliance 3. Monitor for circumvention attempts 4. Regular review of business rule effectiveness

Test Class

Test Class: DisablePlaceOrderTest.cls Coverage: To be determined

Test Scenarios That Should Be Covered: - ✓ Non-member with community products (no membership in cart) = true - ✓ Non-member with community products (with membership in cart) = false - ✓ Member with community products = false - ✓ Non-member without community products = false - ✓ User with null ContactId = false - ✓ Account not found for contact (error handling) - ✓ Multiple WebCarts in Checkout status - ✓ WebCart with mixed product families - ✓ WebCart in non-Checkout status (should not affect result) - ✓ Different product families - ✓ Cacheable behavior (same result on repeat calls)

Testing Challenges: - Must create Person Accounts (special setup) - Requires Commerce Cloud test data (WebCart, CartItem) - Product2 Family values must be configured - Is_Member__c custom field must exist - Cacheable testing requires multiple calls

Test Data Requirements: - User records with ContactId - Person Account records with Is_Member__c - Product2 records with Family = 'Communities' and 'Membership' - WebCart records in 'Checkout' status - CartItem records linking to products

Changes & History

  • Created: Unknown (check git history)
  • Author: Unknown (check git annotations)
  • Purpose: Enforce membership-first business rule
  • Related to: Commerce Cloud checkout implementation

⚠️ Pre-Go-Live Concerns

CRITICAL - Fix Before Go-Live

  • No Error Handling on Queries: Three queries without try-catch - will break UI with cryptic errors if queries fail.
  • No Account Null Check: Account query assumed to return result - will throw NullPointerException if account not found for contact.
  • User ID Validation Missing: No check that userId parameter matches current user - security risk if manipulated.
  • Hardcoded Product Families: 'Communities' and 'Membership' hardcoded - breaks if product structure changes.

HIGH - Address Soon After Go-Live

  • No User Feedback: Users see disabled button with no explanation of why or how to fix.
  • Performance: Three separate queries could be optimized to one or two.
  • No Logging: No analytics on how often rule triggers - can't measure business impact.
  • Cache Staleness: Cacheable attribute may show stale data if cart changes - refreshKey not actually used in logic.

MEDIUM - Future Enhancement

  • Membership Expiration: Only checks Is_Member__c flag - doesn't validate membership is current/not expired.
  • Partial Implementation: Method name 'getWebCart' doesn't describe what it returns.
  • Limited Product Logic: Only handles Communities and Membership families - what about other restricted products?
  • No Configuration: Business rules hardcoded - requires code deployment to change.

LOW - Monitor

  • RefreshKey Parameter: Declared but never used in logic - implement or remove.
  • Method Naming: 'getWebCart' misleading - actually returns boolean for place order enablement.
  • Code Organization: Could extract helper methods for better readability.
  • Return Value Documentation: Boolean return meaning not obvious from method name.

Maintenance Notes

Complexity: Medium (multiple queries + business logic) Recommended Review Schedule: Quarterly (business rule changes)

Key Maintainer Notes:

🛒 BUSINESS CRITICALITY: - This class enforces CORE membership business model - Failures could allow invalid purchases or block valid ones - Directly impacts conversion rate and revenue - Changes require business stakeholder approval - Test extensively before deployment

📋 Usage Patterns: - Called from LWC on cart/checkout pages - Runs on every page load/refresh - Cacheable reduces load but may be stale - Critical path for checkout flow

🧪 Testing Requirements: - Test all combinations in truth table - Test with person accounts and business accounts - Test edge cases (no contact, no account) - Test with multiple products in cart - Test performance with large carts - Verify membership flag accuracy

🔧 Product Configuration: - CRITICAL: Product2.Family must be set correctly - 'Communities' for community access - 'Membership' for membership products - CRITICAL: Account.Is_Member__c must be maintained accurately - Misconfigurations break business rule

⚠️ Gotchas and Warnings: - Only checks Is_Member__c flag - doesn't validate membership dates - Cacheable may show stale data after cart changes - Returns false (allow) if ContactId null - permissive fallback - Product Family values are case-sensitive - Only checks WebCarts in 'Checkout' status - Could have multiple WebCarts per account

📅 When to Review This Class: - When membership rules change - When adding new product types - If conversion rate drops unexpectedly - During Commerce Cloud upgrades - When membership flag logic changes - If customer complaints about blocked checkout

🛑 Emergency Deactivation:

// Add at start of method:
Commerce_Settings__mdt settings = Commerce_Settings__mdt.getInstance('PlaceOrderRules');
if (settings != null && !settings.Enforce_Membership_Rule__c) {
    return false; // Always allow orders
}

🔍 Debugging Tips: - Enable debug logs for user - Check User.ContactId populated - Verify Account.Is_Member__c value - Query WebCarts directly to see what's in Checkout status - Check Product2.Family values on cart items - Test with different user/account combinations

📊 Monitoring Checklist: - Daily: How often rule triggers (disabled orders) - Weekly: Conversion impact (disabled vs completed orders) - Monthly: Membership attachment rate for community purchases - Monitor: False positives (valid orders disabled) - Alert: Spike in disabled orders (potential bug)

🔗 Related Components: - LWC Place Order Button: Consumes this method - WebCart/CartItem: Data source - Product2: Family configuration - Account: Membership status - Membership management system: Maintains Is_Member__c

Business Owner

Primary: Membership Operations / Business Rules Team Secondary: E-Commerce / Product Management Stakeholders: Finance, Marketing, Customer Service, Development Team