Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
149 commits
Select commit Hold shift + click to select a range
a3f1701
test commit
alakhmani Feb 13, 2024
4a8ba7a
update sample shipping calculator for Delivery Estimation
alakhmani Feb 13, 2024
04b36ce
update sample shipping calculator
alakhmani Feb 13, 2024
2af7c33
updated test for delivery estimation fields
alakhmani Feb 14, 2024
77dc051
updated comment
alakhmani Feb 15, 2024
1f8ff40
Merge pull request #50 from forcedotcom/t/commerce/obsidian/updateSam…
alakhmani Feb 15, 2024
1bcc64a
adding test for PromotionCalculatorSample class
patricia-bagzai-sf Feb 16, 2024
49827a9
Merge pull request #51 from forcedotcom/W-14847074/PromotionCalculato…
patricia-bagzai-sf Feb 16, 2024
8b1d07a
Update variable name
patricia-bagzai-sf Feb 19, 2024
a364315
Merge pull request #52 from forcedotcom/@W-14847074/UpdatePromotionCa…
patricia-bagzai-sf Feb 19, 2024
8e06355
[Tax calculator] replaced for loops with iterators
bsrilok Mar 18, 2024
ae773dc
Addressed comments
bsrilok Mar 18, 2024
9b25b3a
code changes
smahbubani99 Mar 18, 2024
0f4f9f5
update unit test
smahbubani99 Mar 18, 2024
114305e
revert comment changes
smahbubani99 Mar 18, 2024
5b7b3a9
update unit test
smahbubani99 Mar 19, 2024
baea2c2
code changes
smahbubani99 Mar 20, 2024
5f354b1
modify utests
smahbubani99 Mar 20, 2024
cc8ed61
Addressed comments
bsrilok Mar 21, 2024
244f3a0
Addressed comments
bsrilok Mar 21, 2024
9cf6c10
change method name
smahbubani99 Mar 21, 2024
6143194
update orchestrator check
smahbubani99 Mar 21, 2024
dda947b
formatting
smahbubani99 Mar 21, 2024
a7923d9
change method name again
smahbubani99 Mar 22, 2024
f036aff
Update CartCalculateSampleUnitTest.cls
smahbubani99 Mar 22, 2024
d8b7615
Merge pull request #54 from forcedotcom/addCouponsToSampleOrchestrator
smahbubani99 Mar 22, 2024
a622066
updating PromotionCalculatorSample example to evalaute BOGO promotion…
patricia-bagzai-sf Mar 26, 2024
aaf5ae4
addressing PR comments
patricia-bagzai-sf Mar 27, 2024
fc67e34
addressed comments
bsrilok Mar 28, 2024
6708c2b
Merge pull request #53 from bsrilok/t/commerce/TaxCalculator
ParameshOddepally Mar 28, 2024
46773ee
updating logic to leverage buyerActionDetails; updating tests
patricia-bagzai-sf Mar 28, 2024
2a12dbb
adding evaluate promotion logic when optionalBuyerActionDetails not p…
patricia-bagzai-sf Apr 2, 2024
6d6a57a
Merge pull request #55 from forcedotcom/W-15061789/optimizePromotoinC…
patricia-bagzai-sf Apr 2, 2024
f3fde2a
@W-15346861-refactored-cart-calculator-apex
bsrilok Apr 24, 2024
0973ccc
@W-15346861-added-test-cases
bsrilok Apr 25, 2024
2f78248
Use proper CartValidationOutputTypeEnum for PricingCalculator
pplat23 Apr 25, 2024
8d929f2
Merge pull request #56 from forcedotcom/fix-cvotype-for-pricingcalcul…
pplat23 Apr 26, 2024
cb5fe17
Fix errors in PricingServiceSample
adarshjain-sf Apr 29, 2024
2550e02
Update comments
adarshjain-sf Apr 30, 2024
95ca63f
Review comments
adarshjain-sf Apr 30, 2024
0f241eb
Update PricingServiceSample.cls
adarshjain-sf Apr 30, 2024
4ac3500
Merge pull request #58 from adarshjain-sf/patch-1
ParameshOddepally May 2, 2024
fe5d211
@W-15346861-addressed-comments
bsrilok May 12, 2024
337c8ef
@W-15346861-addressed-comments
bsrilok May 12, 2024
a84a342
@W-15346861-addressed-comments
bsrilok May 16, 2024
7edf37f
@W-15346861-addressed-comments
bsrilok May 16, 2024
fe5f02a
@W-15346861-adddressed-comments
bsrilok May 21, 2024
4c33c6f
Merge pull request #1 from bsrilok/t/commerce/W-15346861-tax-cart-cal…
bsrilok May 21, 2024
b1f924e
Merge pull request #59 from bsrilok/main
ParameshOddepally May 29, 2024
1a238d7
adding cart endpoint extension samples
balaji-0034 May 30, 2024
78beff6
adding cart endpoint samples
balaji-0034 May 30, 2024
b97fd25
review comments fix
balaji-0034 May 31, 2024
4faa153
adding if else for currency handling
balaji-0034 Jun 3, 2024
162d2d2
Update debug logs
ParameshOddepally Jun 4, 2024
4235e58
empty commit to check CLA
balaji-0034 Jun 6, 2024
d0a9dab
Merge pull request #62 from balaji0034/W-15359680/cartEndpointExtensi…
balaji0034 Jun 6, 2024
56334d0
Format the file
ParameshOddepally Jun 8, 2024
da354ca
Merge pull request #63 from forcedotcom/origin/addDebugLogs
ParameshOddepally Jun 12, 2024
0ef89c5
Adding debug logs
skumar2-sfdc Jun 20, 2024
507b55c
Adding caught exception to the CartCalculateRuntimeException
skumar2-sfdc Jun 21, 2024
1a1683f
Merge pull request #65 from skumar2-sfdc/pricingCalculatorLogging
skumar2-sfdc Jun 21, 2024
61acced
Added null check for order item unit price to support bundles.
ssomanchi-salesforce Jul 12, 2024
c8a2b55
Updated the sample apex code to process the new recalculationRequeste…
sf-cboscenco Jul 12, 2024
5974d82
Merge pull request #66 from ssomanchi-salesforce/create-order-sample-…
gurpreetsainisalesforce Jul 13, 2024
990d4f5
Merge remote-tracking branch 'origin/main' into t/1c-cart-platform/W-…
sf-cboscenco Jul 16, 2024
c6d2c7a
Fixes after review.
sf-cboscenco Jul 16, 2024
ab490de
Merge pull request #67 from forcedotcom/t/1c-cart-platform/W-16205916…
sf-cboscenco Jul 16, 2024
4fdb511
Add sample and tests
l-wei791 Jul 24, 2024
5c05e87
add sample code for commerce inventory dommain, including a test to d…
sf-afoliaco Sep 26, 2024
a6fccc9
make method so can be overriable from the mock
sf-afoliaco Sep 26, 2024
83e4f91
remove fix vaules and add exception for better data validation
sf-afoliaco Sep 27, 2024
cb0fa18
add new test for calculator and comply to folder structure
sf-afoliaco Oct 2, 2024
1488d73
Fix comments
sf-afoliaco Oct 2, 2024
79dda81
address issue since warning are not supported we change the approach
sf-afoliaco Oct 3, 2024
4354939
change from warning to Error
sf-afoliaco Oct 3, 2024
a00dcbe
change method to make more sense
sf-afoliaco Oct 3, 2024
bdf15a0
Merge pull request #70 from sf-afoliaco/t/som/cc-om-not-hotdog/W-1604…
pplat23 Oct 3, 2024
53cbf10
Update test to use new constructor
l-wei791 Jan 23, 2025
73573db
Merge pull request #72 from forcedotcom/t/cc-om-not-hotdog/W-17643044
sf-afoliaco Jan 24, 2025
461dd8b
fix commit
deepalibharmal-salesforce Feb 3, 2025
a4a3ce1
Add tests
deepalibharmal-salesforce Feb 4, 2025
c5497bb
Merge pull request #73 from forcedotcom/t/1c-cart-platform/W-17689078…
deepalibharmal-salesforce Feb 5, 2025
2cc4873
sample gift card extension and test classes
alakhmani Feb 10, 2025
3fda96d
sample gift card extension class
alakhmani Feb 10, 2025
15b0ce0
review comments
alakhmani Feb 11, 2025
ea75a80
review comments
alakhmani Feb 12, 2025
c8f3a98
review comments
alakhmani Feb 12, 2025
cd816ee
review comments
alakhmani Feb 12, 2025
7625740
Merge pull request #76 from forcedotcom/t/commerce/obsidian/GiftCardE…
gurpreetsainisalesforce Feb 13, 2025
b424d5e
Update README.md
spencer-dean Feb 26, 2025
1b51233
Merge pull request #78 from forcedotcom/sd/SplitShipment
snilakandan13 Feb 26, 2025
9119c84
ShippingCartCalculatorSampleAdvance
sf-anilpurohit Mar 24, 2025
defed60
ShippingCartCalculatorSampleAdvance
sf-anilpurohit Mar 25, 2025
0a0c3d5
Merge pull request #80 from sf-anilpurohit/t/commerce/W-17966639-1-new
gurpreetsainisalesforce Mar 26, 2025
309b09a
ShippingCartCalculatorSampleAdvance shipping product name fix
sf-anilpurohit Apr 1, 2025
e0bc5ee
ShippingCartCalculatorSampleAdvance shipping product name fix
sf-anilpurohit Apr 1, 2025
ba36939
Merge pull request #81 from sf-anilpurohit/t/commerce/W-18168796-1
sf-anilpurohit Apr 2, 2025
946bf1d
deleting gift card extensions
alakhmani Apr 2, 2025
3b24857
Merge pull request #82 from forcedotcom/t/commerce/obsidian/W-1790001…
alakhmani Apr 3, 2025
bfbf334
Simplify the TaxService and TaxCartCalculator samples
kazarindn May 6, 2025
81bfbfb
Merge pull request #83 from kazarindn/main
kazarindn May 13, 2025
ab62b60
Buyer Group Extensibility Sample Code
rahulpatelsf May 14, 2025
f6bb6c3
Buyer Group Extensibility Sample Code Comment Changes
rahulpatelsf May 14, 2025
01bddc7
Remove tax-specific CVO cleanup from TaxCartCalculator
kazarindn May 14, 2025
f63b596
Merge pull request #85 from forcedotcom/tax_sample_cleanup
kazarindn May 14, 2025
20f371c
Merge pull request #84 from rahulpatelsf/t/commerce/buyer-group-exten…
rahulpatelsf May 14, 2025
ad3ca0e
updated sample apex for pre/post hooks
ansh-bhalla May 30, 2025
aa3c236
updated sample file naming
ansh-bhalla May 30, 2025
bfe18b1
added sample test class
ansh-bhalla May 30, 2025
56b8d2b
testing null scenario updates to sample apex and tests
ansh-bhalla Jun 3, 2025
0261ef9
updated descriptions
ansh-bhalla Jun 3, 2025
de04bf3
updated apex implementation
ansh-bhalla Jun 5, 2025
c243362
fixed typos and added outofbounds catch
ansh-bhalla Jun 6, 2025
ee924e4
updated api version
ansh-bhalla Jun 6, 2025
5fd0328
Merge pull request #86 from ansh-bhalla/t/commerce/aceofbase/W-183496…
pooja-sharmasf Jun 9, 2025
f651169
Shareable URL sample code
saumyashukla23 Jul 18, 2025
dac7700
Shareable URL sample code
saumyashukla23 Jul 18, 2025
c876610
Shareable URL sample code
saumyashukla23 Jul 18, 2025
51c34f3
Shareable URL sample code
saumyashukla23 Jul 21, 2025
c399f76
Api version for 258
saumyashukla23 Jul 21, 2025
90db61f
Merge pull request #87 from saumyashukla23/W-18935428_sample_apex_sha…
HarishM Jul 21, 2025
14c5bde
including shipping promotions in CartCalculateSample
balaji-0034 Jan 13, 2026
e74f638
adding checkout state check
balaji-0034 Jan 14, 2026
e28804b
trigger cla
balaji-0034 Jan 15, 2026
ab463bd
Create PlaceOrderValidateSample.cls
battalian Jan 20, 2026
115a9e7
Create PlaceOrderValidateSample.cls-meta.xml
battalian Jan 20, 2026
d8de8a6
Create PlaceOrderValidateSampleTest.cls
battalian Jan 20, 2026
a881868
Create PlaceOrderValidateSampleTest.cls-meta.xml
battalian Jan 20, 2026
44403a7
Create PlaceOrderWithValidationsInSequence.cls
battalian Jan 20, 2026
f749de0
Create PlaceOrderWithValidationsInSequence.cls-meta.xml
battalian Jan 20, 2026
f5617fe
Create PlaceOrderWithValidationsInSequenceTest.cls
battalian Jan 20, 2026
5e743b1
Create PlaceOrderWithValidationsInSequenceTest.cls-meta.xml
battalian Jan 20, 2026
df98803
Merge pull request #88 from balaji-0034/t/1c-cart-ninjas/w-19602952/i…
saisubburlj Jan 23, 2026
97a82da
Merge pull request #89 from battalian/main
kushalkrip Jan 27, 2026
e6d3f71
skip promotions and reset cart adjustments if quote is present in cart
jainkaran98 Mar 17, 2026
7e95f2a
add precondition in test
jainkaran98 Mar 17, 2026
46a4808
Create B2B Search Extension Examples
christabel-sebastian Mar 19, 2026
5680a06
empty commit to retrigger CLA validation
christabel-sebastian Mar 20, 2026
1deb1ab
Update POST search example
christabel-sebastian Mar 20, 2026
e9295ba
Update POST search example
christabel-sebastian Mar 21, 2026
3065351
Merge pull request #91 from christabel-sebastian/add-search-extensions
kushalkrip Mar 23, 2026
9068e88
Merge pull request #90 from jainkaran98/t/athena/skip-promotion-if-qu…
saisubburlj Mar 23, 2026
f1f148a
Add Apex v67.0 Secure by Default support to buyer group services
imAdityaSrivastav Apr 23, 2026
7a9f16e
Improve security documentation and add official guidelines link
imAdityaSrivastav Apr 24, 2026
b2004d6
Merge pull request #92 from imAdityaSrivastav/t/shikra/W-22098350
kushalkrip Apr 24, 2026
49184cd
Add CLAUDE.md with Apex v67.0 migration guidelines
imAdityaSrivastav Apr 27, 2026
3002f9e
Merge pull request #93 from imAdityaSrivastav/t/shikra/W-22098350-cla…
saisubburlj Apr 28, 2026
92c25ba
1c-ninjas changes related to 67 compatibility
anant-salesforce Apr 28, 2026
1b4d3ed
Merge pull request #94 from anant-salesforce/t/1c-cart-ninjas/w-22256…
anant-salesforce Apr 29, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 91 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# Commerce Extensibility Repository

Sample implementations for extending Salesforce Commerce services (pricing, buyer groups, tax, shipping, checkout, etc.).

## Repository Structure

```
commerce/
├── domain/ # Business logic extensions (pricing, tax, buyer groups, etc.)
└── endpoint/ # API extensions (cart, search, account)
```

---

## Apex v67.0 Migration

Reference: [Apex Release Notes - Summer '26](https://help.salesforce.com/s/articleView?id=release-notes.rn_apex.htm&release=262&type=5)

When a user asks to migrate files for Apex v67.0, follow this process:

#### Step 1: Analyze

Scan `.cls` files and identify issues based on the v67.0 Secure by Default changes:

**Sharing Keywords** - Classes without a sharing keyword now default to `WITH SHARING`:
```apex
// Explicitly declare the sharing mode you need
public without sharing class MyExtension { }
public with sharing class MyExtension { }
public inherited sharing class MyExtension { }
```

**Query Mode** - Queries now run as `USER_MODE` by default:
```apex
// Add WITH SYSTEM_MODE only if you need to bypass user permissions
[SELECT Id FROM Account WHERE Id = :id WITH SYSTEM_MODE]
```

**DML Access Level** - DML operations now run as `USER_MODE` by default:
```apex
// Add SYSTEM_MODE only if you need to bypass user permissions
Database.insert(records, AccessLevel.SYSTEM_MODE);
insert as system records;
```

**Deprecated Syntax** - `WITH SECURITY_ENFORCED` is deprecated:
```apex
// ❌ Deprecated
[SELECT Name FROM Account WITH SECURITY_ENFORCED]

// ✅ Use WITH USER_MODE
[SELECT Name FROM Account WITH USER_MODE]
```

#### Step 2: Show Diff to User

Present each change clearly with file name, line numbers, what will change, and why.

If user asks, show detailed before/after diff for each change.

#### Step 3: Get Approval

```
Should I apply these X changes across Y files? (yes/no)

Reply 'yes' to proceed, or ask me to show details for any file.
```

**Wait for explicit "yes" before proceeding.**

#### Step 4: Apply Changes

1. Update code with required changes
2. Keep API version unchanged (backward compatibility)
3. Preserve existing formatting

#### Step 5: Report

```
✅ Migration complete!

Updated:
- File1.cls (4 queries, docs)
- File2.cls (docs only)

Next steps:
1. Review changes
2. Run tests
3. Commit when ready
```

34 changes: 27 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@ This repository contains a reference implementation of the Commerce Extensibilit
- Shipping Calculator
- Tax Calculator
- Tax Service
- [Domain Extension for Checkout](#domain-extension-for-checkout)
- Checkout Create Order
- [Domain Extensions for Checkout](#domain-extensions-for-checkout)
- CreateOrder Service
- SplitShipment Service
- [Domain Extensions for Buyer Group](#domain-extensions-for-buyer-group)
- Buyer Group Extensibility Service

Each set of sample code includes: an Apex class, a test class, and any necessary resource files.

Expand Down Expand Up @@ -37,7 +40,7 @@ The sample code for Shipping Calculator includes an Apex class (in `ShippingCalc

### Tax Calculator

The sample code for Tax Calculator includes an Apex class (in `TaxCalculatorSample.apxc`) that calls an external service to retrieve tax information and then save those taxes in `CartTaxes` in `CartItems` and `CartItemAdjustments`.
The sample code for Tax Calculator includes an Apex class (in `TaxCalculatorSample.apxc`) that calls an external service to retrieve tax information and then save those taxes in `CartTaxes` in `CartItems`.

### Tax Service

Expand All @@ -54,15 +57,32 @@ All error cases are propagated to the admin as CommerceDiagnosticEvents (see [Co

All reference implementations include examples of how to propagate an error to the user.

## Domain Extension for Checkout
### Checkout Create Order
## Domain Extensions for Checkout

The sample code for [Checkout Create Order](https://developer.salesforce.com/docs/commerce/salesforce-commerce/guide/CheckoutCreateOrder.html) extension point includes an Apex class (see [CreateOrderSample.cls](commerce/domain/checkout/order/createOrder/classes/CreateOrderSample.cls) that provides an example of how to work with the [OrderGraph](https://developer.salesforce.com/docs/commerce/salesforce-commerce/guide/OrderGraph.html).
### CreateOrder Service

A unit test (see [CreateOrderSampleUnitTest.cls](commerce/domain/checkout/order/createOrder/classes/CreateOrderSampleUnitTest.cls))) that follows this approach for [Mocking the Base Apex Class in Tests](https://developer.salesforce.com/docs/commerce/salesforce-commerce/guide/mock-the-base-apex-class.html).
The sample code for the [CreateOrder Service](https://developer.salesforce.com/docs/commerce/salesforce-commerce/references/comm-apex-reference/CheckoutCreateOrder.html) extension point includes an Apex class (see [CreateOrderSample.cls](commerce/domain/checkout/order/createOrder/classes/CreateOrderSample.cls)) that provides an example of how to work with the [OrderGraph](https://developer.salesforce.com/docs/commerce/salesforce-commerce/guide/OrderGraph.html).

A unit test (see [CreateOrderSampleUnitTest.cls](commerce/domain/checkout/order/createOrder/classes/CreateOrderSampleUnitTest.cls)) that follows this approach for [Mocking the Base Apex Class in Tests](https://developer.salesforce.com/docs/commerce/salesforce-commerce/guide/mock-the-base-apex-class.html).

Also, there is an "integration" test (see [CreateOrderSampleIntegrationTest.cls](commerce/domain/checkout/order/createOrder/classes/CreateOrderSampleIntegrationTest.cls)) that verifies implementation of the CreateOrder extension that calls real default extension point behavior. This testing approach can be used in addition to unit test, it has wider test coverage, but it is less isolated than unit test presented in the example below.

### SplitShipment Service

The sample code for the [SplitShipment Service](https://developer.salesforce.com/docs/commerce/salesforce-commerce/references/comm-apex-reference/SplitShipmentService.html) extension point includes an Apex class (see [SplitShipmentSample.cls](commerce/domain/shipping/splitshipment/SplitShipmentSample.cls)) that creates cart delivery groups by conveyable and non-conveyable products.

Another example (see [SplitShipmentCallsSuper.cls](commerce/domain/shipping/splitshipment/SplitShipmentCallsSuper.cls)) calls the default implementation.

Also, there is a unit test (see [SplitShipmentUnitTest.cls](commerce/domain/shipping/splitshipment/SplitShipmentUnitTest.cls)) that follows this approach for [Mocking the Base Apex Class in Tests](https://developer.salesforce.com/docs/commerce/salesforce-commerce/guide/mock-the-base-apex-class.html).

## Domain Extensions for Buyer Group

### Buyer Group Extensibility Service

The sample code for Buyer Group Extensibility Service includes the following :
- An Apex class (in `BuyerGroupEvaluationServiceSample.apxc`) that uses active postal codes to retrieve buyer groups for logged in and guest users.
- An Org Platform Cache (in `BuyerGroup.cachePartition`) to support low latency in buyer group retrieval.
- Supported Custom objects for storing and associating buyer groups to users via postal codes.(in `PostalCode__c`, `Active_PostalCode__c` and `Postal_Code_Buyer_Group__c`)

## Deployment

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<PlatformCachePartition xmlns="http://soap.sforce.com/2006/04/metadata">
<isDefaultPartition>true</isDefaultPartition>
<masterLabel>BuyerGroup</masterLabel>
<platformCachePartitionTypes>
<allocatedCapacity>0</allocatedCapacity>
<allocatedPartnerCapacity>0</allocatedPartnerCapacity>
<allocatedPurchasedCapacity>0</allocatedPurchasedCapacity>
<allocatedTrialCapacity>0</allocatedTrialCapacity>
<cacheType>Session</cacheType>
</platformCachePartitionTypes>
<platformCachePartitionTypes>
<allocatedCapacity>10</allocatedCapacity>
<allocatedPartnerCapacity>0</allocatedPartnerCapacity>
<allocatedPurchasedCapacity>0</allocatedPurchasedCapacity>
<allocatedTrialCapacity>0</allocatedTrialCapacity>
<cacheType>Organization</cacheType>
</platformCachePartitionTypes>
</PlatformCachePartition>
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/**
* BuyerGroupEvaluationServiceSample is a sample implementation of the BuyerGroupEvaluationService used to determine buyer group IDs for a user (guest or logged-in).
* The use case for this sample implementation is as follows:
* - Out-of-the-box buyer groups based on account, market, and data cloud segment should be returned for both logged-in and guest users.
* - In addition, if the user is a guest or logged-in, then the buyer groups associated with the active postal code stored using deviceId should also be returned.
* - For logged-in users, the buyer groups associated with the BillingPostalCode and ShippingPostalCode of the Account linked to the user are also returned.
*
* Data model changes to support the sample code are as follows:
* - PostalCode__c: Stores the supported postal codes in the PostalCode field.
* - Active_PostalCode__c: Stores the association between deviceId (Guest UUID cookie value) and PostalCode__c.
* This can typically be populated via a custom LWC component where a customer chooses a postal code from a list of available postal codes.
* - Postal_Code_Buyer_Group__c: A junction entity that stores a static mapping between PostalCode__c and the buyer groups associated with it.
*
* Important considerations in the code below:
* - Buyer group responses should be cached using Org Cache to support low latency.
* - No more than MAX_BUYER_GROUPS should be returned by the code.
*
* SECURITY CONSIDERATIONS (Secure by Default - Apex v67.0+):
*
* Starting with Apex v67.0 (Summer '26), all classes must explicitly declare sharing mode and
* all queries must specify WITH SYSTEM_MODE or WITH USER_MODE.
*
* This sample uses:
* - WITHOUT SHARING: Buyer group evaluation needs to work for guest users who have no object/field
* permissions. Using "with sharing" would prevent guest users from accessing buyer group data.
*
* - WITH SYSTEM_MODE for all queries: Guest users need to retrieve buyer group associations, postal
* codes, and account data. WITH USER_MODE would cause permission errors for guest users.
*
* Note: WITH SYSTEM_MODE is backward compatible (ignored in v64-v66 where it was already the default).
*
* For more information on Apex Secure by Default, see:
* https://help.salesforce.com/s/articleView?id=release-notes.rn_apex.htm&release=262&type=5
*/
public without sharing class BuyerGroupEvaluationServiceSample extends commercebuygrp.BuyerGroupEvaluationService {

private static Integer MAX_BUYER_GROUPS = 30;

public override commercebuygrp.BuyerGroupResponse getBuyerGroupIds(commercebuygrp.BuyerGroupRequest request) {
String currentUserId = UserInfo.getUserId(); // Gets the current user ID; could be a logged-in or guest user
String webstoreId = request.getStoreId(); // Gets the webstore record ID
String accountId = request.getAccountId(); // Gets the account ID of the user
String siteId = ((String) [SELECT SiteId FROM WebstoreNetwork WHERE WebstoreId = :webstoreId WITH SYSTEM_MODE][0].get('SiteId')).substring(0, 15); // Gets the network site ID
Map<String, Object> requestParameters = request.getRequestContextParameters();
Boolean isGuestUser = (Boolean) requestParameters.get('isGuestUser');
String guestUUIDKey = 'guest_uuid_essential_' + siteId; // Gets the guest UUID cookie key for the current webstore
String deviceId = (String) requestParameters.get(guestUUIDKey); // Gets the guest UUID cookie value for the current user and webstore

String cachePartition = 'local.BuyerGroup';
Cache.OrgPartition orgPartition = Cache.Org.getPartition(cachePartition); // Gets the buyer group org cache partition

// Cache key must be alphanumeric; converting currentUserId and deviceId to a hashed key
String cacheKey = EncodingUtil.convertToHex(Crypto.generateDigest('MD5', Blob.valueOf(isGuestUser ? deviceId : currentUserId)));
if (orgPartition.contains(cacheKey)) {
// Cache hit — return cached buyer groups
return new commercebuygrp.BuyerGroupResponse((Set<String>) orgPartition.get(cacheKey));
}

// Getting default out-of-the-box buyer groups based on existing logic: account, market, and data cloud segment-based buyer groups
commercebuygrp.BuyerGroupResponse defaultBuyerGroupResponse = super.getBuyerGroupIds(request);
Set<String> buyerGroupIds = new Set<String>(defaultBuyerGroupResponse.getBuyerGroupIds());

Set<String> activePostalCodes = new Set<String>();

// If the user is logged in, get the BillingPostalCode and ShippingPostalCode
if (!isGuestUser) {
SObject currentAccount = [SELECT BillingPostalCode, ShippingPostalCode FROM Account WHERE Id = :accountId WITH SYSTEM_MODE][0];
String billingPostalCode = (String) currentAccount.get('BillingPostalCode');
String shippingPostalCode = (String) currentAccount.get('ShippingPostalCode');
if (billingPostalCode != null) {
activePostalCodes.add(billingPostalCode);
}
if (shippingPostalCode != null) {
activePostalCodes.add(shippingPostalCode);
}
}

// Get active postal codes for both logged-in and guest users based on their device ID
for (Active_PostalCode__c activePostalCode : [SELECT PostalCode__r.PostalCode__c FROM Active_PostalCode__c WHERE DeviceId__c = :deviceId WITH SYSTEM_MODE]) {
if (activePostalCode.PostalCode__c != null) {
activePostalCodes.add(activePostalCode.PostalCode__r.PostalCode__c);
}
}

// Get the buyer groups associated with the postal codes
for (Postal_Code_Buyer_Group__c buyerGroup : [SELECT Buyer_Group__c FROM Postal_Code_Buyer_Group__c WHERE PostalCode__r.PostalCode__c IN :activePostalCodes WITH SYSTEM_MODE]) {
buyerGroupIds.add(buyerGroup.Buyer_Group__c);
}

// Buyer group extensibility supports only up to MAX_BUYER_GROUPS buyer groups
if (buyerGroupIds.size() > MAX_BUYER_GROUPS) {
commercebuygrp.BuyerGroupResponse response = new commercebuygrp.BuyerGroupResponse();
String errorMessage = 'More than ' + MAX_BUYER_GROUPS + ' buyer groups retrieved for the user. Contact Store Administrator.';
response.setError(errorMessage, errorMessage);
return response;
}

orgPartition.put(cacheKey, buyerGroupIds);
return new commercebuygrp.BuyerGroupResponse(buyerGroupIds);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>64.0</apiVersion>
<status>Active</status>
</ApexClass>
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/**
* BuyerGroupShareableURLSample
*
* This class is a sample implementation of the {@code commercebuygrp.BuyerGroupEvaluationService}.
* It demonstrates how to extend the default buyer group evaluation logic to include custom criteria
* based on request context parameters. In this case, the custom criterion is the user's region, which
* is passed as a URL parameter (e.g., in a shareable URL for the storefront).
*
* Use Case:
* - Retrieve default buyer groups based on standard rules (account, market, and data cloud segments).
* - Additionally, include buyer groups associated with the user's region (if provided via request context).
*
* Notes:
* - This example demonstrates extensibility for shareable URLs in the commerce storefront.
* - To use this, the region parameter must be explicitly set in the request context via URL.
* - When implementing real logic, replace the placeholder region-based filtering with actual mapping logic.
*
* Limitations:
* - Maximum allowed buyer groups is controlled by {@link #MAX_BUYER_GROUPS} (currently set to 30).
* - If the number exceeds this limit, an error response is returned instead of the list.
*
* SECURITY CONSIDERATIONS (Secure by Default - Apex v67.0+):
*
* Starting with Apex v67.0 (Summer '26), all classes must explicitly declare sharing mode.
*
* This sample uses:
* - WITHOUT SHARING: Buyer group evaluation needs to work for guest users who have no permissions.
* The base implementation (super.getBuyerGroupIds) already handles data access with system-level
* permissions, so this class inherits that security model.
*
* For more information on Apex Secure by Default, see:
* https://help.salesforce.com/s/articleView?id=release-notes.rn_apex.htm&release=262&type=5
*/
public without sharing class BuyerGroupShareableURLSample extends commercebuygrp.BuyerGroupEvaluationService {

/** Maximum number of buyer groups that can be associated with a single user request. */
private static final Integer MAX_BUYER_GROUPS = 30;

/**
* Retrieves buyer group IDs for a user, including:
* - Default buyer groups (account, market, data cloud segments).
* - Region-based buyer groups (if region parameter is provided).
*
* @param request The {@link commercebuygrp.BuyerGroupRequest} containing context parameters.
* @return A {@link commercebuygrp.BuyerGroupResponse} with buyer group IDs or an error if the limit is exceeded.
*/
public override commercebuygrp.BuyerGroupResponse getBuyerGroupIds(commercebuygrp.BuyerGroupRequest request) {
// Extract context parameters from the incoming request
Map<String, Object> requestParameters = request.getRequestContextParameters();

// Retrieve the custom region parameter passed via shareable URL (e.g., &region=asia)
String region = (String) requestParameters.get('region');

// Get default out-of-the-box buyer groups using base implementation
commercebuygrp.BuyerGroupResponse defaultBuyerGroupResponse = super.getBuyerGroupIds(request);
Set<String> buyerGroupIds = new Set<String>(defaultBuyerGroupResponse.getBuyerGroupIds());

// If region is provided and equals "asia", add region-specific buyer groups
if (region != null && region.equalsIgnoreCase('asia')) {
// Add logic to fetch additional buyer groups for Asia region.
// Example: buyerGroupIds.addAll(getRegionSpecificGroups(region));
}

// Enforce maximum limit for buyer groups
if (buyerGroupIds.size() > MAX_BUYER_GROUPS) {
// Create error response when limit exceeds
commercebuygrp.BuyerGroupResponse response = new commercebuygrp.BuyerGroupResponse();
String errorMessage = 'More than ' + MAX_BUYER_GROUPS + ' buyer groups retrieved for the user. Contact Store Administrator.';
response.setError(errorMessage, errorMessage);
return response;
}


// Return final response with allowed buyer group IDs
return new commercebuygrp.BuyerGroupResponse(buyerGroupIds);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>65.0</apiVersion>
<status>Active</status>
</ApexClass>
Loading